Пример #1
0
        public List <Vector2d> FindIntersections(Polygon2d o)
        {
            List <Vector2d> v = new List <Vector2d>();

            if (!this.GetBounds().Intersects(o.GetBounds()))
            {
                return(v);
            }

            foreach (Segment2d seg in SegmentItr())
            {
                foreach (Segment2d oseg in o.SegmentItr())
                {
                    // this computes test twice for intersections, but seg.intersects doesn't
                    // create any new objects so it should be much faster for majority of segments (should profile!)
                    if (seg.Intersects(oseg))
                    {
                        IntrSegment2Segment2 intr = new IntrSegment2Segment2(seg, oseg);
                        if (intr.Find())
                        {
                            v.Add(intr.Point0);
                            if (intr.Quantity == 2)
                            {
                                v.Add(intr.Point1);
                            }
                        }
                    }
                }
            }
            return(v);
        }
Пример #2
0
        /// <summary>
        /// find set of edges in graph that intersect with edge [a,b]
        /// </summary>
        protected bool find_intersecting_edges(ref Vector2d a, ref Vector2d b, List <Intersection> hits, double tol = 0)
        {
            int      num_hits = 0;
            Vector2d x = Vector2d.Zero, y = Vector2d.Zero;

            foreach (int eid in Graph.EdgeIndices())
            {
                Graph.GetEdgeV(eid, ref x, ref y);
                int sidex = Segment2d.WhichSide(ref a, ref b, ref x, tol);
                int sidey = Segment2d.WhichSide(ref a, ref b, ref y, tol);
                if (sidex == sidey && sidex != 0)
                {
                    continue; // both pts on same side
                }
                IntrSegment2Segment2 intr = new IntrSegment2Segment2(new Segment2d(x, y), new Segment2d(a, b));
                if (intr.Find())
                {
                    hits.Add(new Intersection()
                    {
                        eid = eid, sidex = sidex, sidey = sidey, intr = intr
                    });
                    num_hits++;
                }
            }
            return(num_hits > 0);
        }
Пример #3
0
        public List <Vector2d> FindIntersections(Polygon2d o)
        {
            List <Vector2d> v = new List <Vector2d>();

            if (!this.GetBounds().Intersects(o.GetBounds()))
            {
                return(v);
            }

            foreach (Segment2d seg in SegmentItr())
            {
                foreach (Segment2d oseg in o.SegmentItr())
                {
                    IntrSegment2Segment2 intr = new IntrSegment2Segment2(seg, oseg);
                    if (intr.Find())
                    {
                        v.Add(intr.Point0);
                        if (intr.Quantity == 2)
                        {
                            v.Add(intr.Point1);
                        }
                        break;
                    }
                }
            }
            return(v);
        }
Пример #4
0
        /// <summary>
        /// Find any segment in set that intersects input segment.
        /// Returns intersection test, and index of segment
        /// </summary>
        public IntrSegment2Segment2 FindAnyIntersection(Segment2d seg, out int iSegment)
        {
            int N = Segments.Count;

            for (iSegment = 0; iSegment < N; ++iSegment)
            {
                var intr = new IntrSegment2Segment2(seg, Segments[iSegment]);
                if (intr.Find())
                {
                    return(intr);
                }
            }
            return(null);
        }
Пример #5
0
        public bool Intersects(Polygon2d o)
        {
            if (!this.GetBounds().Intersects(o.GetBounds()))
            {
                return(false);
            }

            foreach (Segment2d seg in SegmentItr())
            {
                foreach (Segment2d oseg in o.SegmentItr())
                {
                    IntrSegment2Segment2 intr = new IntrSegment2Segment2(seg, oseg);
                    if (intr.Find())
                    {
                        return(true);
                    }
                }
            }
            return(false);
        }
Пример #6
0
        public void FindAllIntersections(Segment2d seg, List <double> segmentTs, List <int> indices = null, List <IntrSegment2Segment2> tests = null, bool bOnlySimple = true)
        {
            int N = Segments.Count;

            for (int i = 0; i < N; ++i)
            {
                // want to make sure we do not miss any hits, even if it means
                // we get duplicates...
                var intr = new IntrSegment2Segment2(seg, Segments[i])
                {
                    IntervalThreshold = MathUtil.ZeroTolerance
                };

                if (intr.Find())
                {
                    if (bOnlySimple && intr.IsSimpleIntersection == false)
                    {
                        continue;
                    }

                    if (tests != null)
                    {
                        tests.Add(intr);
                    }

                    if (indices != null)
                    {
                        indices.Add(i);
                    }

                    if (segmentTs != null)
                    {
                        segmentTs.Add(intr.Parameter0);
                        if (!intr.IsSimpleIntersection)
                        {
                            segmentTs.Add(intr.Parameter1);
                        }
                    }
                }
            }
        }
        public virtual bool Apply()
        {
            HashSet <int> OnCurveVerts = new HashSet <int>();     // original vertices that were epsilon-coincident w/ curve vertices

            insert_corners(OnCurveVerts);

            // [RMS] not using this?
            //HashSet<int> corner_v = new HashSet<int>(CurveVertices);

            // not sure we need to track all of these
            HashSet <int> ZeroEdges    = new HashSet <int>();
            HashSet <int> ZeroVertices = new HashSet <int>();

            OnCutEdges = new HashSet <int>();

            HashSet <int> NewEdges       = new HashSet <int>();
            HashSet <int> NewCutVertices = new HashSet <int>();

            sbyte[] signs = new sbyte[2 * Mesh.MaxVertexID + 2 * Curve.VertexCount];

            HashSet <int> segTriangles = new HashSet <int>();
            HashSet <int> segVertices  = new HashSet <int>();
            HashSet <int> segEdges     = new HashSet <int>();

            // loop over segments, insert each one in sequence
            int N = (IsLoop) ? Curve.VertexCount : Curve.VertexCount - 1;

            for (int si = 0; si < N; ++si)
            {
                int       i0  = si;
                int       i1  = (si + 1) % Curve.VertexCount;
                Segment2d seg = new Segment2d(Curve[i0], Curve[i1]);

                int i0_vid = CurveVertices[i0];
                int i1_vid = CurveVertices[i1];

                // If these vertices are already connected by an edge, we can just continue.
                int existing_edge = Mesh.FindEdge(i0_vid, i1_vid);
                if (existing_edge != DMesh3.InvalidID)
                {
                    add_cut_edge(existing_edge);
                    continue;
                }

                if (triSpatial != null)
                {
                    segTriangles.Clear(); segVertices.Clear(); segEdges.Clear();
                    AxisAlignedBox2d segBounds = new AxisAlignedBox2d(seg.P0); segBounds.Contain(seg.P1);
                    segBounds.Expand(MathUtil.ZeroTolerancef * 10);
                    triSpatial.FindTrianglesInRange(segBounds, segTriangles);
                    IndexUtil.TrianglesToVertices(Mesh, segTriangles, segVertices);
                    IndexUtil.TrianglesToEdges(Mesh, segTriangles, segEdges);
                }

                int MaxVID = Mesh.MaxVertexID;
                IEnumerable <int> vertices = Interval1i.Range(MaxVID);
                if (triSpatial != null)
                {
                    vertices = segVertices;
                }

                // compute edge-crossing signs
                // [TODO] could walk along mesh from a to b, rather than computing for entire mesh?
                if (signs.Length < MaxVID)
                {
                    signs = new sbyte[2 * MaxVID];
                }
                gParallel.ForEach(vertices, (vid) => {
                    if (Mesh.IsVertex(vid))
                    {
                        if (vid == i0_vid || vid == i1_vid)
                        {
                            signs[vid] = 0;
                        }
                        else
                        {
                            Vector2d v2 = PointF(vid);
                            // tolerance defines band in which we will consider values to be zero
                            signs[vid] = (sbyte)seg.WhichSide(v2, SpatialEpsilon);
                        }
                    }
                    else
                    {
                        signs[vid] = sbyte.MaxValue;
                    }
                });

                // have to skip processing of new edges. If edge id
                // is > max at start, is new. Otherwise if in NewEdges list, also new.
                // (need both in case we re-use an old edge index)
                int MaxEID = Mesh.MaxEdgeID;
                NewEdges.Clear();
                NewCutVertices.Clear();
                NewCutVertices.Add(i0_vid);
                NewCutVertices.Add(i1_vid);

                // cut existing edges with segment
                IEnumerable <int> edges = Interval1i.Range(MaxEID);
                if (triSpatial != null)
                {
                    edges = segEdges;
                }
                foreach (int eid in edges)
                {
                    if (Mesh.IsEdge(eid) == false)
                    {
                        continue;
                    }
                    if (eid >= MaxEID || NewEdges.Contains(eid))
                    {
                        continue;
                    }

                    // cannot cut boundary edges?
                    if (Mesh.IsBoundaryEdge(eid))
                    {
                        continue;
                    }

                    Index2i ev       = Mesh.GetEdgeV(eid);
                    int     eva_sign = signs[ev.a];
                    int     evb_sign = signs[ev.b];

                    // [RMS] should we be using larger epsilon here? If we don't track OnCurveVerts explicitly, we
                    // need to at least use same epsilon we passed to insert_corner_from_bary...do we still also
                    // need that to catch the edges we split in the poke?
                    bool eva_in_segment = false;
                    if (eva_sign == 0)
                    {
                        eva_in_segment = OnCurveVerts.Contains(ev.a) || Math.Abs(seg.Project(PointF(ev.a))) < (seg.Extent + SpatialEpsilon);
                    }
                    bool evb_in_segment = false;
                    if (evb_sign == 0)
                    {
                        evb_in_segment = OnCurveVerts.Contains(ev.b) || Math.Abs(seg.Project(PointF(ev.b))) < (seg.Extent + SpatialEpsilon);
                    }

                    // If one or both vertices are on-segment, we have special case.
                    // If just one vertex is on the segment, we can skip this edge.
                    // If both vertices are on segment, then we can just re-use this edge.
                    if (eva_in_segment || evb_in_segment)
                    {
                        if (eva_in_segment && evb_in_segment)
                        {
                            ZeroEdges.Add(eid);
                            add_cut_edge(eid);
                            NewCutVertices.Add(ev.a); NewCutVertices.Add(ev.b);
                        }
                        else
                        {
                            int zvid = eva_in_segment ? ev.a : ev.b;
                            ZeroVertices.Add(zvid);
                            NewCutVertices.Add(zvid);
                        }
                        continue;
                    }

                    // no crossing
                    if (eva_sign * evb_sign > 0)
                    {
                        continue;
                    }

                    // compute segment/segment intersection
                    Vector2d             va       = PointF(ev.a);
                    Vector2d             vb       = PointF(ev.b);
                    Segment2d            edge_seg = new Segment2d(va, vb);
                    IntrSegment2Segment2 intr     = new IntrSegment2Segment2(seg, edge_seg);
                    intr.Compute();
                    if (intr.Type == IntersectionType.Segment)
                    {
                        // [RMS] we should have already caught this above, so if it happens here it is probably spurious?
                        // we should have caught this case above, but numerics are different so it might occur again
                        ZeroEdges.Add(eid);
                        NewCutVertices.Add(ev.a); NewCutVertices.Add(ev.b);
                        add_cut_edge(eid);
                        continue;
                    }
                    else if (intr.Type != IntersectionType.Point)
                    {
                        continue; // no intersection
                    }
                    Vector2d x = intr.Point0;
                    double   t = Math.Sqrt(x.DistanceSquared(va) / va.DistanceSquared(vb));

                    // this case happens if we aren't "on-segment" but after we do the test the intersection pt
                    // is within epsilon of one end of the edge. This is a spurious t-intersection and we
                    // can ignore it. Some other edge should exist that picks up this vertex as part of it.
                    // [TODO] what about if this edge is degenerate?
                    bool x_in_segment = Math.Abs(edge_seg.Project(x)) < (edge_seg.Extent - SpatialEpsilon);
                    if (!x_in_segment)
                    {
                        continue;
                    }

                    Index2i et = Mesh.GetEdgeT(eid);
                    spatial_remove_triangles(et.a, et.b);

                    // split edge at this segment
                    DMesh3.EdgeSplitInfo splitInfo;
                    MeshResult           result = Mesh.SplitEdge(eid, out splitInfo, t);
                    if (result != MeshResult.Ok)
                    {
                        throw new Exception("MeshInsertUVSegment.Apply: SplitEdge failed - " + result.ToString());
                        //return false;
                    }

                    // move split point to intersection position
                    SetPointF(splitInfo.vNew, x);
                    NewCutVertices.Add(splitInfo.vNew);

                    NewEdges.Add(splitInfo.eNewBN);
                    NewEdges.Add(splitInfo.eNewCN);

                    spatial_add_triangles(et.a, et.b);
                    spatial_add_triangles(splitInfo.eNewT2, splitInfo.eNewT3);

                    // some splits - but not all - result in new 'other' edges that are on
                    // the polypath. We want to keep track of these edges so we can extract loop later.
                    Index2i ecn = Mesh.GetEdgeV(splitInfo.eNewCN);
                    if (NewCutVertices.Contains(ecn.a) && NewCutVertices.Contains(ecn.b))
                    {
                        add_cut_edge(splitInfo.eNewCN);
                    }

                    // since we don't handle bdry edges this should never be false, but maybe we will handle bdry later...
                    if (splitInfo.eNewDN != DMesh3.InvalidID)
                    {
                        NewEdges.Add(splitInfo.eNewDN);
                        Index2i edn = Mesh.GetEdgeV(splitInfo.eNewDN);
                        if (NewCutVertices.Contains(edn.a) && NewCutVertices.Contains(edn.b))
                        {
                            add_cut_edge(splitInfo.eNewDN);
                        }
                    }
                }
            }

            // extract the cut paths
            if (EnableCutSpansAndLoops)
            {
                find_cut_paths(OnCutEdges);
            }

            return(true);
        }         // Apply()
Пример #8
0
        public virtual bool Apply()
        {
            insert_corners();

            // [RMS] not using this?
            //HashSet<int> corner_v = new HashSet<int>(CurveVertices);

            // not sure we need to track all of these
            HashSet <int> ZeroEdges    = new HashSet <int>();
            HashSet <int> ZeroVertices = new HashSet <int>();

            OnCutEdges = new HashSet <int>();

            // loop over segments, insert each one in sequence
            int N = (IsLoop) ? Curve.VertexCount : Curve.VertexCount - 1;

            for (int si = 0; si < N; ++si)
            {
                int       i0  = si;
                int       i1  = (si + 1) % Curve.VertexCount;
                Segment2d seg = new Segment2d(Curve[i0], Curve[i1]);

                int i0_vid = CurveVertices[i0];
                int i1_vid = CurveVertices[i1];

                // If these vertices are already connected by an edge, we can just continue.
                int existing_edge = Mesh.FindEdge(i0_vid, i1_vid);
                if (existing_edge != DMesh3.InvalidID)
                {
                    OnCutEdges.Add(existing_edge);
                    continue;
                }

                // compute edge-crossing signs
                // [TODO] could walk along mesh from a to b, rather than computing for entire mesh?
                int   MaxVID = Mesh.MaxVertexID;
                int[] signs  = new int[MaxVID];
                gParallel.ForEach(Interval1i.Range(MaxVID), (vid) => {
                    if (Mesh.IsVertex(vid))
                    {
                        if (vid == i0_vid || vid == i1_vid)
                        {
                            signs[vid] = 0;
                        }
                        else
                        {
                            Vector2d v2 = PointF(vid);
                            // tolerance defines band in which we will consider values to be zero
                            signs[vid] = seg.WhichSide(v2, MathUtil.ZeroTolerance);
                        }
                    }
                    else
                    {
                        signs[vid] = int.MaxValue;
                    }
                });

                // have to skip processing of new edges. If edge id
                // is > max at start, is new. Otherwise if in NewEdges list, also new.
                // (need both in case we re-use an old edge index)
                int           MaxEID         = Mesh.MaxEdgeID;
                HashSet <int> NewEdges       = new HashSet <int>();
                HashSet <int> NewCutVertices = new HashSet <int>();
                NewCutVertices.Add(i0_vid);
                NewCutVertices.Add(i1_vid);

                // cut existing edges with segment
                for (int eid = 0; eid < MaxEID; ++eid)
                {
                    if (Mesh.IsEdge(eid) == false)
                    {
                        continue;
                    }
                    if (eid >= MaxEID || NewEdges.Contains(eid))
                    {
                        continue;
                    }

                    // cannot cut boundary edges?
                    if (Mesh.IsBoundaryEdge(eid))
                    {
                        continue;
                    }

                    Index2i ev       = Mesh.GetEdgeV(eid);
                    int     eva_sign = signs[ev.a];
                    int     evb_sign = signs[ev.b];

                    bool eva_in_segment = false;
                    if (eva_sign == 0)
                    {
                        eva_in_segment = Math.Abs(seg.Project(PointF(ev.a))) < (seg.Extent + MathUtil.ZeroTolerance);
                    }
                    bool evb_in_segment = false;
                    if (evb_sign == 0)
                    {
                        evb_in_segment = Math.Abs(seg.Project(PointF(ev.b))) < (seg.Extent + MathUtil.ZeroTolerance);
                    }

                    // If one or both vertices are on-segment, we have special case.
                    // If just one vertex is on the segment, we can skip this edge.
                    // If both vertices are on segment, then we can just re-use this edge.
                    if (eva_in_segment || evb_in_segment)
                    {
                        if (eva_in_segment && evb_in_segment)
                        {
                            ZeroEdges.Add(eid);
                            OnCutEdges.Add(eid);
                        }
                        else
                        {
                            ZeroVertices.Add(eva_in_segment ? ev.a : ev.b);
                        }
                        continue;
                    }

                    // no crossing
                    if (eva_sign * evb_sign > 0)
                    {
                        continue;
                    }

                    // compute segment/segment intersection
                    Vector2d             va       = PointF(ev.a);
                    Vector2d             vb       = PointF(ev.b);
                    Segment2d            edge_seg = new Segment2d(va, vb);
                    IntrSegment2Segment2 intr     = new IntrSegment2Segment2(seg, edge_seg);
                    intr.Compute();
                    if (intr.Type == IntersectionType.Segment)
                    {
                        // [RMS] we should have already caught this above, so if it happens here it is probably spurious?
                        // we should have caught this case above, but numerics are different so it might occur again
                        ZeroEdges.Add(eid);
                        OnCutEdges.Add(eid);
                        continue;
                    }
                    else if (intr.Type != IntersectionType.Point)
                    {
                        continue; // no intersection
                    }
                    Vector2d x = intr.Point0;

                    // this case happens if we aren't "on-segment" but after we do the test the intersection pt
                    // is within epsilon of one end of the edge. This is a spurious t-intersection and we
                    // can ignore it. Some other edge should exist that picks up this vertex as part of it.
                    // [TODO] what about if this edge is degenerate?
                    bool x_in_segment = Math.Abs(edge_seg.Project(x)) < (edge_seg.Extent - MathUtil.ZeroTolerance);
                    if (!x_in_segment)
                    {
                        continue;
                    }

                    // split edge at this segment
                    DMesh3.EdgeSplitInfo splitInfo;
                    MeshResult           result = Mesh.SplitEdge(eid, out splitInfo);
                    if (result != MeshResult.Ok)
                    {
                        throw new Exception("MeshInsertUVSegment.Cut: failed in SplitEdge");
                        //return false;
                    }

                    // move split point to intersection position
                    SetPointF(splitInfo.vNew, x);
                    NewCutVertices.Add(splitInfo.vNew);

                    NewEdges.Add(splitInfo.eNewBN);
                    NewEdges.Add(splitInfo.eNewCN);

                    // some splits - but not all - result in new 'other' edges that are on
                    // the polypath. We want to keep track of these edges so we can extract loop later.
                    Index2i ecn = Mesh.GetEdgeV(splitInfo.eNewCN);
                    if (NewCutVertices.Contains(ecn.a) && NewCutVertices.Contains(ecn.b))
                    {
                        OnCutEdges.Add(splitInfo.eNewCN);
                    }

                    // since we don't handle bdry edges this should never be false, but maybe we will handle bdry later...
                    if (splitInfo.eNewDN != DMesh3.InvalidID)
                    {
                        NewEdges.Add(splitInfo.eNewDN);
                        Index2i edn = Mesh.GetEdgeV(splitInfo.eNewDN);
                        if (NewCutVertices.Contains(edn.a) && NewCutVertices.Contains(edn.b))
                        {
                            OnCutEdges.Add(splitInfo.eNewDN);
                        }
                    }
                }
            }


            //MeshEditor editor = new MeshEditor(Mesh);
            //foreach (int eid in OnCutEdges)
            //    editor.AppendBox(new Frame3f(Mesh.GetEdgePoint(eid, 0.5)), 0.1f);
            //Util.WriteDebugMesh(Mesh, string.Format("C:\\git\\geometry3SharpDemos\\geometry3Test\\test_output\\after_inserted.obj"));


            // extract the cut paths
            if (EnableCutSpansAndLoops)
            {
                find_cut_paths(OnCutEdges);
            }

            return(true);
        }         // Apply()