Files
2024-01-08 09:30:50 +08:00

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"
}
};
}
}