diff --git a/Source/Revit.IFC.Export/Toolkit/IFCInstanceExporter.cs b/Source/Revit.IFC.Export/Toolkit/IFCInstanceExporter.cs index 35285425..119a16e7 100644 --- a/Source/Revit.IFC.Export/Toolkit/IFCInstanceExporter.cs +++ b/Source/Revit.IFC.Export/Toolkit/IFCInstanceExporter.cs @@ -3925,7 +3925,7 @@ public static IFCData CreateArcIndexType(IFCFile file, IList arcIndexList) return arcIndexData; } - public static IFCAnyHandle CreateIndexedPolyCurve(IFCFile file, IFCAnyHandle coordinates, IList segmentIndexList, bool? selfIntersect) + public static IFCAnyHandle CreateIndexedPolyCurve(IFCFile file, IFCAnyHandle coordinates, IList> segmentIndexList, bool? selfIntersect) { if (coordinates == null) throw new ArgumentNullException("Points"); @@ -3936,41 +3936,7 @@ public static IFCAnyHandle CreateIndexedPolyCurve(IFCFile file, IFCAnyHandle coo IFCAnyHandle indexedPolyCurveHnd = CreateInstance(file, IFCEntityType.IfcIndexedPolyCurve, null); IFCAnyHandleUtil.SetAttribute(indexedPolyCurveHnd, "Points", coordinates); if (segmentIndexList != null) - { - IFCAggregate segments = indexedPolyCurveHnd.CreateAggregateAttribute("Segments"); - foreach (GeometryUtil.SegmentIndices segmentIndices in segmentIndexList) - { - if(segmentIndices.IsCalculated == false) - throw new ArgumentNullException("Segments"); - - IFCData segment = null; - - var polyLineIndices = segmentIndices as GeometryUtil.PolyLineIndices; - if (polyLineIndices != null) - { - segment = segments.CreateValueOfType("IfcLineIndex"); - - IFCAggregate lineIndexAggr = segment.AsAggregate(); - foreach (int index in polyLineIndices.Indices) - lineIndexAggr.Add(IFCData.CreateInteger(index)); - } - else - { - var arcIndices = segmentIndices as GeometryUtil.ArcIndices; - if (arcIndices != null) - { - segment = segments.CreateValueOfType("IfcArcIndex"); - - IFCAggregate arcIndexAggr = segment.AsAggregate(); - arcIndexAggr.Add(IFCData.CreateInteger(arcIndices.Start)); - arcIndexAggr.Add(IFCData.CreateInteger(arcIndices.Mid)); - arcIndexAggr.Add(IFCData.CreateInteger(arcIndices.End)); - } - } - segments.Add(segment); - } - } - + IFCAnyHandleUtil.SetAttribute(indexedPolyCurveHnd, "Segments", segmentIndexList, 1, null, 2, null); IFCAnyHandleUtil.SetAttribute(indexedPolyCurveHnd, "SelfIntersect", selfIntersect); return indexedPolyCurveHnd; diff --git a/Source/Revit.IFC.Export/Utility/GeometryUtil.cs b/Source/Revit.IFC.Export/Utility/GeometryUtil.cs index 68cd9cb1..5c9217fa 100644 --- a/Source/Revit.IFC.Export/Utility/GeometryUtil.cs +++ b/Source/Revit.IFC.Export/Utility/GeometryUtil.cs @@ -91,263 +91,6 @@ public override int GetHashCode(EdgeEndPoint edgePnt) } } - /// - /// Stores vertices list of geometry primitives. - /// Derived classes concretize the actual primitive type the vertices list belong to. - /// - private abstract class PrimVertices - { - public IFCAnyHandleUtil.IfcPointList PointList { get; protected set; } = new IFCAnyHandleUtil.IfcPointList(); - public PointBase this[int key] - { - get => PointList[key]; - set => PointList[key] = value; - } - public PointBase Last() { return PointList.Last(); } - } - private class PolyLineVertices : PrimVertices - { - public PolyLineVertices(UV beg, UV end) - { - PointList.AddPoints(beg, end); - } - public PolyLineVertices(XYZ beg, XYZ end) - { - PointList.AddPoints(beg, end); - } - public PolyLineVertices(List points) - { - if (points.Count < 2) - throw new ArgumentException("Number of points must be 2 or greater"); - - PointList.AddPoints(points); - } - public PolyLineVertices(List points) - { - if (points.Count < 2) - throw new ArgumentException("Number of points must be 2 or greater"); - - PointList.AddPoints(points); - } - } - private class ArcVertices : PrimVertices - { - public ArcVertices(UV start, UV mid, UV end) - { - PointList.AddPoints(start, mid, end); - } - public ArcVertices(XYZ start, XYZ mid, XYZ end) - { - PointList.AddPoints(start, mid, end); - } - } - /// - /// Stores indices list used to build geometry primitives. - /// Derived classes concretize the primitive type defined by indices. - /// - public abstract class SegmentIndices - { - public abstract int GetStart(); - public abstract int GetEnd(); - public abstract void SetEnd(int endIndex); - public abstract void CalcIndices(int startIdx); - public bool IsCalculated { get; protected set; } = false; - public virtual bool TryMerge(SegmentIndices segmentIndices) - { - return false; - } - } - public class PolyLineIndices : SegmentIndices - { - public PolyLineIndices(int lineCount) - { LineCount = lineCount; } - public List Indices { get; protected set; } - public int m_lineCount = 0; - public int LineCount - { - get { return m_lineCount; } - //Indices are not valid because line count has been changed. So delete indince list. - set { m_lineCount = value; IsCalculated = false; } - } - public override int GetStart() - { return Indices[0]; } - public override int GetEnd() - { return Indices.Last(); } - public override void SetEnd(int endIndex) - { Indices[Indices.Count - 1] = endIndex; } - public override void CalcIndices(int startIdx) - { - Indices = new List { startIdx }; - Indices.AddRange(Enumerable.Range(startIdx, LineCount).Select(x => x + 1)); - IsCalculated = true; - } - //Function assumes that input and this segmants are consecutive. End index of this segmant must be equal to start index of input segment. - public override bool TryMerge(SegmentIndices segmentIndices) - { - PolyLineIndices inputPolyLineIndices = segmentIndices as PolyLineIndices; - if (segmentIndices == this || inputPolyLineIndices == null) - return false; - - //Indices array after merge must not contain duplicated indices. - //So remove either End index of this segment or Start index of input segment. - Indices.RemoveAt(Indices.Count - 1); - Indices.AddRange(inputPolyLineIndices.Indices); - return true; - } - } - public class ArcIndices : SegmentIndices - { - public int Start { get; protected set; } - public int Mid { get; protected set; } - public int End { get; protected set; } - public override int GetStart() - { return Start; } - public override int GetEnd() - { return End; } - public override void SetEnd(int endIndex) - { End = endIndex; } - public override void CalcIndices(int startIdx) - { - Start = startIdx; - Mid = startIdx + 1; - End = startIdx + 2; - IsCalculated = true; - } - } - /// - /// Accumulates vertices and calculates indices. - /// This class assumes that primitive vertices should be connected in the order they appear in the array. - /// Based on this assumption this class constructs indices array. - /// - private class PolyCurve - { - private List PrimVerticesList { get; set; } = new List(); - public bool PolyLinesOnly { get; protected set; } = true; - //PointList and SegmentsIndices are built by BuildVerticesAndIndices() - public IFCAnyHandleUtil.IfcPointList PointList { get; protected set; } = new IFCAnyHandleUtil.IfcPointList(); - public List SegmentsIndices { get; protected set; } = null; - - public PolyCurve(PrimVertices primVertices) - { - if (!AddPrimVertices(primVertices)) - throw new ArgumentException("Error when constructing PolyCurve"); - } - - public void BuildVerticesAndIndices() - { - foreach (PrimVertices primVertices in PrimVerticesList) - { - const int MinIndexValue = 1; - - //1. Build point list. - //Current poly curve's end point and start point of primitive curve are always equal. - //So remove one of them from point list. - if (PointList.Count != 0) - PointList.Points.RemoveAt(PointList.Count - 1); - PointList.AddPointList(primVertices.PointList); - - //2. Build indices. Do not do it if poly curve contains poly line segments only. - PointBase endPoint = PointList.Last(); - bool startEndPointsAreEqual = CoordsAreWithinVertexTol(PointList[0], endPoint); - SegmentIndices segmentIndices = null; - if (PolyLinesOnly) - { - // Kind of workaround to ensure that the first and last points, if they are supposed to be - // the same, are exactly the same. - if (startEndPointsAreEqual) - PointList[0] = endPoint; - } - else - { - if (SegmentsIndices == null) - SegmentsIndices = new List(); - - if (primVertices as PolyLineVertices != null) - { - segmentIndices = new PolyLineIndices(primVertices.PointList.Count - 1); - } - else if (primVertices as ArcVertices != null) - { - segmentIndices = new ArcIndices(); - } - else - throw new ArgumentException("Unknown PrimVertices object"); - - segmentIndices.CalcIndices(SegmentsIndices.Count == 0 ? MinIndexValue : SegmentsIndices.Last().GetEnd()); - - // if start and end points of poly curve are equal we should remove duplicated point from vertices array. - // Indices array should be updated accordingly ( to access end point programmer should use start index). - if (startEndPointsAreEqual) - { - PointList.Points.RemoveAt(PointList.Count - 1); - segmentIndices.SetEnd(MinIndexValue); - } - - //TryMerge is implemented for polylines because we can easily merge two consecutive polyline segments. - if (SegmentsIndices.Count == 0 || !SegmentsIndices.Last().TryMerge(segmentIndices)) - SegmentsIndices.Add(segmentIndices); - } - } - } - - public bool AddPrimVertices(PrimVertices primVertices) - { - if (primVertices == null) - return false; - - //PrimVertices class guarantees that number of points is always >= 2. - var curvePoints = primVertices.PointList.Points; - var pointsCount = curvePoints.Count; - - PointBase currentStartPoint = PrimVerticesList.Count != 0 ? PrimVerticesList[0][0] : null; - PointBase currentEndPoint = PrimVerticesList.Count != 0 ? PrimVerticesList.Last().Last() : null; - bool addAtEnd = true; - bool reverseCurve = false; - - if (currentStartPoint != null && currentEndPoint != null) - { - // Need to check all possible connections between the current curve and the - // existing curve by checking start and endpoints. - - // For options to attach the next curve to the existing curve below. - if (!CoordsAreWithinVertexTol(curvePoints[0], currentEndPoint)) - { - if (CoordsAreWithinVertexTol(curvePoints[pointsCount - 1], currentEndPoint)) - { - reverseCurve = true; - } - else - { - addAtEnd = false; - if (CoordsAreWithinVertexTol(curvePoints[0], currentStartPoint)) - { - reverseCurve = true; - } - else - { - //Neither start nor end point of Input curve coincide with any of this polycurve's edge points. - //In this case we do not know how to connect them, so return false. - return false; - } - } - } - } - - if (reverseCurve) - curvePoints.Reverse(); - - if (primVertices as PolyLineVertices == null) - PolyLinesOnly = false; - - if (addAtEnd) - PrimVerticesList.Add(primVertices); - else - PrimVerticesList.Insert(0, primVertices); - - return true; - } - } - /// /// Creates a default plane whose origin is at (0, 0, 0) and normal is (0, 0, 1). /// @@ -2842,48 +2585,29 @@ public static bool ProcessCurve(ExporterIFC exporterIFC, Curve curve, Transform return true; } - static UV ScaledUVListFromXYZ(XYZ thePoint, Transform lcs, XYZ projectDir) + static IList ScaledUVListFromXYZ(XYZ thePoint, Transform lcs, XYZ projectDir) { UV projectPoint = GeometryUtil.ProjectPointToXYPlaneOfLCS(lcs, projectDir, thePoint); - return UnitUtil.ScaleLength(projectPoint); + projectPoint = UnitUtil.ScaleLength(projectPoint); + return new List(2) { projectPoint.U, projectPoint.V }; } - private static double DistanceSquaredBetweenVertices(XYZ coord1, XYZ coord2) + private static double DistanceSquaredBetweenVertices(IList coord1, IList coord2) { - var dX = coord1.X - coord2.X; - var dY = coord1.Y - coord2.Y; - var dZ = coord1.Z - coord2.Z; + int size = coord1.Count; + if (size != coord2.Count) + return double.MaxValue; // Cannot compare lists of different number of members - return dX * dX + dY * dY + dZ * dZ; - } - private static double DistanceSquaredBetweenVertices(UV coord1, UV coord2) - { - var dU = coord1.U - coord2.U; - var dV = coord1.V - coord2.V; + double distSq = 0.0; + for (int ii = 0; ii < size; ++ii) + { + distSq += (coord1[ii] - coord2[ii]) * (coord1[ii] - coord2[ii]); + } - return dU * dU + dV * dV; + return distSq; } - private static bool CoordsAreWithinVertexTol(PointBase coord1, PointBase coord2) - { - double vertexTol = UnitUtil.ScaleLength(ExporterCacheManager.Document.Application.VertexTolerance); - Point3D coord13D = coord1 as Point3D; - Point3D coord23D = coord2 as Point3D; - if (coord13D != null && coord23D != null) - return (DistanceSquaredBetweenVertices(coord13D.coords, coord23D.coords) < vertexTol * vertexTol); - Point2D coord12D = coord1 as Point2D; - Point2D coord22D = coord2 as Point2D; - if (coord12D != null && coord22D != null) - return (DistanceSquaredBetweenVertices(coord12D.coords, coord22D.coords) < vertexTol * vertexTol); - - throw new ArgumentException("Invalid Point type"); - } - private static bool CoordsAreWithinVertexTol(XYZ coord1, XYZ coord2) - { - double vertexTol = UnitUtil.ScaleLength(ExporterCacheManager.Document.Application.VertexTolerance); - return (DistanceSquaredBetweenVertices(coord1, coord2) < vertexTol * vertexTol); - } - private static bool CoordsAreWithinVertexTol(UV coord1, UV coord2) + private static bool CoordsAreWithinVertexTol(IList coord1, IList coord2) { double vertexTol = UnitUtil.ScaleLength(ExporterCacheManager.Document.Application.VertexTolerance); return (DistanceSquaredBetweenVertices(coord1, coord2) < vertexTol * vertexTol); @@ -2899,20 +2623,47 @@ private static bool CoordsAreWithinVertexTol(UV coord1, UV coord2) /// IFCAnyHandle for the created IfcIndexedPolyCurve public static IFCAnyHandle CreatePolyCurveFromCurve(ExporterIFC exporterIFC, Curve curve, Transform lcs = null, XYZ projectDir = null) { + IList> pointList = PointListFromCurve(exporterIFC, curve, lcs, projectDir); + if (pointList == null) + return null; + IFCFile file = exporterIFC.GetFile(); + IFCAnyHandle pointListHnd; + if (Is2DPointList(ref pointList)) + pointListHnd = IFCInstanceExporter.CreateCartesianPointList2D(file, pointList); + else + pointListHnd = IFCInstanceExporter.CreateCartesianPointList3D(file, pointList); - PrimVertices vertices = PointListFromCurve(exporterIFC, curve, lcs, projectDir); - // Points from the curve may have been merged after projection, so skip curves that - // won't add any new points. - if (vertices == null) - return null; - PolyCurve polyCurve = new PolyCurve(vertices); - polyCurve.BuildVerticesAndIndices(); - IList segmentsIndices = polyCurve.SegmentsIndices; + IList> segmentIndexList = null; + return IFCInstanceExporter.CreateIndexedPolyCurve(file, pointListHnd, segmentIndexList, false); + } - IFCAnyHandle pointListHnd = IFCInstanceExporter.CreateCartesianPointList(file, polyCurve.PointList); - return IFCInstanceExporter.CreateIndexedPolyCurve(file, pointListHnd, segmentsIndices, false); + static bool Is2DPointList(ref IList> pointList) + { + bool contains2DPoint = false; + bool contains3DPoint = false; + + foreach (IList pointCoord in pointList) + { + if (pointCoord.Count == 2) + contains2DPoint |= true; + else if (pointCoord.Count == 3) + contains3DPoint |= true; + else + throw (new ArgumentOutOfRangeException("pointList", "Only 2D or 3D point coordinates are valid!")); + } + if (contains2DPoint && contains3DPoint) + { + // Something is not right because of a mix of 2D and 3D coordinates. It will normalize below and discard the 3rd ordinate of 3D coordinates to 2D + for (int ii = 0; ii < pointList.Count; ++ii) + { + if (pointList[ii].Count == 3) + pointList[ii].RemoveAt(2); + } + } + + return contains2DPoint; } /// @@ -2929,31 +2680,88 @@ public static IFCAnyHandle CreatePolyCurveFromCurveLoop(ExporterIFC exporterIFC, if (curves.Count() == 0) return null; + bool use3DPoint = (lcs == null || projectDir == null); + IFCFile file = exporterIFC.GetFile(); + List> pointList = new List>(); + + IList currentStartPoint = null; + IList currentEndPoint = null; - PolyCurve polyCurve = null; foreach (Curve curve in curves) { - PrimVertices vertices = PointListFromCurve(exporterIFC, curve, lcs, projectDir); + IList> curveCoords = PointListFromCurve(exporterIFC, curve, lcs, projectDir); + // Points from the curve may have been merged after projection, so skip curves that // won't add any new points. - if (vertices == null) + if (curveCoords == null) continue; - if (polyCurve == null) - polyCurve = new PolyCurve(vertices); - else if (!polyCurve.AddPrimVertices(vertices)) - return null; + int curveCount = curveCoords.Count; + if (curveCoords.Count < 2) + continue; + + bool removeDuplicatePoint = false; + bool addAtEnd = true; + bool reverseCurve = false; + + if (currentStartPoint != null && currentEndPoint != null) + { + // Need to check all possible connections between the current curve and the + // existing curve by checking start and endpoints. + removeDuplicatePoint = true; + + // For options to attach the next curve to the existing curve below. + if (!CoordsAreWithinVertexTol(curveCoords[0], currentEndPoint)) + { + if (CoordsAreWithinVertexTol(curveCoords[curveCount - 1], currentEndPoint)) + { + reverseCurve = true; + } + else + { + addAtEnd = false; + if (CoordsAreWithinVertexTol(curveCoords[0], currentStartPoint)) + { + reverseCurve = true; + } + } + } + } + + if (reverseCurve) + curveCoords.Reverse(); + + if (removeDuplicatePoint) + curveCoords.RemoveAt(addAtEnd ? 0 : curveCount - 1); + + if (addAtEnd) + pointList.AddRange(curveCoords); + else + pointList.InsertRange(0, curveCoords); + + currentStartPoint = pointList[0]; + currentEndPoint = pointList[pointList.Count - 1]; } - polyCurve.BuildVerticesAndIndices(); - IList segmentsIndices = polyCurve.SegmentsIndices; + // Kind of workaround to ensure that the first and last points, if they are supposed to be + // the same, are exactly the same. + if (CoordsAreWithinVertexTol(currentStartPoint, currentEndPoint)) + pointList[pointList.Count - 1] = pointList[0]; + + // SegmentIndexList is not yet supported. + IList> segmentIndexList = null; + + IFCAnyHandle pointListHnd; + if (use3DPoint) + pointListHnd = IFCInstanceExporter.CreateCartesianPointList3D(file, pointList); + else + pointListHnd = IFCInstanceExporter.CreateCartesianPointList2D(file, pointList); - IFCAnyHandle pointListHnd = IFCInstanceExporter.CreateCartesianPointList(file, polyCurve.PointList); - return IFCInstanceExporter.CreateIndexedPolyCurve(file, pointListHnd, segmentsIndices, false); + return IFCInstanceExporter.CreateIndexedPolyCurve(file, pointListHnd, segmentIndexList, false); } - private static PrimVertices PointListFromCurve(ExporterIFC exporterIFC, Curve curve, + private static IList> PointListFromCurve(ExporterIFC exporterIFC, Curve curve, Transform lcs, XYZ projectDir) { if (curve == null) @@ -2968,139 +2776,93 @@ private static PrimVertices PointListFromCurve(ExporterIFC exporterIFC, Curve cu return PointListFromGenericCurve(exporterIFC, curve, lcs, projectDir); } - private static PolyLineVertices PointListFromLine(ExporterIFC exporterIFC, Line line, + private static IList Scaled3dListFromXYZ(ExporterIFC exporterIFC, XYZ thePoint) + { + XYZ vertexScaled = ExporterIFCUtils.TransformAndScalePoint(exporterIFC, thePoint); + return new List(3) { vertexScaled.X, vertexScaled.Y, vertexScaled.Z }; + } + + private static IList> PointListFromLine(ExporterIFC exporterIFC, Line line, Transform lcs, XYZ projectDir) { bool use3DPoint = (lcs == null || projectDir == null); - if (use3DPoint) - { - XYZ startPoint = ExporterIFCUtils.TransformAndScalePoint(exporterIFC, line.GetEndPoint(0)); - XYZ endPoint = ExporterIFCUtils.TransformAndScalePoint(exporterIFC, line.GetEndPoint(1)); - // Avoid consecutive duplicates - if (CoordsAreWithinVertexTol(startPoint, endPoint)) - return null; + IList startPoint = use3DPoint ? + Scaled3dListFromXYZ(exporterIFC, line.GetEndPoint(0)) : + ScaledUVListFromXYZ(line.GetEndPoint(0), lcs, projectDir); - return new PolyLineVertices(startPoint, endPoint); - } - else - { - var startPoint = ScaledUVListFromXYZ(line.GetEndPoint(0), lcs, projectDir); - var endPoint = ScaledUVListFromXYZ(line.GetEndPoint(1), lcs, projectDir); - // Avoid consecutive duplicates - if (CoordsAreWithinVertexTol(startPoint, endPoint)) - return null; + IList endPoint = use3DPoint ? + Scaled3dListFromXYZ(exporterIFC, line.GetEndPoint(1)) : + ScaledUVListFromXYZ(line.GetEndPoint(1), lcs, projectDir); - return new PolyLineVertices(startPoint, endPoint); - } + // Avoid consecutive duplicates + if (CoordsAreWithinVertexTol(startPoint, endPoint)) + return null; + + List> pointList = new List>(); + pointList.Add(startPoint); + pointList.Add(endPoint); + return pointList; } - private static PrimVertices PointListFromArc(ExporterIFC exporterIFC, Arc arc, + private static IList> PointListFromArc(ExporterIFC exporterIFC, Arc arc, Transform lcs, XYZ projectDir) { bool use3DPoint = (lcs == null || projectDir == null); - if (use3DPoint && arc.IsBound) - { - XYZ startPoint = ExporterIFCUtils.TransformAndScalePoint(exporterIFC, arc.Evaluate(0, true)); - XYZ midPoint = ExporterIFCUtils.TransformAndScalePoint(exporterIFC, arc.Evaluate(0.5, true)); - XYZ endPoint = ExporterIFCUtils.TransformAndScalePoint(exporterIFC, arc.Evaluate(1, true)); + IList> pointList = new List>(); - return new ArcVertices(startPoint, midPoint, endPoint); - } - else + // An integer value is used here to get an accurate interval the value ranges from + // 0 to 90 or 100 percent, depending on whether the arc is bound or not. + int normalizedEnd = arc.IsBound ? 10 : 9; + IList lastPoint = null; + for (int ii = 0; ii <= normalizedEnd; ++ii) { - //If arc's normal is parallel to projection direction and Z axis of lcs then projected arc will be of correct shape. - //That is why it can be defined by 3 points: start, mid, end. - if (MathUtil.VectorsAreParallel(arc.Normal, projectDir) && MathUtil.VectorsAreParallel(lcs.BasisZ, projectDir) && arc.IsBound) - { - var startPoint = ScaledUVListFromXYZ(arc.Evaluate(0, true), lcs, projectDir); - var midPoint = ScaledUVListFromXYZ(arc.Evaluate(0.5, true), lcs, projectDir); - var endPoint = ScaledUVListFromXYZ(arc.Evaluate(1, true), lcs, projectDir); + XYZ tessellationPt = arc.Evaluate(ii / 10.0, arc.IsBound); + IList point = use3DPoint ? + Scaled3dListFromXYZ(exporterIFC, tessellationPt) : + ScaledUVListFromXYZ(tessellationPt, lcs, projectDir); - return new ArcVertices(startPoint, midPoint, endPoint); - } - - //Handle cases when Arc is a circle (arc.IsBound == false) or projected arc is of incorrect shape - //and cannot be defined by 3 points. Tesselate it in this case. - List pointList3D = new List(); - List pointList2D = new List(); - - // An integer value is used here to get an accurate interval the value ranges from - // 0 to 90 or 100 percent, depending on whether the arc is bound or not. - int normalizedEnd = arc.IsBound ? 10 : 9; - XYZ lastPoint3D = null; - UV lastPoint2D = null; - for (int ii = 0; ii <= normalizedEnd; ++ii) + // Avoid consecutive duplicates + if (lastPoint == null || !CoordsAreWithinVertexTol(point, lastPoint)) { - XYZ tessellationPt = arc.Evaluate(ii / 10.0, arc.IsBound); - if (use3DPoint) - { - XYZ point = ExporterIFCUtils.TransformAndScalePoint(exporterIFC, tessellationPt); - - // Avoid consecutive duplicates - if (lastPoint3D == null || !CoordsAreWithinVertexTol(point, lastPoint3D)) - { - pointList3D.Add(point); - lastPoint3D = point; - } - } - else - { - var point2D = ScaledUVListFromXYZ(tessellationPt, lcs, projectDir); - - // Avoid consecutive duplicates - if (lastPoint2D == null || !CoordsAreWithinVertexTol(point2D, lastPoint2D)) - { - pointList2D.Add(point2D); - lastPoint2D = point2D; - } - } + pointList.Add(point); + lastPoint = point; } - - if (pointList3D != null && pointList3D.Count >= 2) - return new PolyLineVertices(pointList3D); - else if (pointList2D != null && pointList2D.Count >= 2) - return new PolyLineVertices(pointList2D); } - return null; + if (pointList.Count < 2) + return null; + + return pointList; } - private static PolyLineVertices PointListFromGenericCurve(ExporterIFC exporterIFC, + private static IList> PointListFromGenericCurve(ExporterIFC exporterIFC, Curve curve, Transform lcs, XYZ projectDir) { bool use3DPoint = (lcs == null || projectDir == null); - List listXYZ = new List(); - List listUV = new List(); - + IList> pointList = new List>(); IList tessellatedCurve = curve.Tessellate(); - var pointsCount = tessellatedCurve.Count; - for (int ii = 0; ii < pointsCount; ++ii) + IList lastPoint = null; + for (int ii = 0; ii < tessellatedCurve.Count; ++ii) { - if (use3DPoint) - { - var point = ExporterIFCUtils.TransformAndScalePoint(exporterIFC, tessellatedCurve[ii]); - // Avoid consecutive duplicates - if (listXYZ.Count == 0 || !CoordsAreWithinVertexTol(point, listXYZ.Last())) - listXYZ.Add(point); - } - else + IList point = use3DPoint ? + Scaled3dListFromXYZ(exporterIFC, tessellatedCurve[ii]) : + ScaledUVListFromXYZ(tessellatedCurve[ii], lcs, projectDir); + + // Avoid consecutive duplicates + if (lastPoint == null || !CoordsAreWithinVertexTol(point, lastPoint)) { - var point = ScaledUVListFromXYZ(tessellatedCurve[ii], lcs, projectDir); - // Avoid consecutive duplicates - if (listUV.Count == 0 || !CoordsAreWithinVertexTol(point, listUV.Last())) - listUV.Add(point); + pointList.Add(point); + lastPoint = point; } } - if (listXYZ != null && listXYZ.Count >= 2) - return new PolyLineVertices(listXYZ); - else if (listUV != null && listUV.Count >= 2) - return new PolyLineVertices(listUV); + if (pointList.Count < 2) + return null; - return null; + return pointList; } static private bool AllowedCurveForAllowComplexBoundary(Curve curve) @@ -3651,18 +3413,15 @@ public static IFCAnyHandle CreateIFCCurveFromRevitCurve(IFCFile file, ExporterIF if (ExporterCacheManager.ExportOptionsCache.ExportAs4ReferenceView) { - PrimVertices vertices = PointListFromCurve(exporterIFC, curve, additionalTrf, null); - // Points from the curve may have been merged after projection, so skip curves that - // won't add any new points. - if (vertices == null) + IList> pointList = PointListFromCurve(exporterIFC, curve, additionalTrf, null); + if (pointList == null) return null; - PolyCurve polyCurve = new PolyCurve(vertices); - polyCurve.BuildVerticesAndIndices(); - IList segmentsIndices = polyCurve.SegmentsIndices; + // Segment index list not yet supported. + IList> segmentIndexList = null; - IFCAnyHandle pointListHnd = IFCInstanceExporter.CreateCartesianPointList(file, polyCurve.PointList); - return IFCInstanceExporter.CreateIndexedPolyCurve(file, pointListHnd, segmentsIndices, false); + IFCAnyHandle pointListHnd = IFCInstanceExporter.CreateCartesianPointList3D(file, pointList); + return IFCInstanceExporter.CreateIndexedPolyCurve(file, pointListHnd, segmentIndexList, false); } // if the Curve is a line, do the following diff --git a/Source/Revit.IFC.Export/Utility/TriangleMergeUtil.cs b/Source/Revit.IFC.Export/Utility/TriangleMergeUtil.cs index 442b71e5..d8081953 100644 --- a/Source/Revit.IFC.Export/Utility/TriangleMergeUtil.cs +++ b/Source/Revit.IFC.Export/Utility/TriangleMergeUtil.cs @@ -362,13 +362,6 @@ public TriangleMergeUtil(TriangulatedShellComponent triangulatedBody) { m_Geom = triangulatedBody; m_MeshGeom = null; - m_MeshVertices.Clear(); - int idx = 0; - foreach(XYZ vert in triangulatedBody.GetVertices()) - { - m_MeshVertices.Add(idx, vert); - idx++; - } } ///