コード例 #1
0
        List <Vector2d> collapse_by_deviation_tol(List <Vector2d> input, bool[] keep_segments, double offset_threshold)
        {
            int N     = input.Count;
            int NStop = (IsLoop) ? input.Count : input.Count - 1;

            List <Vector2d> result = new List <Vector2d>();

            result.Add(input[0]);

            double thresh_sqr = offset_threshold * offset_threshold;

            int last_i     = 0;
            int cur_i      = 1;
            int skip_count = 0;

            if (keep_segments[0])           // if first segment is constrained
            {
                result.Add(input[1]);
                last_i = 1; cur_i = 2;
            }

            while (cur_i < NStop)
            {
                int i0 = cur_i, i1 = (cur_i + 1) % N;

                if (keep_segments[i0])
                {
                    if (last_i != i0)
                    {
                        // skip join segment if it is degenerate
                        double join_dist = input[i0].Distance(result[result.Count - 1]);
                        if (join_dist > MathUtil.Epsilon)
                        {
                            result.Add(input[i0]);
                        }
                    }
                    result.Add(input[i1]);
                    last_i     = i1;
                    skip_count = 0;
                    if (i1 == 0)
                    {
                        cur_i = NStop;
                    }
                    else
                    {
                        cur_i = i1;
                    }
                    continue;
                }

                Vector2d dir        = input[i1] - input[last_i];
                Line2d   accum_line = new Line2d(input[last_i], dir.Normalized);

                // find deviation of vertices between last_i and next
                double max_dev_sqr = 0;
                for (int k = last_i + 1; k <= cur_i; k++)
                {
                    double distSqr = accum_line.DistanceSquared(input[k]);
                    if (distSqr > max_dev_sqr)
                    {
                        max_dev_sqr = distSqr;
                    }
                }

                // if we deviated too much, we keep this first vertex
                if (max_dev_sqr > thresh_sqr)
                {
                    result.Add(input[cur_i]);
                    last_i = cur_i;
                    cur_i++;
                    skip_count = 0;
                }
                else
                {
                    // skip this vertex
                    cur_i++;
                    skip_count++;
                }
            }


            if (IsLoop)
            {
                // if we skipped everything, rest of code doesn't work
                if (result.Count < 3)
                {
                    return(handle_tiny_case(result, input, keep_segments, offset_threshold));
                }

                Line2d last_line        = Line2d.FromPoints(input[last_i], input[cur_i % N]);
                bool   collinear_startv = last_line.DistanceSquared(result[0]) < thresh_sqr;
                bool   collinear_starts = last_line.DistanceSquared(result[1]) < thresh_sqr;
                if (collinear_startv && collinear_starts && result.Count > 3)
                {
                    // last seg is collinear w/ start seg, merge them
                    result[0] = input[last_i];
                    result.RemoveAt(result.Count - 1);
                }
                else if (collinear_startv)
                {
                    // skip last vertex
                }
                else
                {
                    result.Add(input[input.Count - 1]);
                }
            }
            else
            {
                // in polyline we always add last vertex
                result.Add(input[input.Count - 1]);
            }

            return(result);
        }
コード例 #2
0
 public IntrLine2Triangle2(Line2d l, Triangle2d t)
 {
     line = l; triangle = t;
 }
コード例 #3
0
        protected virtual void do_split(Line2d line, bool insert_edges, int insert_gid)
        {
            if (EdgeSigns.Length < Graph.MaxVertexID)
            {
                EdgeSigns.resize(Graph.MaxVertexID);
            }

            foreach (int vid in Graph.VertexIndices())
            {
                EdgeSigns[vid] = line.WhichSide(Graph.GetVertex(vid), OnVertexTol);
            }


            hits.Clear();
            foreach (int eid in Graph.EdgeIndices())
            {
                Index2i ev    = Graph.GetEdgeV(eid);
                var     signs = new Index2i(EdgeSigns[ev.a], EdgeSigns[ev.b]);
                if (signs.a * signs.b > 0)
                {
                    continue;                       // both positive or negative, ignore
                }

                var hit = new edge_hit()
                {
                    hit_eid = eid, vtx_signs = signs, hit_vid = -1
                };
                Vector2d a = Graph.GetVertex(ev.a);
                Vector2d b = Graph.GetVertex(ev.b);

                // parallel-edge case (both are zero)
                if (signs.a == signs.b)
                {
                    if (a.DistanceSquared(b) > MathUtil.Epsilon)
                    {
                        // we need to somehow not insert a new segment for this span below.
                        // so, insert two hit points for the ray-interval, with same eid.
                        // This will result in this span being skipped by the same-eid test below
                        // *however*, if other edges self-intersect w/ this segment, this will *not work*
                        // and duplicate edges will be inserted
                        hit.hit_vid = ev.a;
                        hit.line_t  = line.Project(a);
                        hits.Add(hit);
                        hit.hit_vid = ev.b;
                        hit.line_t  = line.Project(b);
                        hits.Add(hit);
                    }
                    else
                    {
                        // degenerate edge - fall through to a == 0 case below
                        signs.b = 1;
                    }
                }

                if (signs.a == 0)
                {
                    hit.hit_pos = a;
                    hit.hit_vid = ev.a;
                    hit.line_t  = line.Project(a);
                }
                else if (signs.b == 0)
                {
                    hit.hit_pos = b;
                    hit.hit_vid = ev.b;
                    hit.line_t  = line.Project(b);
                }
                else
                {
                    var intr = new IntrLine2Segment2(line, new Segment2d(a, b));
                    if (intr.Find() == false)
                    {
                        throw new Exception("GraphSplitter2d.Split: signs are different but ray did not it?");
                    }

                    if (intr.IsSimpleIntersection)
                    {
                        hit.hit_pos = intr.Point;
                        hit.line_t  = intr.Parameter;
                    }
                    else
                    {
                        throw new Exception("GraphSplitter2d.Split: got parallel edge case!");
                    }
                }
                hits.Add(hit);
            }

            // sort by increasing ray-t
            hits.Sort((hit0, hit1) => { return(hit0.line_t.CompareTo(hit1.line_t)); });

            // insert segments between successive intersection points
            int N = hits.Count;

            for (int i = 0; i < N - 1; ++i)
            {
                int j = i + 1;
                // note: skipping parallel segments depends on this eid == eid test (see above)
                if (hits[i].line_t == hits[j].line_t || hits[i].hit_eid == hits[j].hit_eid)
                {
                    continue;
                }

                int vi = hits[i].hit_vid;
                int vj = hits[j].hit_vid;
                if (vi == vj && vi >= 0)
                {
                    continue;
                }

                if (vi >= 0 && vj >= 0)
                {
                    int existing = Graph.FindEdge(vi, vj);
                    if (existing >= 0)
                    {
                        continue;
                    }
                }

                if (vi == -1)
                {
                    DGraph2.EdgeSplitInfo split;
                    var result = Graph.SplitEdge(hits[i].hit_eid, out split);
                    if (result != MeshResult.Ok)
                    {
                        throw new Exception("GraphSplitter2d.Split: first edge split failed!");
                    }

                    vi = split.vNew;
                    Graph.SetVertex(vi, hits[i].hit_pos);
                    edge_hit tmp = hits[i]; tmp.hit_vid = vi; hits[i] = tmp;
                }

                if (vj == -1)
                {
                    DGraph2.EdgeSplitInfo split;
                    var result = Graph.SplitEdge(hits[j].hit_eid, out split);
                    if (result != MeshResult.Ok)
                    {
                        throw new Exception("GraphSplitter2d.Split: second edge split failed!");
                    }

                    vj = split.vNew;
                    Graph.SetVertex(vj, hits[j].hit_pos);
                    edge_hit tmp = hits[j]; tmp.hit_vid = vj; hits[j] = tmp;
                }

                // check if we actually want to add this segment
                if (InsideTestF != null)
                {
                    Vector2d midpoint = 0.5 * (Graph.GetVertex(vi) + Graph.GetVertex(vj));
                    if (InsideTestF(midpoint) == false)
                    {
                        continue;
                    }
                }

                if (insert_edges)
                {
                    Graph.AppendEdge(vi, vj, insert_gid);
                }
            }
        }
コード例 #4
0
 public IntrLine2Segment2(Line2d line, Segment2d seg)
 {
     this.line = line; segment = seg;
 }
コード例 #5
0
 public IntrLine2Line2(Line2d l1, Line2d l2)
 {
     line1 = l1; line2 = l2;
 }
コード例 #6
0
 static public double MinDistance(Line2d line, Segment2d segment)
 {
     return(new DistLine2Segment2(line, segment).Get());
 }
コード例 #7
0
 public DistLine2Segment2(Line2d LineIn, Segment2d SegmentIn)
 {
     this.segment = SegmentIn; this.line = LineIn;
 }
コード例 #8
0
 static public double MinDistance(Line2d line1, Line2d line2)
 {
     return(new DistLine2Line2(line1, line2).Get());
 }
コード例 #9
0
 public DistLine2Line2(Line2d Line1, Line2d Line2)
 {
     this.line2 = Line2; this.line1 = Line1;
 }