531 lines
23 KiB
C#
531 lines
23 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics;
|
|
using System.IO;
|
|
using System.IO.Compression;
|
|
using System.Reflection;
|
|
using System.Security.Cryptography;
|
|
using System.Text;
|
|
using Autodesk.Revit.DB;
|
|
using KGdev.BI3D.Revit.Common;
|
|
using KGdev.BI3D.Revit.Common.Models;
|
|
using Newtonsoft.Json;
|
|
|
|
namespace KGdev.BI3D.Revit.ExporterV2
|
|
{
|
|
public class Exporter : IExporter
|
|
{
|
|
public List<IOptionDefinition> Options
|
|
{
|
|
get { return new List<IOptionDefinition>(this.options); }
|
|
}
|
|
|
|
public string Description
|
|
{
|
|
get { return "Export all objects visible in the active view to 3DBI."; }
|
|
}
|
|
|
|
public Exporter(
|
|
IBI3DViewsProvider viewsProvider,
|
|
IGlobalStore globalStore,
|
|
ILinkedDocumentsUtilities linkedDocumentsUtilities,
|
|
//IAuthProvider authProvider,
|
|
IElementIdProvider elementIdProvider
|
|
)
|
|
{
|
|
this.viewsProvider = viewsProvider;
|
|
this.globalStore = globalStore;
|
|
this.linkedDocumentsUtilities = linkedDocumentsUtilities;
|
|
//this.authProvider = authProvider;
|
|
this.elementIdProvider = elementIdProvider;
|
|
}
|
|
|
|
public Dictionary<string, LinkedElementIdPath> Export(
|
|
View3D objectsView,
|
|
string path,
|
|
Dictionary<string, object> optionValues
|
|
)
|
|
{
|
|
//if (!this.authProvider.ValidateToken(this.globalStore.GetToken()))
|
|
//{
|
|
// throw new Exception("Failed to authorize.");
|
|
//}
|
|
Document document = objectsView.Document;
|
|
GeometryRetrieverResult geometryRetrieverResult = new GeometryRetrieverResult();
|
|
Transform transform = Transform.Identity;
|
|
if (optionValues.ContainsKey("origin_provider"))
|
|
{
|
|
string text = optionValues["origin_provider"].ToString();
|
|
bool flag4 = "project_basepoint" == text;
|
|
if (flag4)
|
|
{
|
|
Element element = new FilteredElementCollector(document)
|
|
.OfCategory(BuiltInCategory.OST_ProjectBasePoint)
|
|
.FirstElement();
|
|
bool flag5 = element != null;
|
|
if (flag5)
|
|
{
|
|
BoundingBoxXYZ boundingBoxXYZ = element.get_BoundingBox(objectsView);
|
|
XYZ min = boundingBoxXYZ.Min;
|
|
transform = Transform.CreateTranslation(min.Multiply(-1.0));
|
|
}
|
|
}
|
|
}
|
|
bool flag6 = optionValues.ContainsKey("export_context");
|
|
if (flag6)
|
|
{
|
|
if ((bool)optionValues["export_context"])
|
|
{
|
|
View3D contextView3D = this.viewsProvider.GetContextView3D(document);
|
|
bool flag9 = contextView3D != null;
|
|
if (flag9)
|
|
{
|
|
GeometryRetriever geometryRetriever = new GeometryRetriever(
|
|
document,
|
|
false,
|
|
transform,
|
|
geometryRetrieverResult,
|
|
this.elementIdProvider
|
|
);
|
|
new CustomExporter(document, geometryRetriever)
|
|
{
|
|
ShouldStopOnError = false
|
|
}.Export(new List<ElementId> { contextView3D.Id });
|
|
}
|
|
}
|
|
}
|
|
GeometryRetriever geometryRetriever2 = new GeometryRetriever(
|
|
document,
|
|
true,
|
|
transform,
|
|
geometryRetrieverResult,
|
|
this.elementIdProvider
|
|
);
|
|
new CustomExporter(document, geometryRetriever2) { ShouldStopOnError = false }.Export(
|
|
new List<ElementId> { objectsView.Id }
|
|
);
|
|
if (optionValues.ContainsKey("include_context_rooms"))
|
|
{
|
|
if ((bool)optionValues["include_context_rooms"])
|
|
{
|
|
RoomGeometryRetriever roomGeometryRetriever = new RoomGeometryRetriever();
|
|
IList<LinkedDocumentInformation> linkedDocuments =
|
|
this.linkedDocumentsUtilities.GetLinkedDocuments(
|
|
document,
|
|
transform,
|
|
true,
|
|
new List<ElementId>()
|
|
);
|
|
foreach (LinkedDocumentInformation linkedDocumentInformation in linkedDocuments)
|
|
{
|
|
roomGeometryRetriever.Start(
|
|
linkedDocumentInformation.Document,
|
|
false,
|
|
linkedDocumentInformation.TransformToRoot,
|
|
geometryRetrieverResult,
|
|
this.elementIdProvider,
|
|
linkedDocumentInformation.PassedLinkInstanceIds
|
|
);
|
|
}
|
|
}
|
|
}
|
|
if (optionValues.ContainsKey("include_business_rooms"))
|
|
{
|
|
if ((bool)optionValues["include_business_rooms"])
|
|
{
|
|
RoomGeometryRetriever roomGeometryRetriever2 = new RoomGeometryRetriever();
|
|
IList<LinkedDocumentInformation> linkedDocuments2 =
|
|
this.linkedDocumentsUtilities.GetLinkedDocuments(
|
|
document,
|
|
transform,
|
|
true,
|
|
new List<ElementId>()
|
|
);
|
|
foreach (
|
|
LinkedDocumentInformation linkedDocumentInformation2 in linkedDocuments2
|
|
)
|
|
{
|
|
roomGeometryRetriever2.Start(
|
|
linkedDocumentInformation2.Document,
|
|
true,
|
|
linkedDocumentInformation2.TransformToRoot,
|
|
geometryRetrieverResult,
|
|
this.elementIdProvider,
|
|
linkedDocumentInformation2.PassedLinkInstanceIds
|
|
);
|
|
}
|
|
}
|
|
}
|
|
using (MemoryStream memoryStream = new MemoryStream())
|
|
{
|
|
byte[] bytes = Encoding.UTF8.GetBytes("3dbi");
|
|
memoryStream.Write(bytes, 0, bytes.Length);
|
|
byte[] bytes2 = BitConverter.GetBytes(2U);
|
|
bool isLittleEndian = BitConverter.IsLittleEndian;
|
|
if (isLittleEndian)
|
|
{
|
|
Array.Reverse(bytes2);
|
|
}
|
|
memoryStream.Write(bytes2, 0, bytes2.Length);
|
|
long num = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
|
|
byte[] bytes3 = BitConverter.GetBytes((uint)num);
|
|
bool isLittleEndian2 = BitConverter.IsLittleEndian;
|
|
if (isLittleEndian2)
|
|
{
|
|
Array.Reverse(bytes3);
|
|
}
|
|
memoryStream.Write(bytes3, 0, bytes3.Length);
|
|
//int num2 = this.authProvider.LicenseTypeInt(this.globalStore.GetToken());
|
|
//byte[] bytes4 = BitConverter.GetBytes((uint)num2);
|
|
//bool isLittleEndian3 = BitConverter.IsLittleEndian;
|
|
//if (isLittleEndian3)
|
|
//{
|
|
// Array.Reverse(bytes4);
|
|
//}
|
|
//memoryStream.Write(bytes4, 0, bytes4.Length);
|
|
byte[] bytes5 = BitConverter.GetBytes((uint)geometryRetrieverResult.Ids.Count);
|
|
bool isLittleEndian4 = BitConverter.IsLittleEndian;
|
|
if (isLittleEndian4)
|
|
{
|
|
Array.Reverse(bytes5);
|
|
}
|
|
memoryStream.Write(bytes5, 0, bytes5.Length);
|
|
foreach (string text2 in geometryRetrieverResult.Ids)
|
|
{
|
|
byte[] bytes6 = Encoding.UTF8.GetBytes(text2);
|
|
byte[] bytes7 = BitConverter.GetBytes((uint)bytes6.Length);
|
|
bool isLittleEndian5 = BitConverter.IsLittleEndian;
|
|
if (isLittleEndian5)
|
|
{
|
|
Array.Reverse(bytes7);
|
|
}
|
|
memoryStream.Write(bytes7, 0, bytes7.Length);
|
|
memoryStream.Write(bytes6, 0, bytes6.Length);
|
|
}
|
|
string text3 = Convert.ToBase64String(memoryStream.ToArray());
|
|
SHA512Managed sha512Managed = new SHA512Managed();
|
|
byte[] array = sha512Managed.ComputeHash(Encoding.UTF8.GetBytes(text3));
|
|
HasherInput hasherInput = new HasherInput
|
|
{
|
|
Token = this.globalStore.GetToken(),
|
|
HexSha512Hash = BitConverter.ToString(array).Replace("-", "")
|
|
};
|
|
string text4 = Path.Combine(
|
|
this.globalStore.GetAppTempDirectoryPath(),
|
|
"v1hin.temp"
|
|
);
|
|
string text5 = JsonConvert.SerializeObject(hasherInput);
|
|
File.WriteAllText(text4, text5);
|
|
string text6 = "";
|
|
using (Process process = new Process())
|
|
{
|
|
process.StartInfo.FileName =
|
|
"\""
|
|
+ Path.Combine(
|
|
Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location),
|
|
"KGdev.BI3D.Hasher.V1.exe"
|
|
)
|
|
+ "\"";
|
|
process.StartInfo.Arguments = string.Format(
|
|
"\"{0}\"",
|
|
text4.Replace("\\\\", "/")
|
|
);
|
|
process.StartInfo.UseShellExecute = false;
|
|
process.StartInfo.RedirectStandardOutput = true;
|
|
process.Start();
|
|
text6 = process.StandardOutput.ReadToEnd();
|
|
process.WaitForExit();
|
|
}
|
|
string[] array2 = text6.Split(
|
|
new string[] { "signature:" },
|
|
StringSplitOptions.None
|
|
);
|
|
bool flag16 = array2.Length != 2;
|
|
if (flag16)
|
|
{
|
|
throw new Exception(text6);
|
|
}
|
|
text6 = array2[1];
|
|
byte[] bytes8 = BitConverter.GetBytes((uint)text6.Length);
|
|
bool isLittleEndian6 = BitConverter.IsLittleEndian;
|
|
if (isLittleEndian6)
|
|
{
|
|
Array.Reverse(bytes8);
|
|
}
|
|
memoryStream.Write(bytes8, 0, bytes8.Length);
|
|
byte[] bytes9 = Encoding.UTF8.GetBytes(text6);
|
|
memoryStream.Write(bytes9, 0, bytes9.Length);
|
|
byte[] bytes10 = BitConverter.GetBytes((uint)geometryRetrieverResult.Colors.Count);
|
|
bool isLittleEndian7 = BitConverter.IsLittleEndian;
|
|
if (isLittleEndian7)
|
|
{
|
|
Array.Reverse(bytes10);
|
|
}
|
|
memoryStream.Write(bytes10, 0, bytes10.Length);
|
|
foreach (RGBA rgba in geometryRetrieverResult.Colors)
|
|
{
|
|
byte[] array3 = new byte[] { rgba.R, rgba.G, rgba.B, rgba.A };
|
|
memoryStream.Write(array3, 0, 4);
|
|
}
|
|
byte[] bytes11 = BitConverter.GetBytes(
|
|
(uint)geometryRetrieverResult.Positions.Count
|
|
);
|
|
bool isLittleEndian8 = BitConverter.IsLittleEndian;
|
|
if (isLittleEndian8)
|
|
{
|
|
Array.Reverse(bytes11);
|
|
}
|
|
memoryStream.Write(bytes11, 0, bytes11.Length);
|
|
foreach (Position position in geometryRetrieverResult.Positions)
|
|
{
|
|
float[] array4 = new float[] { position.X, position.Y, position.Z };
|
|
foreach (float num3 in array4)
|
|
{
|
|
byte[] bytes12 = BitConverter.GetBytes(num3);
|
|
bool isLittleEndian9 = BitConverter.IsLittleEndian;
|
|
if (isLittleEndian9)
|
|
{
|
|
Array.Reverse(bytes12);
|
|
}
|
|
memoryStream.Write(bytes12, 0, bytes12.Length);
|
|
}
|
|
}
|
|
byte[] bytes13 = BitConverter.GetBytes((uint)geometryRetrieverResult.Indices.Count);
|
|
bool isLittleEndian10 = BitConverter.IsLittleEndian;
|
|
if (isLittleEndian10)
|
|
{
|
|
Array.Reverse(bytes13);
|
|
}
|
|
memoryStream.Write(bytes13, 0, bytes13.Length);
|
|
foreach (int num4 in geometryRetrieverResult.Indices)
|
|
{
|
|
byte[] bytes14 = BitConverter.GetBytes(num4);
|
|
bool isLittleEndian11 = BitConverter.IsLittleEndian;
|
|
if (isLittleEndian11)
|
|
{
|
|
Array.Reverse(bytes14);
|
|
}
|
|
memoryStream.Write(bytes14, 0, bytes14.Length);
|
|
}
|
|
byte[] bytes15 = BitConverter.GetBytes(
|
|
(uint)geometryRetrieverResult.ColorIndices.Count
|
|
);
|
|
bool isLittleEndian12 = BitConverter.IsLittleEndian;
|
|
if (isLittleEndian12)
|
|
{
|
|
Array.Reverse(bytes15);
|
|
}
|
|
memoryStream.Write(bytes15, 0, bytes15.Length);
|
|
foreach (uint num5 in geometryRetrieverResult.ColorIndices)
|
|
{
|
|
byte[] bytes16 = BitConverter.GetBytes(num5);
|
|
bool isLittleEndian13 = BitConverter.IsLittleEndian;
|
|
if (isLittleEndian13)
|
|
{
|
|
Array.Reverse(bytes16);
|
|
}
|
|
memoryStream.Write(bytes16, 0, bytes16.Length);
|
|
}
|
|
byte[] bytes17 = BitConverter.GetBytes(
|
|
(uint)geometryRetrieverResult.IdIndices.Count
|
|
);
|
|
bool isLittleEndian14 = BitConverter.IsLittleEndian;
|
|
if (isLittleEndian14)
|
|
{
|
|
Array.Reverse(bytes17);
|
|
}
|
|
memoryStream.Write(bytes17, 0, bytes17.Length);
|
|
foreach (uint num6 in geometryRetrieverResult.IdIndices)
|
|
{
|
|
byte[] bytes18 = BitConverter.GetBytes(num6);
|
|
bool isLittleEndian15 = BitConverter.IsLittleEndian;
|
|
if (isLittleEndian15)
|
|
{
|
|
Array.Reverse(bytes18);
|
|
}
|
|
memoryStream.Write(bytes18, 0, bytes18.Length);
|
|
}
|
|
bool flag17 =
|
|
optionValues.ContainsKey("include_scenes")
|
|
&& (bool)optionValues["include_scenes"];
|
|
if (flag17)
|
|
{
|
|
List<View3D> scenes = this.viewsProvider.GetScenes(document);
|
|
byte[] bytes19 = BitConverter.GetBytes((uint)scenes.Count);
|
|
bool isLittleEndian16 = BitConverter.IsLittleEndian;
|
|
if (isLittleEndian16)
|
|
{
|
|
Array.Reverse(bytes19);
|
|
}
|
|
memoryStream.Write(bytes19, 0, bytes19.Length);
|
|
foreach (View3D view3D in scenes)
|
|
{
|
|
string sceneName = this.viewsProvider.GetSceneName(view3D);
|
|
byte[] bytes20 = Encoding.UTF8.GetBytes(sceneName);
|
|
byte[] bytes21 = BitConverter.GetBytes((uint)bytes20.Length);
|
|
bool isLittleEndian17 = BitConverter.IsLittleEndian;
|
|
if (isLittleEndian17)
|
|
{
|
|
Array.Reverse(bytes21);
|
|
}
|
|
memoryStream.Write(bytes21, 0, bytes21.Length);
|
|
memoryStream.Write(bytes20, 0, bytes20.Length);
|
|
ViewOrientation3D orientation = view3D.GetOrientation();
|
|
Position position2 = orientation.EyePosition.To3DBIPosition();
|
|
Position position3 = (
|
|
orientation.EyePosition + orientation.ForwardDirection * 82.0
|
|
).To3DBIPosition();
|
|
float[] array6 = new float[]
|
|
{
|
|
position2.X,
|
|
position2.Y,
|
|
position2.Z,
|
|
position3.X,
|
|
position3.Y,
|
|
position3.Z
|
|
};
|
|
foreach (float num7 in array6)
|
|
{
|
|
byte[] bytes22 = BitConverter.GetBytes(num7);
|
|
bool isLittleEndian18 = BitConverter.IsLittleEndian;
|
|
if (isLittleEndian18)
|
|
{
|
|
Array.Reverse(bytes22);
|
|
}
|
|
memoryStream.Write(bytes22, 0, bytes22.Length);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
byte[] bytes23 = BitConverter.GetBytes(0U);
|
|
bool isLittleEndian19 = BitConverter.IsLittleEndian;
|
|
if (isLittleEndian19)
|
|
{
|
|
Array.Reverse(bytes23);
|
|
}
|
|
memoryStream.Write(bytes23, 0, bytes23.Length);
|
|
}
|
|
using (FileStream fileStream = new FileStream(path, FileMode.OpenOrCreate))
|
|
{
|
|
using (
|
|
ZipArchive zipArchive = new ZipArchive(
|
|
fileStream,
|
|
ZipArchiveMode.Create,
|
|
false
|
|
)
|
|
)
|
|
{
|
|
ZipArchiveEntry zipArchiveEntry = zipArchive.CreateEntry("v2.3dbi");
|
|
using (Stream stream = zipArchiveEntry.Open())
|
|
{
|
|
memoryStream.Position = 0L;
|
|
memoryStream.CopyTo(stream);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return geometryRetrieverResult.ExportedElementIdPathById;
|
|
}
|
|
|
|
private const string HASHER_INPUT_FILE_NAME = "v1hin.temp";
|
|
|
|
private const string FILE_HEADER = "3dbi";
|
|
|
|
private const uint FILE_VERSION = 2U;
|
|
|
|
private const string ZIP_ENTRY_NAME = "v2.3dbi";
|
|
|
|
private const string HASHER_EXECUTABLE_NAME = "KGdev.BI3D.Hasher.V1.exe";
|
|
|
|
private const string OPTION_ID_EXPORT_CONTEXT = "export_context";
|
|
|
|
private const string OPTION_ID_INCLUDE_CONTEXT_ROOMS = "include_context_rooms";
|
|
|
|
private const string OPTION_ID_INCLUDE_BUSINESS_ROOMS = "include_business_rooms";
|
|
|
|
private const string OPTION_ID_INCLUDE_SCENES = "include_scenes";
|
|
|
|
private const string OPTION_ID_ORIGIN_PROVIDER = "origin_provider";
|
|
|
|
private const string OPTION_SELECT_VALUE_ID_DEFAULT_ORIGIN = "default_origin";
|
|
|
|
private const string OPTION_SELECT_VALUE_ID_PROJECT_BASEPOINT = "project_basepoint";
|
|
|
|
private const string DESCRIPTION = "Export all objects visible in the active view to 3DBI.";
|
|
|
|
private const double SCENES_TARGET_DISTANCE_FEET = 82.0;
|
|
|
|
private readonly IBI3DViewsProvider viewsProvider;
|
|
|
|
private readonly IGlobalStore globalStore;
|
|
|
|
private readonly ILinkedDocumentsUtilities linkedDocumentsUtilities;
|
|
|
|
//private readonly IAuthProvider authProvider;
|
|
|
|
private readonly IElementIdProvider elementIdProvider;
|
|
|
|
private List<IOptionDefinition> options = new List<IOptionDefinition>
|
|
{
|
|
new OptionDefinition
|
|
{
|
|
Id = "export_context",
|
|
OptionValueType = OptionValueType.BOOLEAN,
|
|
Label = "Export Context",
|
|
Description =
|
|
"Export objects that are visible in the \"3DBI-Context\" view as Context Objects. Context Objects are static objects that are always visible.",
|
|
DefaultValue = true
|
|
},
|
|
new OptionDefinition
|
|
{
|
|
Id = "include_business_rooms",
|
|
OptionValueType = OptionValueType.BOOLEAN,
|
|
Label = "Include Rooms & Spaces",
|
|
Description =
|
|
"Export rooms and spaces as Business Objects. All rooms in the active document will be exported and have their Element Id assigned as Object Identifier.",
|
|
DefaultValue = true
|
|
},
|
|
new OptionDefinition
|
|
{
|
|
Id = "include_context_rooms",
|
|
OptionValueType = OptionValueType.BOOLEAN,
|
|
Label = "Include Rooms & Spaces as Context",
|
|
Description =
|
|
"Export rooms and spaces as Context Objects. Context Objects are static objects that are always visible.",
|
|
DefaultValue = false
|
|
},
|
|
new OptionDefinition
|
|
{
|
|
Id = "include_scenes",
|
|
OptionValueType = OptionValueType.BOOLEAN,
|
|
Label = "Export Scenes",
|
|
Description =
|
|
"Export camera positions of all perspective views with a \"3DBI_\" prefix in their name as 3dbi scenes.",
|
|
DefaultValue = false
|
|
},
|
|
new OptionDefinition
|
|
{
|
|
Id = "origin_provider",
|
|
OptionValueType = OptionValueType.SELECT,
|
|
Label = "Model Origin",
|
|
Description = "Specify which origin (point 0, 0, 0) to use.",
|
|
PossibleValues = new List<ISelectOptionDefinitionValue>
|
|
{
|
|
new SelectOptionDefinitionValue
|
|
{
|
|
Value = "default_origin",
|
|
Label = "Default Origin"
|
|
},
|
|
new SelectOptionDefinitionValue
|
|
{
|
|
Value = "project_basepoint",
|
|
Label = "Project Basepoint"
|
|
}
|
|
},
|
|
DefaultValue = "default_origin"
|
|
}
|
|
};
|
|
}
|
|
}
|