/// <summary> /// Return a closed loop of integer-based points /// scaled to millimetres from a given Revit model /// face in feet. /// </summary> internal static JtLoop GetLoop( Autodesk.Revit.Creation.Application creapp, Face face) { JtLoop loop = null; foreach (EdgeArray a in face.EdgeLoops) { int nEdges = a.Size; List <Curve> curves = new List <Curve>(nEdges); XYZ p0 = null; // loop start point XYZ p; // edge start point XYZ q = null; // edge end point // Test ValidateCurveLoops //CurveLoop loopIfc = new CurveLoop(); foreach (Edge e in a) { // This requires post-processing using // SortCurvesContiguous: Curve curve = e.AsCurve(); if (_debug_output) { p = curve.GetEndPoint(0); q = curve.GetEndPoint(1); Debug.Print("{0} --> {1}", Util.PointString(p), Util.PointString(q)); } // This returns the curves already // correctly oriented: curve = e.AsCurveFollowingFace( face); if (_debug_output) { p = curve.GetEndPoint(0); q = curve.GetEndPoint(1); Debug.Print("{0} --> {1} following face", Util.PointString(p), Util.PointString(q)); } curves.Add(curve); // Throws an exception saying "This curve // will make the loop not contiguous. // Parameter name: pCurve" //loopIfc.Append( curve ); } // We never reach this point: //List<CurveLoop> loopsIfc // = new List<CurveLoop>( 1 ); //loopsIfc.Add( loopIfc ); //IList<CurveLoop> loopsIfcOut = ExporterIFCUtils // .ValidateCurveLoops( loopsIfc, XYZ.BasisZ ); // This is no longer needed if we use // AsCurveFollowingFace instead of AsCurve: CurveUtils.SortCurvesContiguous( creapp, curves, _debug_output); q = null; loop = new JtLoop(nEdges); foreach (Curve curve in curves) { // Todo: handle non-linear curve. // Especially: if two long lines have a // short arc in between them, skip the arc // and extend both lines. p = curve.GetEndPoint(0); Debug.Assert(null == q || q.IsAlmostEqualTo(p, 1e-04), string.Format( "expected last endpoint to equal current start point, not distance {0}", (null == q ? 0 : p.DistanceTo(q)))); q = curve.GetEndPoint(1); if (_debug_output) { Debug.Print("{0} --> {1}", Util.PointString(p), Util.PointString(q)); } if (null == p0) { p0 = p; // save loop start point } int n = -1; if (_tessellate_curves && _min_tessellation_curve_length_in_feet < q.DistanceTo(p)) { IList <XYZ> pts = curve.Tessellate(); n = pts.Count; Debug.Assert(1 < n, "expected at least two points"); Debug.Assert(p.IsAlmostEqualTo(pts[0]), "expected tessellation start equal curve start point"); Debug.Assert(q.IsAlmostEqualTo(pts[n - 1]), "expected tessellation end equal curve end point"); if (2 == n) { n = -1; // this is a straight line } else { --n; // skip last point for (int i = 0; i < n; ++i) { loop.Add(new Point2dInt(pts[i])); } } } // If tessellation is disabled, // or curve is too short to tessellate, // or has only two tessellation points, // just add the start point: if (-1 == n) { loop.Add(new Point2dInt(p)); } } Debug.Assert(q.IsAlmostEqualTo(p0, 1e-05), string.Format( "expected last endpoint to equal current start point, not distance {0}", p0.DistanceTo(q))); } return(loop); }