Exemple #1
0
        /// <summary>
        /// Compute opening angle at vertex vID.
        /// If not a vertex, or valence != 2, returns invalidValue argument.
        /// If either edge is degenerate, returns invalidValue argument.
        /// </summary>
        public double OpeningAngle(int vID, double invalidValue = double.MaxValue)
        {
            if (vertices_refcount.isValid(vID) == false)
            {
                return(invalidValue);
            }
            List <int> vedges = vertex_edges[vID];

            if (vedges.Count != 2)
            {
                return(invalidValue);
            }

            int nbra = edge_other_v(vedges[0], vID);
            int nbrb = edge_other_v(vedges[1], vID);

            Vector2d v = new Vector2d(vertices[2 * vID], vertices[2 * vID + 1]);
            Vector2d a = new Vector2d(vertices[2 * nbra], vertices[2 * nbra + 1]);
            Vector2d b = new Vector2d(vertices[2 * nbrb], vertices[2 * nbrb + 1]);

            a -= v;
            if (a.Normalize() == 0)
            {
                return(invalidValue);
            }
            b -= v;
            if (b.Normalize() == 0)
            {
                return(invalidValue);
            }
            return(Vector2d.AngleD(a, b));
        }
Exemple #2
0
 public Segment2d(Vector2d p0, Vector2d p1)
 {
     //update_from_endpoints(p0, p1);
     Center    = 0.5 * (p0 + p1);
     Direction = p1 - p0;
     Extent    = 0.5 * Direction.Normalize();
 }
Exemple #3
0
        // t in range[0,1] spans ellipse
        public Vector2d TangentT(double t)
        {
            double theta = (IsReversed) ?
                           (1 - t) * AngleEndDeg + (t) * AngleStartDeg :
                           (1 - t) * AngleStartDeg + (t) * AngleEndDeg;

            theta = theta * MathUtil.Deg2Rad;
            double cost = Math.Cos(theta);
            double sint = Math.Sin(theta);

            // [RMS] adapted this formula from dxf.net.
            double a = this.Extent.x, b = this.Extent.y;
            double a1 = a * sint;
            double b1 = b * cost;

            double k = a1 * a1 + b1 * b1;
            double d = Math.Sqrt(k);
            //double k1 = (-a * b * sint) * d;
            double ddt = 0.5 * (1 / d) * ((2 * a * a * sint * cost) - (2 * b * b * cost * sint));
            //double k2 = ddt * (a * b * cost);

            double dx = ((-a * b * sint) * d - ddt * (a * b * cost)) / k;
            double dy = ((a * b * cost) * d - ddt * (a * b * sint)) / k;

            Vector2d tangent = dx * Axis0 + dy * Axis1;

            if (IsReversed)
            {
                tangent = -tangent;
            }
            tangent.Normalize();
            return(tangent);
        }
Exemple #4
0
 public Segment2d(Segment2d other)
 {
     //update_from_endpoints(p0, p1);
     Center    = 0.5 * (other.P0 + other.P1);
     Direction = other.P1 - other.P0;
     Extent    = 0.5 * Direction.Normalize();
 }
Exemple #5
0
        public static double PlaneAngleSignedD(Vector2d vFrom, Vector2d vTo)
        {
            vFrom.Normalize();
            vTo.Normalize();
            double fSign  = Math.Sign(vFrom.Cross(vTo));
            double fAngle = fSign * Vector2d.AngleD(vFrom, vTo);

            return(fAngle);
        }
Exemple #6
0
        public void NeighboursV(int iVertex, ref Vector2d v0, ref Vector2d v1, bool bNormalize = false)
        {
            int N = vertices.Count;

            v0 = vertices[(iVertex == 0) ? N - 1 : iVertex - 1] - vertices[iVertex];
            v1 = vertices[(iVertex + 1) % N] - vertices[iVertex];
            if (bNormalize)
            {
                v0.Normalize();
                v1.Normalize();
            }
        }
        public Vector2d TangentT(double t)
        {
            double   theta   = (IsReversed) ? -t * MathUtil.TwoPI : t * MathUtil.TwoPI;
            Vector2d tangent = new Vector2d(-Math.Sin(theta), Math.Cos(theta));

            if (IsReversed)
            {
                tangent = -tangent;
            }
            tangent.Normalize();
            return(tangent);
        }
Exemple #8
0
        // t in range[0,1] spans ellipse
        public Vector2d TangentT(double t)
        {
            double   theta = (IsReversed) ? -t * MathUtil.TwoPI : t * MathUtil.TwoPI;
            double   c = Math.Cos(theta), s = Math.Sin(theta);
            Vector2d tangent = -Extent.x * s * Axis0 + Extent.y * c * Axis1;

            if (IsReversed)
            {
                tangent = -tangent;
            }
            tangent.Normalize();
            return(tangent);
        }
Exemple #9
0
        public Vector2d TangentT(double t)
        {
            double theta = (IsReversed) ?
                           (1 - t) * AngleEndDeg + (t) * AngleStartDeg :
                           (1 - t) * AngleStartDeg + (t) * AngleEndDeg;

            theta = theta * MathUtil.Deg2Rad;
            Vector2d tangent = new Vector2d(-Math.Sin(theta), Math.Cos(theta));

            if (IsReversed)
            {
                tangent = -tangent;
            }
            tangent.Normalize();
            return(tangent);
        }
Exemple #10
0
        /// <summary>
        /// Construct normal at poly vertex by averaging face normals. This is
        /// equivalent (?) to angle-based normal, ie is local/independent of segment lengths.
        /// Points "inward" for clockwise polygon, outward for counter-clockwise
        /// </summary>
        public Vector2d GetNormal_FaceAvg(int i)
        {
            Vector2d next = vertices[(i + 1) % vertices.Count];
            Vector2d prev = vertices[i == 0 ? vertices.Count - 1 : i - 1];

            next -= vertices[i]; next.Normalize();
            prev -= vertices[i]; prev.Normalize();

            Vector2d n   = (next.Perp - prev.Perp);
            double   len = n.Normalize();

            if (len == 0)
            {
                return((next + prev).Normalized);   // this gives right direction for degenerate angle
            }
            else
            {
                return(n);
            }
        }
        public static IntersectionType Classify(Vector2d P0, Vector2d D0, Vector2d P1, Vector2d D1,
                                                double dotThreshold, ref Vector2d s)
        {
            // Ensure dotThreshold is nonnegative.
            dotThreshold = Math.Max(dotThreshold, (double)0);

            // The intersection of two lines is a solution to P0+s0*D0 = P1+s1*D1.
            // Rewrite this as s0*D0 - s1*D1 = P1 - P0 = Q.  If D0.Dot(Perp(D1)) = 0,
            // the lines are parallel.  Additionally, if Q.Dot(Perp(D1)) = 0, the
            // lines are the same.  If D0.Dot(Perp(D1)) is not zero, then
            //   s0 = Q.Dot(Perp(D1))/D0.Dot(Perp(D1))
            // produces the point of intersection.  Also,
            //   s1 = Q.Dot(Perp(D0))/D0.Dot(Perp(D1))

            Vector2d diff        = P1 - P0;
            double   D0DotPerpD1 = D0.DotPerp(D1);

            if (Math.Abs(D0DotPerpD1) > dotThreshold)
            {
                // Lines intersect in a single point.
                double invD0DotPerpD1 = ((double)1) / D0DotPerpD1;
                double diffDotPerpD0  = diff.DotPerp(D0);
                double diffDotPerpD1  = diff.DotPerp(D1);
                s[0] = diffDotPerpD1 * invD0DotPerpD1;
                s[1] = diffDotPerpD0 * invD0DotPerpD1;
                return(IntersectionType.Point);
            }

            // Lines are parallel.
            diff.Normalize();
            double diffNDotPerpD1 = diff.DotPerp(D1);

            if (Math.Abs(diffNDotPerpD1) <= dotThreshold)
            {
                // Lines are colinear.
                return(IntersectionType.Line);
            }

            // Lines are parallel, but distinct.
            return(IntersectionType.Empty);
        }
Exemple #12
0
        /// <summary>
        /// Test if segments intersect. Returns true for parallel-line overlaps.
        /// Returns same result as IntrSegment2Segment2.
        /// </summary>
        public bool Intersects(ref Segment2d seg2, double dotThresh = double.Epsilon, double intervalThresh = 0)
        {
            // see IntrLine2Line2 and IntrSegment2Segment2 for details on this code

            Vector2d diff        = seg2.Center - Center;
            double   D0DotPerpD1 = Direction.DotPerp(seg2.Direction);

            if (Math.Abs(D0DotPerpD1) > dotThresh)
            {               // Lines intersect in a single point.
                double invD0DotPerpD1 = ((double)1) / D0DotPerpD1;
                double diffDotPerpD0  = diff.DotPerp(Direction);
                double diffDotPerpD1  = diff.DotPerp(seg2.Direction);
                double s  = diffDotPerpD1 * invD0DotPerpD1;
                double s2 = diffDotPerpD0 * invD0DotPerpD1;
                return(Math.Abs(s) <= (Extent + intervalThresh) &&
                       Math.Abs(s2) <= (seg2.Extent + intervalThresh));
            }

            // Lines are parallel.
            diff.Normalize();
            double diffNDotPerpD1 = diff.DotPerp(seg2.Direction);

            if (Math.Abs(diffNDotPerpD1) <= dotThresh)
            {
                // Compute the location of segment1 endpoints relative to segment0.
                diff = seg2.Center - Center;
                double t1      = Direction.Dot(diff);
                double tmin    = t1 - seg2.Extent;
                double tmax    = t1 + seg2.Extent;
                var    extents = new Interval1d(-Extent, Extent);
                if (extents.Overlaps(new Interval1d(tmin, tmax)))
                {
                    return(true);
                }

                return(false);
            }

            // lines are parallel but not collinear
            return(false);
        }
Exemple #13
0
 void update_from_endpoints(Vector2d p0, Vector2d p1)
 {
     Center    = 0.5 * (p0 + p1);
     Direction = p1 - p0;
     Extent    = 0.5 * Direction.Normalize();
 }
Exemple #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++;
        }