Exemplo n.º 1
0
        public static VectorArray2d SampleArcLen(IParametricCurve2d curve, double fSpacing)
        {
            if (curve.HasArcLength == false)
            {
                throw new InvalidOperationException("CurveSampler2.SampleArcLen: curve does not support arc length sampling!");
            }

            double fLen = curve.ArcLength;

            if (fLen < MathUtil.ZeroTolerance)
            {
                VectorArray2d degen = new VectorArray2d(2);
                degen[0] = curve.SampleArcLength(0);
                degen[1] = curve.SampleArcLength(1);
                return(degen);
            }
            int nSteps = Math.Max((int)(fLen / fSpacing) + 1, 2);

            VectorArray2d vec = new VectorArray2d(nSteps);

            for (int i = 0; i < nSteps; ++i)
            {
                double t = (double)i / (double)(nSteps - 1);
                vec[i] = curve.SampleArcLength(t * fLen);
            }

            return(vec);
        }
Exemplo n.º 2
0
 public Element Add(IParametricCurve2d curve)
 {
     if (curve.IsClosed)
     {
         SmoothLoopElement e = new SmoothLoopElement
         {
             ID     = id_generator++,
             source = curve
         };
         UpdateSampling(e);
         vElements.Add(e);
         return(e);
     }
     else
     {
         SmoothCurveElement e = new SmoothCurveElement
         {
             ID     = id_generator++,
             source = curve
         };
         UpdateSampling(e);
         vElements.Add(e);
         return(e);
     }
 }
Exemplo n.º 3
0
        public static void Restore(out IParametricCurve2d curve, BinaryReader reader)
        {
            curve = null;
            int nType = reader.ReadInt32();

            if (nType == 1)
            {
                Segment2d segment = new Segment2d();
                Restore(ref segment, reader);
                curve = segment;
            }
            else if (nType == 2)
            {
                Circle2d circle = new Circle2d(Vector2d.Zero, 1.0);
                Restore(ref circle, reader);
                curve = circle;
            }
            else if (nType == 3)
            {
                Arc2d arc = new Arc2d(Vector2d.Zero, 1.0, 0, 1);
                Restore(ref arc, reader);
                curve = arc;
            }
            else if (nType == 100)
            {
                ParametricCurveSequence2 seq = new ParametricCurveSequence2();
                Restore(ref seq, reader);
                curve = seq;
            }
            else
            {
                throw new Exception("gSerialization.Restore: IParametricCurve2D : unknown curve type " + nType.ToString());
            }
        }
Exemplo n.º 4
0
        public static VectorArray2d SampleTRange(IParametricCurve2d curve, int N, double t0, double t1)
        {
            VectorArray2d vec = new VectorArray2d(N);

            for (int i = 0; i < N; ++i)
            {
                double alpha = (double)i / (double)(N - 1);
                double t     = (1 - alpha) * t0 + alpha * t1;
                vec[i] = curve.SampleT(t);
            }
            return(vec);
        }
Exemplo n.º 5
0
        public void AddHole(IParametricCurve2d hole)
        {
            if (outer == null)
            {
                throw new Exception("PlanarSolid2d.AddHole: outer polygon not set!");
            }

            //        if ( (bOuterIsCW && hole.IsClockwise) || (bOuterIsCW == false && hole.IsClockwise == false) )
            //throw new Exception("PlanarSolid2d.AddHole: new hole has same orientation as outer polygon!");

            holes.Add(hole);
        }
Exemplo n.º 6
0
        public static VectorArray2d SampleT(IParametricCurve2d curve, int N)
        {
            double        fLenT  = curve.ParamLength;
            VectorArray2d vec    = new VectorArray2d(N);
            double        divide = (curve.IsClosed) ? (double)N : (double)(N - 1);

            for (int i = 0; i < N; ++i)
            {
                double t = (double)i / divide;
                vec[i] = curve.SampleT(t * fLenT);
            }
            return(vec);
        }
Exemplo n.º 7
0
		// 2D curve utils?
		public static double SampledDistance(IParametricCurve2d c, Vector2d point, int N = 100)
		{
			double tMax = c.ParamLength;
			double min_dist = double.MaxValue;
			for ( int i = 0; i <= N; ++i ) {
				double fT = (double)i / (double)N;
				fT *= tMax;
				Vector2d p = c.SampleT(fT);
				double d = p.DistanceSquared(point);
				if ( d < min_dist )
					min_dist = d;
			}
			return Math.Sqrt(min_dist);
		}
Exemplo n.º 8
0
        public static VectorArray2d SampleT(IParametricCurve2d curve, double fSpacing)
        {
            double fLenT = 1.0f;                        // assumption for now is that all curves span [0,1] t-range

            int nSteps = Math.Max((int)(fLenT / fSpacing) + 1, 2);

            VectorArray2d vec = new VectorArray2d(nSteps);

            for (int i = 0; i < nSteps; ++i)
            {
                double t = (double)i / (double)(nSteps - 1);
                vec[i] = curve.SampleT(t * fLenT);
            }

            return(vec);
        }
Exemplo n.º 9
0
        public static VectorArray2d SampleT(IParametricCurve2d curve, double fSpacing)
        {
            double fLenT = curve.ParamLength;

            int nSteps = Math.Max((int)(fLenT / fSpacing) + 1, 2);

            VectorArray2d vec = new VectorArray2d(nSteps);

            for (int i = 0; i < nSteps; ++i)
            {
                double t = (double)i / (double)(nSteps - 1);
                vec[i] = curve.SampleT(t * fLenT);
            }

            return(vec);
        }
Exemplo n.º 10
0
        // returns set of closed loops (not necessarily solids)
        public ClosedLoopsInfo FindClosedLoops(double fSimplifyDeviationTol = 0.1)
        {
            var loopElems = new List <SmoothLoopElement>(LoopsItr());
            int N         = loopElems.Count;

            int maxid = 0;

            foreach (var v in loopElems)
            {
                maxid = Math.Max(maxid, v.ID + 1);
            }

            // copy polygons, simplify if desired
            double fClusterTol   = 0.0;                 // don't do simple clustering, can lose corners
            double fDeviationTol = fSimplifyDeviationTol;
            var    polygons      = new Polygon2d[maxid];
            var    curves        = new IParametricCurve2d[maxid];

            foreach (var v in loopElems)
            {
                var p = new Polygon2d(v.polygon);
                if (fClusterTol > 0 || fDeviationTol > 0)
                {
                    p.Simplify(fClusterTol, fDeviationTol);
                }

                polygons[v.ID] = p;
                curves[v.ID]   = v.source;
            }

            var ci = new ClosedLoopsInfo()
            {
                Polygons = new List <Polygon2d>(),
                Loops    = new List <IParametricCurve2d>()
            };

            for (int i = 0; i < polygons.Length; ++i)
            {
                if (polygons[i] != null && polygons[i].VertexCount > 0)
                {
                    ci.Polygons.Add(polygons[i]);
                    ci.Loops.Add(curves[i]);
                }
            }

            return(ci);
        }
Exemplo n.º 11
0
        // returns set of open curves (ie non-solids)
        public OpenCurvesInfo FindOpenCurves(double fSimplifyDeviationTol = 0.1)
        {
            List <SmoothCurveElement> curveElems = new List <SmoothCurveElement>(CurvesItr());
            int N = curveElems.Count;

            int maxid = 0;

            foreach (var v in curveElems)
            {
                maxid = Math.Max(maxid, v.ID + 1);
            }

            // copy polygons, simplify if desired
            double fClusterTol   = 0.0;                 // don't do simple clustering, can lose corners
            double fDeviationTol = fSimplifyDeviationTol;

            PolyLine2d[]         polylines = new PolyLine2d[maxid];
            IParametricCurve2d[] curves    = new IParametricCurve2d[maxid];
            foreach (var v in curveElems)
            {
                PolyLine2d p = new PolyLine2d(v.polyLine);
                if (fClusterTol > 0 || fDeviationTol > 0)
                {
                    p.Simplify(fClusterTol, fDeviationTol);
                }
                polylines[v.ID] = p;
                curves[v.ID]    = v.source;
            }

            OpenCurvesInfo ci = new OpenCurvesInfo()
            {
                Polylines = new List <PolyLine2d>(),
                Curves    = new List <IParametricCurve2d>()
            };

            for (int i = 0; i < polylines.Length; ++i)
            {
                if (polylines[i] != null && polylines[i].VertexCount > 0)
                {
                    ci.Polylines.Add(polylines[i]);
                    ci.Curves.Add(curves[i]);
                }
            }

            return(ci);
        }
Exemplo n.º 12
0
 /// <summary>
 /// if the children of C are a tree, iterate through all the leaves
 /// </summary>
 public static IEnumerable <IParametricCurve2d> LeafCurvesIteration(IParametricCurve2d c)
 {
     if (c is IMultiCurve2d)
     {
         var multiC = c as IMultiCurve2d;
         foreach (IParametricCurve2d c2 in multiC.Curves)
         {
             foreach (var c3 in LeafCurvesIteration(c2))
             {
                 yield return(c3);
             }
         }
     }
     else
     {
         yield return(c);
     }
 }
Exemplo n.º 13
0
 public void Add(IParametricCurve2d curve)
 {
     if (curve.IsClosed)
     {
         SmoothLoopElement e = new SmoothLoopElement();
         e.ID     = id_generator++;
         e.source = curve;
         UpdateSampling(e);
         vElements.Add(e);
     }
     else
     {
         SmoothCurveElement e = new SmoothCurveElement();
         e.ID     = id_generator++;
         e.source = curve;
         UpdateSampling(e);
         vElements.Add(e);
     }
 }
Exemplo n.º 14
0
 /// <summary>
 /// iterate through "leaf" curves, ie all the IParametricCurve2D's
 /// embedded in loops that do not contain any child curves
 /// </summary>
 public IEnumerable <IParametricCurve2d> LoopLeafComponentsItr()
 {
     foreach (Element e in vElements)
     {
         if (e is SmoothLoopElement)
         {
             IParametricCurve2d source = e.source;
             if (source is IMultiCurve2d)
             {
                 foreach (var c in CurveUtils2.LeafCurvesIteration(source))
                 {
                     yield return(c);
                 }
             }
             else
             {
                 yield return(source);
             }
         }
     }
 }
Exemplo n.º 15
0
 public static void Store(IParametricCurve2d curve, BinaryWriter writer)
 {
     if (curve is Segment2d)
     {
         writer.Write((int)1);
         Store((Segment2d)curve, writer);
     }
     else if (curve is Circle2d)
     {
         writer.Write((int)2);
         Store((Circle2d)curve, writer);
     }
     else if (curve is Arc2d)
     {
         writer.Write((int)3);
         Store((Arc2d)curve, writer);
     }
     else if (curve is ParametricCurveSequence2)
     {
         writer.Write((int)100);
         Store(curve as ParametricCurveSequence2, writer);
     }
 }
Exemplo n.º 16
0
        public static VectorArray2d AutoSample(IParametricCurve2d curve, double fSpacingLength, double fSpacingT)
        {
            if (curve is ParametricCurveSequence2)
            {
                return(AutoSample(curve as ParametricCurveSequence2, fSpacingLength, fSpacingT));
            }

            if (curve.HasArcLength)
            {
                if (curve is NURBSCurve2)
                {
                    return(SampleNURBSHybrid(curve as NURBSCurve2, fSpacingLength));
                }
                else
                {
                    return(SampleArcLen(curve, fSpacingLength));
                }
            }
            else
            {
                return(SampleT(curve, fSpacingT));
            }
        }
Exemplo n.º 17
0
        // Finds set of "solid" regions - eg boundary loops with interior holes.
        // Result has outer loops being clockwise, and holes counter-clockwise
        public SolidRegionInfo FindSolidRegions(double fSimplifyDeviationTol = 0.1, bool bWantCurveSolids = true)
        {
            List <SmoothLoopElement> valid = new List <SmoothLoopElement>(LoopsItr());
            int N = valid.Count;

            // precompute bounding boxes
            int maxid = 0;

            foreach (var v in valid)
            {
                maxid = Math.Max(maxid, v.ID + 1);
            }
            AxisAlignedBox2d[] bounds = new AxisAlignedBox2d[maxid];
            foreach (var v in valid)
            {
                bounds[v.ID] = v.Bounds();
            }

            // copy polygons, simplify if desired
            double fClusterTol   = 0.0;                         // don't do simple clustering, can lose corners
            double fDeviationTol = fSimplifyDeviationTol;

            Polygon2d[] polygons = new Polygon2d[maxid];
            foreach (var v in valid)
            {
                Polygon2d p = new Polygon2d(v.polygon);
                if (fClusterTol > 0 || fDeviationTol > 0)
                {
                    p.Simplify(fClusterTol, fDeviationTol);
                }
                polygons[v.ID] = p;
            }

            // sort by bbox containment to speed up testing (does it??)
            valid.Sort((x, y) => {
                return(bounds[x.ID].Contains(bounds[y.ID]) ? -1 : 1);
            });

            // containment sets
            bool[] bIsContained = new bool[N];
            Dictionary <int, List <int> > ContainSets = new Dictionary <int, List <int> >();

            // construct containment sets
            for (int i = 0; i < N; ++i)
            {
                SmoothLoopElement loopi = valid[i];
                Polygon2d         polyi = polygons[loopi.ID];

                for (int j = 0; j < N; ++j)
                {
                    if (i == j)
                    {
                        continue;
                    }
                    SmoothLoopElement loopj = valid[j];
                    Polygon2d         polyj = polygons[loopj.ID];

                    // cannot be contained if bounds are not contained
                    if (bounds[loopi.ID].Contains(bounds[loopj.ID]) == false)
                    {
                        continue;
                    }

                    // any other early-outs??

                    if (polyi.Contains(polyj))
                    {
                        if (ContainSets.ContainsKey(i) == false)
                        {
                            ContainSets.Add(i, new List <int>());
                        }
                        ContainSets[i].Add(j);
                        bIsContained[j] = true;
                    }
                }
            }

            List <GeneralPolygon2d>  polysolids = new List <GeneralPolygon2d>();
            List <PlanarSolid2d>     solids     = new List <PlanarSolid2d>();
            List <SmoothLoopElement> used       = new List <SmoothLoopElement>();

            // extract solids from containment relationships
            foreach (var i in ContainSets.Keys)
            {
                SmoothLoopElement outer_element = valid[i];
                used.Add(outer_element);
                if (bIsContained[i])
                {
                    throw new Exception("PlanarComplex.FindSolidRegions: multiply-nested regions not supported!");
                }

                Polygon2d          outer_poly = polygons[outer_element.ID];
                IParametricCurve2d outer_loop = (bWantCurveSolids) ? outer_element.source.Clone() : null;
                if (outer_poly.IsClockwise == false)
                {
                    outer_poly.Reverse();
                    if (bWantCurveSolids)
                    {
                        outer_loop.Reverse();
                    }
                }

                GeneralPolygon2d g = new GeneralPolygon2d();
                g.Outer = outer_poly;
                PlanarSolid2d s = new PlanarSolid2d();
                if (bWantCurveSolids)
                {
                    s.SetOuter(outer_loop, true);
                }

                foreach (int hi in ContainSets[i])
                {
                    SmoothLoopElement he = valid[hi];
                    used.Add(he);
                    Polygon2d          hole_poly = polygons[he.ID];
                    IParametricCurve2d hole_loop = (bWantCurveSolids) ? he.source.Clone() : null;
                    if (hole_poly.IsClockwise)
                    {
                        hole_poly.Reverse();
                        if (bWantCurveSolids)
                        {
                            hole_loop.Reverse();
                        }
                    }

                    try {
                        g.AddHole(hole_poly);
                        if (hole_loop != null)
                        {
                            s.AddHole(hole_loop);
                        }
                    } catch {
                        // don't add this hole - must intersect or something
                        // We should have caught this earlier!
                    }
                }

                polysolids.Add(g);
                if (bWantCurveSolids)
                {
                    solids.Add(s);
                }
            }

            for (int i = 0; i < N; ++i)
            {
                SmoothLoopElement loopi = valid[i];
                if (used.Contains(loopi))
                {
                    continue;
                }

                Polygon2d          outer_poly = polygons[loopi.ID];
                IParametricCurve2d outer_loop = (bWantCurveSolids) ? loopi.source.Clone() : null;
                if (outer_poly.IsClockwise == false)
                {
                    outer_poly.Reverse();
                    if (bWantCurveSolids)
                    {
                        outer_loop.Reverse();
                    }
                }

                GeneralPolygon2d g = new GeneralPolygon2d();
                g.Outer = outer_poly;
                PlanarSolid2d s = new PlanarSolid2d();
                if (bWantCurveSolids)
                {
                    s.SetOuter(outer_loop, true);
                }

                polysolids.Add(g);
                if (bWantCurveSolids)
                {
                    solids.Add(s);
                }
            }

            return(new SolidRegionInfo()
            {
                Polygons = polysolids,
                Solids = (bWantCurveSolids) ? solids : null
            });
        }
Exemplo n.º 18
0
 public static List <IParametricCurve2d> Flatten(IParametricCurve2d curve)
 {
     return(new List <IParametricCurve2d>(LeafCurvesIteration(curve)));
 }
Exemplo n.º 19
0
 public void SetOuter(IParametricCurve2d loop, bool bIsClockwise)
 {
     Debug.Assert(loop.IsClosed);
     outer = loop;
     //bOuterIsCW = bIsClockwise;
 }
 public void Append(IParametricCurve2d c)
 {
     // sanity checking??
     curves.Add(c);
 }
Exemplo n.º 21
0
        // Finds set of "solid" regions - eg boundary loops with interior holes.
        // Result has outer loops being clockwise, and holes counter-clockwise
        public SolidRegionInfo FindSolidRegions(FindSolidsOptions options)
        {
            var validLoops = new List <SmoothLoopElement>(LoopsItr());
            int N          = validLoops.Count;

            // precompute bounding boxes
            int maxid = 0;

            foreach (var v in validLoops)
            {
                maxid = Math.Max(maxid, v.ID + 1);
            }

            var bounds = new AxisAlignedBox2d[maxid];

            foreach (var v in validLoops)
            {
                bounds[v.ID] = v.Bounds();
            }

            // copy polygons, simplify if desired
            double fClusterTol   = 0.0;                 // don't do simple clustering, can lose corners
            double fDeviationTol = options.SimplifyDeviationTolerance;
            var    polygons      = new Polygon2d[maxid];

            foreach (var v in validLoops)
            {
                var p = new Polygon2d(v.polygon);
                if (fClusterTol > 0 || fDeviationTol > 0)
                {
                    p.Simplify(fClusterTol, fDeviationTol);
                }

                polygons[v.ID] = p;
            }

            // sort by bbox containment to speed up testing (does it??)
            validLoops.Sort((x, y) =>
            {
                return(bounds[x.ID].Contains(bounds[y.ID]) ? -1 : 1);
            });

            // containment sets
            bool[] bIsContained     = new bool[N];
            var    ContainSets      = new Dictionary <int, List <int> >();
            var    ContainedParents = new Dictionary <int, List <int> >();

            bool bUseOrient       = options.TrustOrientations;
            bool bWantCurveSolids = options.WantCurveSolids;
            bool bCheckHoles      = !options.AllowOverlappingHoles;

            // construct containment sets
            for (int i = 0; i < N; ++i)
            {
                SmoothLoopElement loopi = validLoops[i];
                Polygon2d         polyi = polygons[loopi.ID];

                for (int j = 0; j < N; ++j)
                {
                    if (i == j)
                    {
                        continue;
                    }

                    SmoothLoopElement loopj = validLoops[j];
                    Polygon2d         polyj = polygons[loopj.ID];

                    // if we are preserving orientations, holes cannot contain holes and
                    // outers cannot contain outers!
                    if (bUseOrient && loopj.polygon.IsClockwise == loopi.polygon.IsClockwise)
                    {
                        continue;
                    }

                    // cannot be contained if bounds are not contained
                    if (bounds[loopi.ID].Contains(bounds[loopj.ID]) == false)
                    {
                        continue;
                    }

                    // any other early-outs??

                    if (polyi.Contains(polyj))
                    {
                        if (ContainSets.ContainsKey(i) == false)
                        {
                            ContainSets.Add(i, new List <int>());
                        }

                        ContainSets[i].Add(j);
                        bIsContained[j] = true;

                        if (ContainedParents.ContainsKey(j) == false)
                        {
                            ContainedParents.Add(j, new List <int>());
                        }

                        ContainedParents[j].Add(i);
                    }
                }
            }

            var polysolids     = new List <GeneralPolygon2d>();
            var polySolidsInfo = new List <GeneralSolid>();

            var solids = new List <PlanarSolid2d>();
            var used   = new HashSet <SmoothLoopElement>();

            var LoopToOuterIndex = new Dictionary <SmoothLoopElement, int>();

            var ParentsToProcess = new List <int>();


            // The following is a lot of code but it is very similar, just not clear how
            // to refactor out the common functionality
            //   1) we find all the top-level uncontained polys and add them to the final polys list
            //   2a) for any poly contained in those parent-polys, that is not also contained in anything else,
            //       add as hole to that poly
            //   2b) remove all those used parents & holes from consideration
            //   2c) now find all the "new" top-level polys
            //   3) repeat 2a-c until done all polys
            //   4) any remaining polys must be interior solids w/ no holes
            //          **or** weird leftovers like intersecting polys...

            // add all top-level uncontained polys
            for (int i = 0; i < N; ++i)
            {
                SmoothLoopElement loopi = validLoops[i];
                if (bIsContained[i])
                {
                    continue;
                }

                Polygon2d          outer_poly = polygons[loopi.ID];
                IParametricCurve2d outer_loop = (bWantCurveSolids) ? loopi.source.Clone() : null;
                if (outer_poly.IsClockwise == false)
                {
                    outer_poly.Reverse();
                    if (bWantCurveSolids)
                    {
                        outer_loop.Reverse();
                    }
                }

                var g = new GeneralPolygon2d();
                g.Outer = outer_poly;
                var s = new PlanarSolid2d();
                if (bWantCurveSolids)
                {
                    s.SetOuter(outer_loop, true);
                }

                int idx = polysolids.Count;
                LoopToOuterIndex[loopi] = idx;
                used.Add(loopi);

                if (ContainSets.ContainsKey(i))
                {
                    ParentsToProcess.Add(i);
                }

                polysolids.Add(g);
                polySolidsInfo.Add(new GeneralSolid()
                {
                    Outer = loopi
                });
                if (bWantCurveSolids)
                {
                    solids.Add(s);
                }
            }


            // keep iterating until we processed all parent loops
            while (ParentsToProcess.Count > 0)
            {
                var ContainersToRemove = new List <int>();

                // now for all top-level polys that contain children, add those children
                // as long as they do not have multiple contain-parents
                foreach (int i in ParentsToProcess)
                {
                    SmoothLoopElement parentloop = validLoops[i];
                    int outer_idx = LoopToOuterIndex[parentloop];

                    List <int> children = ContainSets[i];
                    foreach (int childj in children)
                    {
                        SmoothLoopElement childLoop = validLoops[childj];
                        Debug.Assert(used.Contains(childLoop) == false);

                        // skip multiply-contained children
                        List <int> parents = ContainedParents[childj];
                        if (parents.Count > 1)
                        {
                            continue;
                        }

                        Polygon2d          hole_poly = polygons[childLoop.ID];
                        IParametricCurve2d hole_loop = (bWantCurveSolids) ? childLoop.source.Clone() : null;
                        if (hole_poly.IsClockwise)
                        {
                            hole_poly.Reverse();
                            if (bWantCurveSolids)
                            {
                                hole_loop.Reverse();
                            }
                        }

                        try
                        {
                            polysolids[outer_idx].AddHole(hole_poly, bCheckHoles);
                            polySolidsInfo[outer_idx].Holes.Add(childLoop);
                            if (hole_loop != null)
                            {
                                solids[outer_idx].AddHole(hole_loop);
                            }
                        }
                        catch
                        {
                            // don't add this hole - must intersect or something?
                            // We should have caught this earlier!
                        }

                        used.Add(childLoop);
                        if (ContainSets.ContainsKey(childj))
                        {
                            ContainersToRemove.Add(childj);
                        }
                    }
                    ContainersToRemove.Add(i);
                }

                // remove all containers that are no longer valid
                foreach (int ci in ContainersToRemove)
                {
                    ContainSets.Remove(ci);

                    // have to remove from each ContainedParents list
                    var keys = new List <int>(ContainedParents.Keys);
                    foreach (int j in keys)
                    {
                        if (ContainedParents[j].Contains(ci))
                        {
                            ContainedParents[j].Remove(ci);
                        }
                    }
                }

                ParentsToProcess.Clear();

                // ok now find next-level uncontained parents...
                for (int i = 0; i < N; ++i)
                {
                    SmoothLoopElement loopi = validLoops[i];
                    if (used.Contains(loopi))
                    {
                        continue;
                    }

                    if (ContainSets.ContainsKey(i) == false)
                    {
                        continue;
                    }

                    List <int> parents = ContainedParents[i];
                    if (parents.Count > 0)
                    {
                        continue;
                    }

                    Polygon2d          outer_poly = polygons[loopi.ID];
                    IParametricCurve2d outer_loop = (bWantCurveSolids) ? loopi.source.Clone() : null;
                    if (outer_poly.IsClockwise == false)
                    {
                        outer_poly.Reverse();
                        if (bWantCurveSolids)
                        {
                            outer_loop.Reverse();
                        }
                    }

                    var g = new GeneralPolygon2d();
                    g.Outer = outer_poly;
                    var s = new PlanarSolid2d();
                    if (bWantCurveSolids)
                    {
                        s.SetOuter(outer_loop, true);
                    }

                    int idx = polysolids.Count;
                    LoopToOuterIndex[loopi] = idx;
                    used.Add(loopi);

                    if (ContainSets.ContainsKey(i))
                    {
                        ParentsToProcess.Add(i);
                    }

                    polysolids.Add(g);
                    polySolidsInfo.Add(new GeneralSolid()
                    {
                        Outer = loopi
                    });
                    if (bWantCurveSolids)
                    {
                        solids.Add(s);
                    }
                }
            }


            // any remaining loops must be top-level
            for (int i = 0; i < N; ++i)
            {
                SmoothLoopElement loopi = validLoops[i];
                if (used.Contains(loopi))
                {
                    continue;
                }

                Polygon2d          outer_poly = polygons[loopi.ID];
                IParametricCurve2d outer_loop = (bWantCurveSolids) ? loopi.source.Clone() : null;
                if (outer_poly.IsClockwise == false)
                {
                    outer_poly.Reverse();
                    if (bWantCurveSolids)
                    {
                        outer_loop.Reverse();
                    }
                }

                var g = new GeneralPolygon2d();
                g.Outer = outer_poly;
                var s = new PlanarSolid2d();
                if (bWantCurveSolids)
                {
                    s.SetOuter(outer_loop, true);
                }

                polysolids.Add(g);
                polySolidsInfo.Add(new GeneralSolid()
                {
                    Outer = loopi
                });
                if (bWantCurveSolids)
                {
                    solids.Add(s);
                }
            }



            return(new SolidRegionInfo()
            {
                Polygons = polysolids,
                PolygonsSources = polySolidsInfo,
                Solids = (bWantCurveSolids) ? solids : null
            });
        }
 public void Prepend(IParametricCurve2d c)
 {
     curves.Insert(0, c);
 }