Beispiel #1
0
        public double Distance(Vector2d point)
        {
            Vector2d PmC       = point - Center;
            double   lengthPmC = PmC.Length;

            if (lengthPmC > MathUtil.Epsilon)
            {
                Vector2d dv    = PmC / lengthPmC;
                double   theta = Math.Atan2(dv.y, dv.x);
                if (theta < AngleStartDeg || theta > AngleEndDeg)
                {
                    theta = MathUtil.Clamp(theta, AngleStartDeg * MathUtil.Deg2Rad, AngleEndDeg * MathUtil.Deg2Rad);
                    double   c = Math.Cos(theta), s = Math.Sin(theta);
                    Vector2d pos = new Vector2d(Center.x + Radius * c, Center.y + Radius * s);
                    return(pos.Distance(point));
                }
                else
                {
                    return(Math.Abs(lengthPmC - Radius));
                }
            }
            else
            {
                return(Radius);
            }
        }
Beispiel #2
0
        public double Distance(Vector2d point)
        {
            Vector2d PmC       = point - Center;
            double   lengthPmC = PmC.Length;

            if (lengthPmC > MathUtil.Epsilon)
            {
                Vector2d dv    = PmC / lengthPmC;
                double   theta = Math.Atan2(dv.y, dv.x) * MathUtil.Rad2Deg;
                if (!(theta >= AngleStartDeg && theta <= AngleEndDeg))
                {
                    double   ctheta = MathUtil.ClampAngleDeg(theta, AngleStartDeg, AngleEndDeg);
                    double   radians = ctheta * MathUtil.Deg2Rad;
                    double   c = Math.Cos(radians), s = Math.Sin(radians);
                    Vector2d pos = new Vector2d(Center.x + Radius * c, Center.y + Radius * s);
                    return(pos.Distance(point));
                }
                else
                {
                    return(Math.Abs(lengthPmC - Radius));
                }
            }
            else
            {
                return(Radius);
            }
        }
        /// <summary>
        /// find nearest boundary vertex, within searchRadius
        /// </summary>
        protected int find_nearest_boundary_vertex(Vector2d pt, double searchRadius, int ignore_vid = -1)
        {
            KeyValuePair <int, double> found =
                PointHash.FindNearestInRadius(pt, searchRadius,
                                              (b) => { return(pt.Distance(Graph.GetVertex(b))); },
                                              (vid) => { return(Graph.IsBoundaryVertex(vid) == false || vid == ignore_vid); });

            if (found.Key == PointHash.InvalidValue)
            {
                return(-1);
            }
            return(found.Key);
        }
        private static int MergeAppendVertex(DGraph2 graph, Vector2d vertex, double mergeThreshold)
        {
            for (int i = 0; i < graph.VertexCount; i++)
            {
                double d = vertex.Distance(graph.GetVertex(i));
                if (d < mergeThreshold)
                {
                    return(i);
                }
            }

            return(graph.AppendVertex(vertex));
        }
Beispiel #5
0
        /// <summary>
        /// compute length of path through graph
        /// </summary>
        public static double PathLength(DGraph2 graph, IList <int> pathVertices)
        {
            double   len = 0;
            int      N = pathVertices.Count;
            Vector2d prev = graph.GetVertex(pathVertices[0]), next = Vector2d.Zero;

            for (int i = 1; i < N; ++i)
            {
                next = graph.GetVertex(pathVertices[i]);
                len += prev.Distance(next);
                prev = next;
            }
            return(len);
        }
        public void CollapseDegenerateEdges(double fDegenLenThresh = MathUtil.Epsilonf)
        {
            bool done       = false;
            int  max_passes = 100;
            int  pass_count = 0;

            while (done == false && pass_count++ < max_passes)
            {
                done = true;

                int N = Graph.MaxEdgeID;
                for (int eid = 0; eid < N; eid++)
                {
                    if (!Graph.IsEdge(eid))
                    {
                        continue;
                    }

                    if (FixedEdgeFilterF(eid))
                    {
                        continue;
                    }

                    Index2i ev = Graph.GetEdgeV(eid);

                    Vector2d va = Graph.GetVertex(ev.a);
                    Vector2d vb = Graph.GetVertex(ev.b);
                    if (va.Distance(vb) < fDegenLenThresh)
                    {
                        int keep   = ev.a;
                        int remove = ev.b;

                        DGraph2.EdgeCollapseInfo collapseInfo;
                        if (Graph.CollapseEdge(keep, remove, out collapseInfo) == MeshResult.Ok)
                        {
                            done = false;
                        }
                    }
                }
                ;
            }
        }
Beispiel #7
0
        public double SignedDistance(Vector2d pt)
        {
            double d = Center.Distance(pt);

            return(d - Radius);
        }
Beispiel #8
0
        override public MeshGenerator Generate()
        {
            if (Polygon == null)
            {
                Polygon = Polygon2d.MakeCircle(1.0f, 8);
            }

            int NV           = Vertices.Count;
            int Slices       = Polygon.VertexCount;
            int nRings       = (ClosedLoop && NoSharedVertices) ? NV + 1 : NV;
            int nRingSize    = (NoSharedVertices) ? Slices + 1 : Slices;
            int nCapVertices = (NoSharedVertices) ? Slices + 1 : 1;

            if (Capped == false || ClosedLoop == true)
            {
                nCapVertices = 0;
            }

            vertices = new VectorArray3d(nRings * nRingSize + 2 * nCapVertices);
            uv       = new VectorArray2f(vertices.Count);
            normals  = new VectorArray3f(vertices.Count);

            int quad_strips = (ClosedLoop) ? NV : NV - 1;
            int nSpanTris   = quad_strips * (2 * Slices);
            int nCapTris    = (Capped && ClosedLoop == false) ? 2 * Slices : 0;

            triangles = new IndexArray3i(nSpanTris + nCapTris);

            Frame3f  fCur = new Frame3f(Frame);
            Vector3d dv   = CurveUtils.GetTangent(Vertices, 0, ClosedLoop);

            fCur.Origin = (Vector3f)Vertices[0];
            fCur.AlignAxis(2, (Vector3f)dv);
            Frame3f fStart = new Frame3f(fCur);

            double circumference = Polygon.ArcLength;
            double pathLength    = CurveUtils.ArcLength(Vertices, ClosedLoop);
            double accum_path_u  = 0;

            // generate tube
            for (int ri = 0; ri < nRings; ++ri)
            {
                int vi = ri % NV;

                // propagate frame
                Vector3d tangent = CurveUtils.GetTangent(Vertices, vi, ClosedLoop);
                fCur.Origin = (Vector3f)Vertices[vi];
                fCur.AlignAxis(2, (Vector3f)tangent);

                // generate vertices
                int nStartR = ri * nRingSize;

                double accum_ring_v = 0;
                for (int j = 0; j < nRingSize; ++j)
                {
                    int      k      = nStartR + j;
                    Vector2d pv     = Polygon.Vertices[j % Slices];
                    Vector2d pvNext = Polygon.Vertices[(j + 1) % Slices];
                    Vector3d v      = fCur.FromPlaneUV((Vector2f)pv, 2);
                    vertices[k] = v;

                    uv[k]         = new Vector2f(accum_path_u, accum_ring_v);
                    accum_ring_v += (pv.Distance(pvNext) / circumference);

                    Vector3f n = (Vector3f)(v - fCur.Origin).Normalized;
                    normals[k] = n;
                }

                int    viNext = (ri + 1) % NV;
                double d      = Vertices[vi].Distance(Vertices[viNext]);
                accum_path_u += d / pathLength;
            }


            // generate triangles
            int ti    = 0;
            int nStop = (ClosedLoop && NoSharedVertices == false) ? nRings : (nRings - 1);

            for (int ri = 0; ri < nStop; ++ri)
            {
                int r0 = ri * nRingSize;
                int r1 = r0 + nRingSize;
                if (ClosedLoop && ri == nStop - 1 && NoSharedVertices == false)
                {
                    r1 = 0;
                }
                for (int k = 0; k < nRingSize - 1; ++k)
                {
                    triangles.Set(ti++, r0 + k, r0 + k + 1, r1 + k + 1, Clockwise);
                    triangles.Set(ti++, r0 + k, r1 + k + 1, r1 + k, Clockwise);
                }
                if (NoSharedVertices == false)        // last quad if we aren't sharing vertices
                {
                    int M = nRingSize - 1;
                    triangles.Set(ti++, r0 + M, r0, r1, Clockwise);
                    triangles.Set(ti++, r0 + M, r1, r1 + M, Clockwise);
                }
            }

            if (Capped && ClosedLoop == false)
            {
                Vector2d c = (OverrideCapCenter) ? CapCenter : Polygon.Bounds.Center;

                // add endcap verts
                int nBottomC = nRings * nRingSize;
                vertices[nBottomC]  = fStart.FromPlaneUV((Vector2f)c, 2);
                uv[nBottomC]        = new Vector2f(0.5f, 0.5f);
                normals[nBottomC]   = -fStart.Z;
                startCapCenterIndex = nBottomC;

                int nTopC = nBottomC + 1;
                vertices[nTopC]   = fCur.FromPlaneUV((Vector2f)c, 2);
                uv[nTopC]         = new Vector2f(0.5f, 0.5f);
                normals[nTopC]    = fCur.Z;
                endCapCenterIndex = nTopC;

                if (NoSharedVertices)
                {
                    // duplicate first loop and make a fan w/ bottom-center
                    int nExistingB = 0;
                    int nStartB    = nTopC + 1;
                    for (int k = 0; k < Slices; ++k)
                    {
                        vertices[nStartB + k] = vertices[nExistingB + k];
                        Vector2d vuv = ((Polygon[k] - c).Normalized + Vector2d.One) * 0.5;
                        uv[nStartB + k]      = (Vector2f)vuv;
                        normals[nStartB + k] = normals[nBottomC];
                    }
                    append_disc(Slices, nBottomC, nStartB, true, Clockwise, ref ti);

                    // duplicate second loop and make fan
                    int nExistingT = nRingSize * (nRings - 1);
                    int nStartT    = nStartB + Slices;
                    for (int k = 0; k < Slices; ++k)
                    {
                        vertices[nStartT + k] = vertices[nExistingT + k];
                        uv[nStartT + k]       = uv[nStartB + k];
                        normals[nStartT + k]  = normals[nTopC];
                    }
                    append_disc(Slices, nTopC, nStartT, true, !Clockwise, ref ti);
                }
                else
                {
                    append_disc(Slices, nBottomC, 0, true, Clockwise, ref ti);
                    append_disc(Slices, nTopC, nRingSize * (nRings - 1), true, !Clockwise, ref ti);
                }
            }

            return(this);
        }
Beispiel #9
0
        // (sequentially) find each triangle that path point lies in, and insert a vertex for
        // that point into mesh.
        void insert_corners(HashSet <int> MeshVertsOnCurve)
        {
            PrimalQuery2d query = new PrimalQuery2d(PointF);

            if (UseTriSpatial)
            {
                int count = Mesh.TriangleCount + Curve.VertexCount;
                int bins  = 32;
                if (count < 25)
                {
                    bins = 8;
                }
                else if (count < 100)
                {
                    bins = 16;
                }
                AxisAlignedBox3d bounds3 = Mesh.CachedBounds;
                AxisAlignedBox2d bounds2 = new AxisAlignedBox2d(bounds3.Min.xy, bounds3.Max.xy);
                triSpatial = new TriangleBinsGrid2d(bounds2, bins);
                foreach (int tid in Mesh.TriangleIndices())
                {
                    spatial_add_triangle(tid);
                }
            }

            Func <int, Vector2d, bool> inTriangleF = (tid, pos) => {
                Index3i tv           = Mesh.GetTriangle(tid);
                int     query_result = query.ToTriangleUnsigned(pos, tv.a, tv.b, tv.c);
                return(query_result == -1 || query_result == 0);
            };

            CurveVertices = new int[Curve.VertexCount];
            for (int i = 0; i < Curve.VertexCount; ++i)
            {
                Vector2d vInsert  = Curve[i];
                bool     inserted = false;

                // find the triangle that contains this curve point
                int contain_tid = DMesh3.InvalidID;
                if (triSpatial != null)
                {
                    contain_tid = triSpatial.FindContainingTriangle(vInsert, inTriangleF);
                }
                else
                {
                    foreach (int tid in Mesh.TriangleIndices())
                    {
                        Index3i tv = Mesh.GetTriangle(tid);
                        // [RMS] using unsigned query here because we do not need to care about tri CW/CCW orientation
                        //   (right? otherwise we have to explicitly invert mesh. Nothing else we do depends on tri orientation)
                        //int query_result = query.ToTriangle(vInsert, tv.a, tv.b, tv.c);
                        int query_result = query.ToTriangleUnsigned(vInsert, tv.a, tv.b, tv.c);
                        if (query_result == -1 || query_result == 0)
                        {
                            contain_tid = tid;
                            break;
                        }
                    }
                }

                // if we found one, insert the point via face-poke or edge-split,
                // unless it is exactly at existing vertex, in which case we can re-use it
                if (contain_tid != DMesh3.InvalidID)
                {
                    Index3i  tv   = Mesh.GetTriangle(contain_tid);
                    Vector3d bary = MathUtil.BarycentricCoords(vInsert, PointF(tv.a), PointF(tv.b), PointF(tv.c));
                    // SpatialEpsilon is our zero-tolerance, so merge if we are closer than that
                    bool is_existing_v;
                    int  vid = insert_corner_from_bary(i, contain_tid, bary, 0.01, 100 * SpatialEpsilon, out is_existing_v);
                    if (vid > 0)
                    {
                        CurveVertices[i] = vid;
                        if (is_existing_v)
                        {
                            MeshVertsOnCurve.Add(vid);
                        }
                        inserted = true;
                    }
                }

                // if we did not find containing triangle,
                // try matching with any existing vertices.
                // This can happen if curve point is right on mesh border...
                if (inserted == false)
                {
                    foreach (int vid in Mesh.VertexIndices())
                    {
                        Vector2d v = PointF(vid);
                        if (vInsert.Distance(v) < SpatialEpsilon)
                        {
                            CurveVertices[i] = vid;
                            MeshVertsOnCurve.Add(vid);
                            inserted = true;
                        }
                    }
                }

                // TODO: also case where curve point is right on mesh border edge,
                // and so it ends up being outside all triangles?


                if (inserted == false)
                {
                    throw new Exception("MeshInsertUVPolyCurve.insert_corners: curve vertex "
                                        + i.ToString() + " is not inside or on any mesh triangle!");
                }
            }
        }