diff --git a/20210129/doc/zxq/NwGeoExporter/NwGeoExporter/CustomExporter.cs b/20210129/doc/zxq/NwGeoExporter/NwGeoExporter/CustomExporter.cs index ec2be8b..4c995a5 100644 --- a/20210129/doc/zxq/NwGeoExporter/NwGeoExporter/CustomExporter.cs +++ b/20210129/doc/zxq/NwGeoExporter/NwGeoExporter/CustomExporter.cs @@ -11,28 +11,34 @@ namespace NwGeoExporter { public class CustomExporter : InwSimplePrimitivesCB { - private TransformM transform3D; + //private TransformM transform3D; public CustomExporter() { Triangles = new List(); } - public CustomExporter(TransformM transform3D):this() - { - this.transform3D = transform3D; - } + //public CustomExporter(TransformM transform3D):this() + //{ + // this.transform3D = transform3D; + //} public List Triangles { get; set; } public void Triangle(InwSimpleVertex v1, InwSimpleVertex v2, InwSimpleVertex v3) { + //var vertices = new PointM[] + // { + // transform3D.OfPoint(new PointM(v1)), + // transform3D.OfPoint(new PointM(v2)), + // transform3D.OfPoint(new PointM(v3)), + // }; var vertices = new PointM[] - { - transform3D.OfPoint(new PointM(v1)), - transform3D.OfPoint(new PointM(v2)), - transform3D.OfPoint(new PointM(v3)), - }; + { + new PointM(v1), + new PointM(v2), + new PointM(v3), + }; var normals = new VectorM[] { new VectorM(v1), @@ -40,7 +46,7 @@ namespace NwGeoExporter new VectorM(v3), }; //Triangles.Add(new Triangle(v1,v2,v3)); - Triangles.Add(new Triangle(normals,vertices)); + Triangles.Add(new Triangle(normals, vertices)); } public void Line(InwSimpleVertex v1, InwSimpleVertex v2) diff --git a/20210129/doc/zxq/NwGeoExporter/NwGeoExporter/Models/Instance.cs b/20210129/doc/zxq/NwGeoExporter/NwGeoExporter/Models/Instance.cs index eb101a5..92152cb 100644 --- a/20210129/doc/zxq/NwGeoExporter/NwGeoExporter/Models/Instance.cs +++ b/20210129/doc/zxq/NwGeoExporter/NwGeoExporter/Models/Instance.cs @@ -22,24 +22,8 @@ namespace NwGeoExporter.Models [JsonIgnore] public TransformM Transform { get; set; } - ///// - ///// 转换-序列化(列主序) - ///// - //public double[] transform - //{ - // get - // { - // return new double[] - // { - // Transform.BasicX.X,Transform.BasicX.Y,Transform.BasicX.Z,0 - // ,Transform.BasicY.X,Transform.BasicY.Y,Transform.BasicY.Z,0 - // ,Transform.BasicZ.X,Transform.BasicZ.Y,Transform.BasicZ.Z,0 - // ,Transform.Origin.X,Transform.Origin.Y,Transform.Origin.Z,1 - // }; - // } - //} /// - /// 转换-序列化(行主序) + /// 转换-序列化(列主序) /// public double[] transform { @@ -50,10 +34,11 @@ namespace NwGeoExporter.Models Transform.BasicX.X,Transform.BasicX.Y,Transform.BasicX.Z,0 ,Transform.BasicY.X,Transform.BasicY.Y,Transform.BasicY.Z,0 ,Transform.BasicZ.X,Transform.BasicZ.Y,Transform.BasicZ.Z,0 - ,Transform.Origin.X,Transform.Origin.Y,Transform.Origin.Z,1 + ,Transform.Origin.X.Feet2Mm(),Transform.Origin.Y.Feet2Mm(),Transform.Origin.Z.Feet2Mm(),1 }; } } + /// /// 是否可见 /// diff --git a/20210129/doc/zxq/NwGeoExporter/NwGeoExporter/Models/Mesh.cs b/20210129/doc/zxq/NwGeoExporter/NwGeoExporter/Models/Mesh.cs index 2d6e2d7..27e5622 100644 --- a/20210129/doc/zxq/NwGeoExporter/NwGeoExporter/Models/Mesh.cs +++ b/20210129/doc/zxq/NwGeoExporter/NwGeoExporter/Models/Mesh.cs @@ -15,7 +15,7 @@ namespace NwGeoExporter.Models /// 顶点数组-序列化数据 /// public double[] vertices { get => VerticeList.SelectMany(x => new List { x.X.Feet2Mm(), x.Y.Feet2Mm(), x.Z.Feet2Mm() }).ToArray(); } - //public double[] vertices { get => VerticeList.SelectMany(x => new List { x.X, x.Y, x.Z }).ToArray(); } + /// /// 顶点索引-序列化数据 /// @@ -71,35 +71,63 @@ namespace NwGeoExporter.Models { for (int i = 0; i < triangle.Vertices.Length; i++) { - // bool isHandle = false; - // for (int j = 0; j < VerticeList.Count; j++) - // { - // if (VerticeList[j] == triangle.vertices[i]) - // { - // //拿到索引集合中与当前顶点值一样的索引 - // List indexList = IndiceList.FindIndexs(x => x == j); + bool isHandle = false; + //相同的顶点位置的索引 + List indexList = VerticeList.FindIndexs(x => x == triangle.Vertices[i]); + //当前三角面片顶点法向 + VectorM currentVector = triangle.Normals[i]; + //最后一次合并的索引 + int lastMergeIndex = 0; + while (indexList.Count != 0) + { + //判断索引内是否需要合并的顶点 + var index = indexList.FindIndex(x => NormalList[x].AngelTo(currentVector).ToAngle() - 90 > 0.1); + if (index == -1) + { + break; + } + else if (!isHandle)//第一次 + { + NormalList[indexList[index]] = (currentVector + NormalList[indexList[index]]).Normalize(); + currentVector = NormalList[indexList[index]]; + lastMergeIndex = indexList[index]; + indexList.RemoveAt(index); + isHandle = true; + } + else//原来顶点位置一致的与合并后的顶点进行比较 + { + int removeIndex = Math.Max(lastMergeIndex, indexList[index]); + lastMergeIndex = Math.Min(lastMergeIndex, indexList[index]); - // //TODO:考虑多个的情况 - // //第几个需要跟当前顶点法向进行平均 - // int index = indexList.FindIndex(x => NormalList[x] - // .AngelTo(triangle.normals[i]).ToAngle() - 90 > 0.1); - // //有遇到顶点法线平均 - // if (index != -1) - // { - // NormalList[j] = (triangle.normals[i] + NormalList[j]).Normalize(); - // isHandle = true; - // break; - // } - // } - // } - // if (!isHandle) - // { - //添加顶点以及顶点法向以及对应的索引 - VerticeList.Add(triangle.Vertices[i]); - NormalList.Add(triangle.Normals[i]); - IndiceList.Add(VerticeList.Count - 1); + //重置索引 + for (int k = 0; k < IndiceList.Count; k++) + { + if (IndiceList[k] > removeIndex) + { + IndiceList[k]--; + } + else if (IndiceList[k] == removeIndex) + { + IndiceList[k] = lastMergeIndex; + } + } + + //删除不需要的顶点和法向 + NormalList.RemoveAt(removeIndex); + VerticeList.RemoveAt(removeIndex); + } + } + if (!isHandle) + { + //添加顶点以及顶点法向以及对应的索引 + VerticeList.Add(triangle.Vertices[i]); + NormalList.Add(triangle.Normals[i]); + IndiceList.Add(VerticeList.Count - 1); + }else + { + IndiceList.Add(lastMergeIndex); + } } - //} } public void AddTriangles(IEnumerable triangles) diff --git a/20210129/doc/zxq/NwGeoExporter/NwGeoExporter/Models/PointM.cs b/20210129/doc/zxq/NwGeoExporter/NwGeoExporter/Models/PointM.cs index 59630fe..ba3fab8 100644 --- a/20210129/doc/zxq/NwGeoExporter/NwGeoExporter/Models/PointM.cs +++ b/20210129/doc/zxq/NwGeoExporter/NwGeoExporter/Models/PointM.cs @@ -42,7 +42,7 @@ namespace NwGeoExporter.Models { if (obj is PointM pm) { - if (pm.X.Round(6) == X.Round(6) && pm.Y.Round(6) == Y.Round(6) && pm.Z.Round(6) == Z.Round(6)) + if (pm.X.Round(4) == X.Round(4) && pm.Y.Round(4) == Y.Round(4) && pm.Z.Round(4) == Z.Round(4)) return true; } return false; diff --git a/20210129/doc/zxq/NwGeoExporter/NwGeoExporter/Models/TransformM.cs b/20210129/doc/zxq/NwGeoExporter/NwGeoExporter/Models/TransformM.cs index 4919be4..a449099 100644 --- a/20210129/doc/zxq/NwGeoExporter/NwGeoExporter/Models/TransformM.cs +++ b/20210129/doc/zxq/NwGeoExporter/NwGeoExporter/Models/TransformM.cs @@ -27,7 +27,7 @@ namespace NwGeoExporter.Models Origin = new PointM(), }; } - private InwLTransform3f3 inwTransform; + //private InwLTransform3f3 inwTransform; private TransformM() { @@ -44,31 +44,31 @@ namespace NwGeoExporter.Models BasicY = new VectorM(matrixElements[4], matrixElements[5], matrixElements[6]); BasicZ = new VectorM(matrixElements[8], matrixElements[9], matrixElements[10]); Origin = new PointM(matrixElements[12], matrixElements[13], matrixElements[14]); - this.inwTransform = inwTransform; - } - public PointM OfPoint(PointM point) - { - double[] matrixElements = ((Array)(object)inwTransform.Matrix).ToArray(); - double x = point.X; - double y = point.Y; - double z = point.Z; - double w = matrixElements[3] * x + matrixElements[7] * y + matrixElements[11] * z + matrixElements[15]; - return new PointM( - (matrixElements[0] * x + matrixElements[4] * y + matrixElements[8] * z + matrixElements[12]) / w, - (matrixElements[1] * x + matrixElements[5] * y + matrixElements[9] * z + matrixElements[13]) / w, - (matrixElements[2] * x + matrixElements[6] * y + matrixElements[10] * z + matrixElements[14]) / w); + //this.inwTransform = inwTransform; } //public PointM OfPoint(PointM point) //{ + // double[] matrixElements = ((Array)(object)inwTransform.Matrix).ToArray(); // double x = point.X; // double y = point.Y; // double z = point.Z; - // return - // new PointM( - // BasicX.X * x + BasicY.X * y + BasicZ.X * z + Origin.X, - // BasicX.Y * x + BasicY.Y * y + BasicZ.Y * z + Origin.Y, - // BasicX.Z * x + BasicY.Z * y + BasicZ.Z * z + Origin.Z - // ); + // double w = matrixElements[3] * x + matrixElements[7] * y + matrixElements[11] * z + matrixElements[15]; + // return new PointM( + //(matrixElements[0] * x + matrixElements[4] * y + matrixElements[8] * z + matrixElements[12]) / w, + //(matrixElements[1] * x + matrixElements[5] * y + matrixElements[9] * z + matrixElements[13]) / w, + //(matrixElements[2] * x + matrixElements[6] * y + matrixElements[10] * z + matrixElements[14]) / w); //} + public PointM OfPoint(PointM point) + { + double x = point.X; + double y = point.Y; + double z = point.Z; + return + new PointM( + BasicX.X * x + BasicY.X * y + BasicZ.X * z + Origin.X, + BasicX.Y * x + BasicY.Y * y + BasicZ.Y * z + Origin.Y, + BasicX.Z * x + BasicY.Z * y + BasicZ.Z * z + Origin.Z + ); + } } } diff --git a/20210129/doc/zxq/NwGeoExporter/NwGeoExporter/NwEx/IEnumerableEx.cs b/20210129/doc/zxq/NwGeoExporter/NwGeoExporter/NwEx/IEnumerableEx.cs index 460ae66..7257f56 100644 --- a/20210129/doc/zxq/NwGeoExporter/NwGeoExporter/NwEx/IEnumerableEx.cs +++ b/20210129/doc/zxq/NwGeoExporter/NwGeoExporter/NwEx/IEnumerableEx.cs @@ -1,4 +1,5 @@ -using System; +using Autodesk.Navisworks.Api; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -41,7 +42,20 @@ namespace NwGeoExporter.NwEx } return -1; } - + /// + /// 转ModelItemCollection + /// + /// + /// + public static ModelItemCollection ToCollection(this IEnumerable items) + { + ModelItemCollection collection = new ModelItemCollection(); + foreach (var it in items) + { + collection.Add(it); + } + return collection; + } /// /// 找到所有的索引 /// @@ -61,7 +75,7 @@ namespace NwGeoExporter.NwEx indexList.Add(i); } } - return indexList.Count == 0 ? null : indexList; + return indexList.Count == 0 ? new List() : indexList; } } } diff --git a/20210129/doc/zxq/NwGeoExporter/NwGeoExporter/NwExporterPlugin.cs b/20210129/doc/zxq/NwGeoExporter/NwGeoExporter/NwExporterPlugin.cs index 58f9de9..17ff1aa 100644 --- a/20210129/doc/zxq/NwGeoExporter/NwGeoExporter/NwExporterPlugin.cs +++ b/20210129/doc/zxq/NwGeoExporter/NwGeoExporter/NwExporterPlugin.cs @@ -42,6 +42,11 @@ namespace NwGeoExporter //获取项目树中的子项 var modelItemColl = ModelItemUtils.GetModelItems(doc); + //分组(子项中有相同几何数据的分为一组) + var itemGroup = modelItemColl.GroupBy(x => x, new BaseComparer((x, y) => x.IsSameInstance(y))).Select(x => x.ToList()).ToList(); + + //取其中一个 + modelItemColl = itemGroup.Select(x => x.First()).ToCollection(); //转换成选择集 COMApi.InwOpSelection selItemColl = ComBridge.ToInwOpSelection(modelItemColl); @@ -51,88 +56,91 @@ namespace NwGeoExporter { //是否是可载入族 bool isInstance = ModelItemUtils.IsRevitInstance(modelItemColl[index].Parent.Parent); - - #region 查找Mesh材质 - //材质属性 - var material = GetMaterial(modelItemColl[index].Parent); - //查找材质索引 - int matIndex = materialList.FindIndex(x => x.Equals(material)); - if (matIndex == -1) - { - materialList.Add(material); - matIndex = materialList.Count - 1; - } - #endregion - - #region Revit元素属性 - Dictionary elemPropertyDict = new Dictionary(); - DataPropertyCollection elemPropertyColl = null; - if (isInstance) - { - elemPropertyColl = GetDataPropertys(modelItemColl[index].Parent.Parent, PropertyCategoryName.LcRevitData_Element); - } - else - { - elemPropertyColl = GetDataPropertys(modelItemColl[index].Parent, PropertyCategoryName.LcRevitData_Element); - } - //二级是系统族获取元素属性的方法 - foreach (var elemProperty in elemPropertyColl) - { - if (!elemPropertyDict.ContainsKey(elemProperty.CombinedName.ToString())) - elemPropertyDict.Add(elemProperty.CombinedName.ToString(), GetValueString(elemProperty)); - } - #endregion - - #region 拿构件ID - string elemID = ""; - DataPropertyCollection projectPropertyColl = null; - if (isInstance) - { - projectPropertyColl = GetDataPropertys(modelItemColl[index].Parent.Parent, PropertyCategoryName.LcOaNode); - } - else - { - projectPropertyColl = GetDataPropertys(modelItemColl[index].Parent, PropertyCategoryName.LcOaNode); - } - foreach (var projectProperty in projectPropertyColl) - { - if (projectProperty.Name == "LcOaNodeGuid") - { - elemID = GetValueString(projectProperty); - } - } - #endregion - - #region 获取Mesh - Mesh mesh = new Mesh(matIndex); - TransformM transform3D = null; + Mesh mesh = null; + int instanceIndex = 0; foreach (COMApi.InwOaFragment3 frag in path.Fragments()) { - //if (transform3D == null) - //{ - InwLTransform3f3 localToWorld = (InwLTransform3f3)frag.GetLocalToWorldMatrix(); - transform3D = new TransformM(localToWorld); - //} - CustomExporter customExporter = new CustomExporter(transform3D); - // generate the primitives - frag.GenerateSimplePrimitives(COMApi.nwEVertexProperty.eNORMAL, customExporter); - mesh.AddTriangles(customExporter.Triangles); - } - meshList.Add(mesh); - #endregion + #region Revit元素属性 + Dictionary elemPropertyDict = new Dictionary(); + DataPropertyCollection elemPropertyColl = null; + if (isInstance) + { + elemPropertyColl = GetDataPropertys(itemGroup[index][instanceIndex].Parent.Parent, PropertyCategoryName.LcRevitData_Element); + } + else + { + elemPropertyColl = GetDataPropertys(itemGroup[index][instanceIndex].Parent, PropertyCategoryName.LcRevitData_Element); + } + //二级是系统族获取元素属性的方法 + foreach (var elemProperty in elemPropertyColl) + { + if (!elemPropertyDict.ContainsKey(elemProperty.CombinedName.ToString())) + elemPropertyDict.Add(elemProperty.CombinedName.ToString(), GetValueString(elemProperty)); + } + #endregion - #region 构建Instance对象 - Instance currentInstance = new Instance() - { - id = elemID, - mesh = meshList.Count - 1, - Transform = TransformM.Identify, - visible = 1.0, - info = elemPropertyDict, - }; - instanceList.Add(currentInstance); + #region 拿构件ID + string elemID = ""; + DataPropertyCollection projectPropertyColl = null; + if (isInstance) + { + projectPropertyColl = GetDataPropertys(modelItemColl[index].Parent.Parent, PropertyCategoryName.LcOaNode); + } + else + { + projectPropertyColl = GetDataPropertys(modelItemColl[index].Parent, PropertyCategoryName.LcOaNode); + } + foreach (var projectProperty in projectPropertyColl) + { + if (projectProperty.Name == "LcOaNodeGuid") + { + elemID = GetValueString(projectProperty); + } + } + #endregion + + InwLTransform3f3 localToWorld = (InwLTransform3f3)frag.GetLocalToWorldMatrix(); + var transform3D = new TransformM(localToWorld); + if (mesh == null) + { + #region 查找Mesh材质 + //材质属性 + var material = GetMaterial(modelItemColl[index].Parent); + //查找材质索引 + int matIndex = materialList.FindIndex(x => x.Equals(material)); + if (matIndex == -1) + { + materialList.Add(material); + matIndex = materialList.Count - 1; + } + #endregion + + mesh = new Mesh(matIndex); + + CustomExporter customExporter = new CustomExporter(); + // generate the primitives + frag.GenerateSimplePrimitives(COMApi.nwEVertexProperty.eNORMAL, customExporter); + mesh.AddTriangles(customExporter.Triangles); + meshList.Add(mesh); + } + #region 构建Instance对象 + Instance currentInstance = new Instance() + { + id = elemID, + mesh = meshList.Count - 1, + Transform = transform3D, + visible = 1.0, + info = elemPropertyDict, + }; + #endregion + instanceList.Add(currentInstance); + instanceIndex++; + } index++; - #endregion + + + + } NwModel model = new NwModel(instanceList, meshList, materialList); diff --git a/20210129/doc/zxq/NwGeoExporter/NwGeoExporter/NwGeoExporter.csproj b/20210129/doc/zxq/NwGeoExporter/NwGeoExporter/NwGeoExporter.csproj index 5bfae46..25265cd 100644 --- a/20210129/doc/zxq/NwGeoExporter/NwGeoExporter/NwGeoExporter.csproj +++ b/20210129/doc/zxq/NwGeoExporter/NwGeoExporter/NwGeoExporter.csproj @@ -71,6 +71,7 @@ + diff --git a/20210129/doc/zxq/NwGeoExporter/NwGeoExporter/NwUtils/BaseComparer.cs b/20210129/doc/zxq/NwGeoExporter/NwGeoExporter/NwUtils/BaseComparer.cs new file mode 100644 index 0000000..647dfef --- /dev/null +++ b/20210129/doc/zxq/NwGeoExporter/NwGeoExporter/NwUtils/BaseComparer.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace NwGeoExporter.NwUtils +{ + public class BaseComparer : IEqualityComparer + { + public BaseComparer(Func func) + { + Func = func; + } + + private Func Func { get; } + + public bool Equals(T x, T y) + { + return (bool)Func?.Invoke(x, y); + } + + public int GetHashCode(T obj) + { + return 0; + } + } +}