Пример #1
0
 void update_from_endpoints(Vector2d p0, Vector2d p1)
 {
     Center    = 0.5 * (p0 + p1);
     Direction = p1 - p0;
     Extent    = 0.5 * Direction.Normalize();
 }
Пример #2
0
 public Segment2d(Vector2d center, Vector2d direction, double extent)
 {
     Center = center; Direction = direction; Extent = extent;
 }
Пример #3
0
 public double Project(Vector2d p)
 {
     return((p - Center).Dot(Direction));
 }
Пример #4
0
        public double Distance(Vector2d pt)
        {
            double d = Center.Distance(pt);

            return(Math.Abs(d - Radius));
        }
Пример #5
0
 public void Transform(ITransform2 xform)
 {
     Center = xform.TransformP(Center);
     Radius = xform.TransformScalar(Radius);
 }
Пример #6
0
        public void Simplify(double clusterTol           = 0.0001,
                             double lineDeviationTol     = 0.01,
                             bool bSimplifyStraightLines = true)
        {
            int n = vertices.Count;

            if (n < 3)
            {
                return;
            }

            int i, k, pv;                        // misc counters

            Vector2d[] vt = new Vector2d[n + 1]; // vertex buffer
            bool[]     mk = new bool[n + 1];
            for (i = 0; i < n + 1; ++i)          // marker buffer
            {
                mk[i] = false;
            }

            // STAGE 1.  Vertex Reduction within tolerance of prior vertex cluster
            double clusterTol2 = clusterTol * clusterTol;

            vt[0] = vertices[0];                          // start at the beginning
            for (i = 1, k = 1, pv = 0; i < n; i++)
            {
                if ((vertices[i] - vertices[pv]).LengthSquared < clusterTol2)
                {
                    continue;
                }
                vt[k++] = vertices[i];
                pv      = i;
            }
            bool skip_dp = false;

            if (k == 1)
            {
                vt[k++] = vertices[1];
                vt[k++] = vertices[2];
                skip_dp = true;
            }
            else if (k == 2)
            {
                vt[k++] = vertices[0];
                skip_dp = true;
            }

            // push on start vertex again, because simplifyDP is for polylines, not polygons
            vt[k++] = vertices[0];

            // STAGE 2.  Douglas-Peucker polyline simplification
            int nv = 0;

            if (skip_dp == false && lineDeviationTol > 0)
            {
                mk[0] = mk[k - 1] = true;                     // mark the first and last vertices
                simplifyDP(lineDeviationTol, vt, 0, k - 1, mk);
                for (i = 0; i < k - 1; ++i)
                {
                    if (mk[i])
                    {
                        nv++;
                    }
                }
            }
            else
            {
                for (i = 0; i < k; ++i)
                {
                    mk[i] = true;
                }
                nv = k - 1;
            }

            // polygon requires at least 3 vertices
            if (nv == 2)
            {
                for (i = 1; i < k - 1; ++i)
                {
                    if (mk[1] == false)
                    {
                        mk[1] = true;
                    }
                    else if (mk[k - 2] == false)
                    {
                        mk[k - 2] = true;
                    }
                }
                nv++;
            }
            else if (nv == 1)
            {
                mk[1] = true;
                mk[2] = true;
                nv   += 2;
            }

            // copy marked vertices back to this polygon
            vertices = new List <Vector2d>();
            for (i = 0; i < k - 1; ++i)               // last vtx is copy of first, and definitely marked
            {
                if (mk[i])
                {
                    vertices.Add(vt[i]);
                }
            }

            Timestamp++;
            return;
        }
Пример #7
0
        public double SignedDistance(Vector2d pt)
        {
            double d = Center.Distance(pt);

            return(d - Radius);
        }
Пример #8
0
 public Vector3d(Vector2d copy, double _z)
 {
     x = copy.x; y = copy.y; z = _z;
 }
Пример #9
0
        public bool IsReversed;                 // use ccw orientation instead of cw

        public Circle2d(Vector2d center, double radius)
        {
            IsReversed = false;
            Center     = center;
            Radius     = radius;
        }
Пример #10
0
        override public MeshGenerator Generate()
        {
            if (Polygon == null)
            {
                Polygon = Polygon2d.MakeCircle(1.0f, 8);
            }

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

            if (Capped == false)
            {
                nCapVertices = 0;
            }

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

            int nSpanTris = (Vertices.Count - 1) * (2 * Slices);
            int nCapTris  = (Capped) ? 2 * Slices : 0;

            triangles = new IndexArray3i(nSpanTris + nCapTris);

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

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

            // generate tube
            for (int ri = 0; ri < nRings; ++ri)
            {
                // propagate frame
                if (ri != 0)
                {
                    Vector3d tan = CurveUtils.GetTangent(Vertices, ri);
                    fCur.Origin = (Vector3f)Vertices[ri];
                    if (ri == 11)
                    {
                        dv = tan;
                    }
                    fCur.AlignAxis(2, (Vector3f)tan);
                }

                float uv_along = (float)ri / (float)(nRings - 1);

                // generate vertices
                int nStartR = ri * nRingSize;
                for (int j = 0; j < nRingSize; ++j)
                {
                    float uv_around = (float)j / (float)(nRings);

                    int      k  = nStartR + j;
                    Vector2d pv = Polygon.Vertices[j % Slices];
                    Vector3d v  = fCur.FromPlaneUV((Vector2f)pv, 2);
                    vertices[k] = v;
                    uv[k]       = new Vector2f(uv_along, uv_around);
                    Vector3f n = (Vector3f)(v - fCur.Origin).Normalized;
                    normals[k] = n;
                }
            }


            // generate triangles
            int ti = 0;

            for (int ri = 0; ri < nRings - 1; ++ri)
            {
                int r0 = ri * nRingSize;
                int r1 = r0 + nRingSize;
                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)        // close disc if we went all the way
                {
                    triangles.Set(ti++, r1 - 1, r0, r1, Clockwise);
                    triangles.Set(ti++, r1 - 1, r1, r1 + nRingSize - 1, Clockwise);
                }
            }

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

                int nTopC = nBottomC + 1;
                vertices[nTopC]   = fCur.Origin;
                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];
                        uv[nStartB + k]       = (Vector2f)Polygon.Vertices[k].Normalized;
                        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]       = (Vector2f)Polygon.Vertices[k].Normalized;
                        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);
        }
Пример #11
0
 public Ray2d(Vector2d origin, Vector2d direction)
 {
     this.Origin    = origin;
     this.Direction = direction;
     this.Direction.Normalize();     // float cast may not be normalized in double, is trouble in algorithms!
 }
Пример #12
0
        /// <summary>
        /// hex-grid tiling of circles inside bounds, with spacing between elements
        /// Returns list of translations to element.
        /// Always allows at least one row and column, even if element overflows bounds in that dimension.
        /// </summary>
        public static List <Vector2d> BoundedCircleTiling2(AxisAlignedBox2d element, AxisAlignedBox2d bounds,
                                                           double spacing)
        {
            Vector2d oshift = -element.Min;
            double   w = element.Width; double h = element.Height;

            if (MathUtil.EpsilonEqual(w, h, MathUtil.Epsilonf) == false)
            {
                throw new Exception("BoundedHexTiling2: input box is not square");
            }

            // note: this is a circle tiling, not a hex tiling, so even though we are
            // starting in top-left with a "tip" hex, we don't have to offset down so that tip is inside
            // the box (circle cuts off)

            double    r   = w / 2;
            Hexagon2d hex = new Hexagon2d(element.Center, r, Hexagon2d.TopModes.Tip);

            hex.InnerRadius = r;

            double stepx = hex.HorzSpacing;
            double stepy = hex.VertSpacing;

            double spacingy = spacing;
            double spacingx = spacing;

            // half-rows on top and bottom add up to full row-height
            int ny = Math.Max(1, (int)(bounds.Height / stepy));
            // reduce count so that we fit w/ spacing
            double spaceh = (ny - 1) * spacingy;

            while (ny > 1 && bounds.Height - (stepy * ny + spaceh) < 0)
            {
                ny--;
            }

            // even rows start at x=0
            int nx_even = Math.Max(1, (int)(bounds.Width / stepx));
            // reduce count if we spill over w/ spacing
            double spacew = (nx_even - 1) * spacingx;

            while (nx_even > 1 && bounds.Width - (stepx * nx_even + spacew) < 0)
            {
                nx_even--;
            }

            // odd rows have an extra half-step added to left side,
            // so we may need to reduce count
            int nx_odd = nx_even;

            spacew = (nx_odd - 1) * spacingx;
            if (ny > 0 && (stepx * nx_odd + spacew + stepx * 0.5) > bounds.Width)
            {
                nx_odd--;
                spacew = (nx_odd - 1) * spacingx;
            }


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

            for (int yi = 0; yi < ny; ++yi)
            {
                double dy = yi * stepy + yi * spacingy;

                // x shift and count are different on odd rows
                double shiftx = stepx * 0.5;
                int    nx     = nx_odd;
                if (yi % 2 == 0)
                {
                    shiftx = 0;
                    nx     = nx_even;
                }

                for (int xi = 0; xi < nx; ++xi)
                {
                    double dx = shiftx + xi * stepx + xi * spacingx;
                    translations.Add(new Vector2d(dx, dy) + oshift + bounds.Min);
                }
            }

            return(translations);
        }
Пример #13
0
 public void AppendVertex(Vector2d v)
 {
     vertices.Add(v);
     Timestamp++;
 }
Пример #14
0
        public void Chamfer(double chamfer_dist, double minConvexAngleDeg = 30, double minConcaveAngleDeg = 30)
        {
            if (IsClockwise)
            {
                throw new Exception("must be ccw?");
            }

            List <Vector2d> NewV = new List <Vector2d>();
            int             N    = Vertices.Count;

            int iCur = 0;

            do
            {
                Vector2d center = Vertices[iCur];

                int      iPrev = (iCur == 0) ? N - 1 : iCur - 1;
                Vector2d prev  = Vertices[iPrev];
                int      iNext = (iCur + 1) % N;
                Vector2d next  = Vertices[iNext];

                Vector2d cp     = prev - center;
                double   cpdist = cp.Normalize();
                Vector2d cn     = next - center;
                double   cndist = cn.Normalize();

                // if degenerate, skip this vert
                if (cpdist < MathUtil.ZeroTolerancef || cndist < MathUtil.ZeroTolerancef)
                {
                    iCur = iNext;
                    continue;
                }

                double angle = Vector2d.AngleD(cp, cn);
                // TODO document what this means sign-wise
                double sign     = cp.Perp.Dot(cn);
                bool   bConcave = (sign > 0);

                double thresh = (bConcave) ? minConcaveAngleDeg : minConvexAngleDeg;

                // ok not too sharp
                if (angle > thresh)
                {
                    NewV.Add(center);
                    iCur = iNext;
                    continue;
                }


                double   prev_cut_dist = Math.Min(chamfer_dist, cpdist * 0.5);
                Vector2d prev_cut      = center + prev_cut_dist * cp;
                double   next_cut_dist = Math.Min(chamfer_dist, cndist * 0.5);
                Vector2d next_cut      = center + next_cut_dist * cn;

                NewV.Add(prev_cut);
                NewV.Add(next_cut);
                iCur = iNext;
            } while (iCur != 0);

            vertices = NewV;
            Timestamp++;
        }
Пример #15
0
 public static double IsLeft(ref Vector2d P0, ref Vector2d P1, ref Vector2d P2)
 {
     return(Math.Sign(((P1.x - P0.x) * (P2.y - P0.y) - (P2.x - P0.x) * (P1.y - P0.y))));
 }
Пример #16
0
        public bool Contains(Vector2d p)
        {
            double d = Center.DistanceSquared(p);

            return(d <= Radius * Radius);
        }
Пример #17
0
        /// <summary>
        /// Compute barycentric coordinates/weights of vPoint inside triangle (V0,V1,V2).
        /// If point is inside triangle, coords will pe positive and sum to 1.
        /// ie if result is a, then vPoint = a.x*V0 + a.y*V1 + a.z*V2.
        /// </summary>
        public static Vector3d BarycentricCoords(Vector2d vPoint, Vector2d V0, Vector2d V1, Vector2d V2)
        {
            Vector2d kV02    = V0 - V2;
            Vector2d kV12    = V1 - V2;
            Vector2d kPV2    = vPoint - V2;
            double   fM00    = kV02.Dot(kV02);
            double   fM01    = kV02.Dot(kV12);
            double   fM11    = kV12.Dot(kV12);
            double   fR0     = kV02.Dot(kPV2);
            double   fR1     = kV12.Dot(kPV2);
            double   fDet    = fM00 * fM11 - fM01 * fM01;
            double   fInvDet = 1.0 / fDet;
            double   fBary1  = (fM11 * fR0 - fM01 * fR1) * fInvDet;
            double   fBary2  = (fM00 * fR1 - fM01 * fR0) * fInvDet;
            double   fBary3  = 1.0 - fBary1 - fBary2;

            return(new Vector3d(fBary1, fBary2, fBary3));
        }
Пример #18
0
        public double DistanceSquared(Vector2d p)
        {
            int seg; double segt;

            return(DistanceSquared(p, out seg, out segt));
        }