コード例 #1
0
        /// <summary>
        /// Enumerates all vertex indexes at which
        /// both outgoing edges meet at an angle that
        /// is less than the given threshold.
        /// </summary>
        public static IEnumerable <int> GetSpikes(
            this Polygon3d self, double toleranceInDegrees = 0.1)
        {
            if (toleranceInDegrees < 0.0)
            {
                throw new ArgumentOutOfRangeException();
            }
            var threshold = Conversion.RadiansFromDegrees(toleranceInDegrees).Cos();
            var edges     = self.GetEdgeArray();

            edges.Apply(e => e.Normalized);
            var ec = edges.Length;

            if (V3d.Dot(-edges[ec - 1], edges[0]) > threshold)
            {
                yield return(0);
            }
            for (int i = 1; i < ec; i++)
            {
                if (V3d.Dot(-edges[i - 1], edges[i]) > threshold)
                {
                    yield return(i);
                }
            }
        }
コード例 #2
0
 /// <summary>
 /// Compute the triangulation of the supplied concave polygon and
 /// return the resulting triangle index array.
 /// </summary>
 public static int[] ComputeTriangulationOfConcavePolygon(
     this Polygon3d polygon, double absoluteEpsilon)
 {
     int[] triangleIndexArray = new int[3 * (polygon.PointCount - 2)];
     polygon.ComputeTriangulationOfConcavePolygon(
         absoluteEpsilon, 0, triangleIndexArray);
     return(triangleIndexArray);
 }
コード例 #3
0
        public void Polygon3dBoundingBox()
        {
            var poly = new Polygon3d(V3d.OOO, V3d.IOO, V3d.IIO);
            var bb   = poly.BoundingBox3d(0.5);

            Assert.IsTrue(bb.Min == new V3d(0.0, 0.0, -0.5));
            Assert.IsTrue(bb.Max == new V3d(1.0, 1.0, 0.5));
        }
コード例 #4
0
 public static double ComputeFromPointFormFactor(
     this Polygon3d targetPolygon,
     V3d sourcePoint, V3d sourceNormal,
     double eps = 1e-6)
 {
     return(targetPolygon.ComputeUnscaledFormFactor(
                sourcePoint, sourceNormal, eps)
            / Constant.PiTimesTwo);
 }
コード例 #5
0
 public static double ComputeToPointFormFactor(
     this Polygon3d sourcePolygon, double polygonArea,
     V3d targetPoint, V3d targetNormal,
     double eps = 1e-6)
 {
     return(sourcePolygon.ComputeUnscaledFormFactor(
                targetPoint, targetNormal, eps)
            / (Constant.PiTimesTwo * polygonArea));
 }
コード例 #6
0
        public static double ComputeUnscaledFormFactor(
            this Polygon3d polygon,
            V3d p, V3d n,
            double eps = 1e-6)
        {
            var vc = polygon.PointCount;

            V3d[] cpa = new V3d[vc + 1];

            var cc = 0;
            var pb = polygon[0] - p;
            var hb = V3d.Dot(pb, n); bool hbp = hb > eps, hbn = hb < -eps;

            if (hb >= -eps)
            {
                cpa[cc++] = pb;
            }
            var p0 = pb; var h0 = hb; var h0p = hbp; var h0n = hbn;

            for (int vi = 1; vi < vc; vi++)
            {
                var  p1 = polygon[vi] - p; var h1 = V3d.Dot(p1, n);
                bool h1p = h1 > eps, h1n = h1 < -eps;
                if (h0p && h1n || h0n && h1p)
                {
                    cpa[cc++] = p0 + (p1 - p0) * (h0 / (h0 - h1));
                }
                if (h1 >= -eps)
                {
                    cpa[cc++] = p1;
                }
                p0 = p1; h0 = h1; h0p = h1p; h0n = h1n;
            }
            if (h0p && hbn || h0n && hbp)
            {
                cpa[cc++] = p0 + (pb - p0) * (h0 / (h0 - hb));
            }

            var cpr = cpa.Map(cc, v => v.Length);

            var    cv = V3d.Cross(cpa[0], cpa[cc - 1]);
            double ff = V3d.Dot(n, cv)
                        * Fun.AcosC(V3d.Dot(cpa[0], cpa[cc - 1])
                                    / (cpr[0] * cpr[cc - 1]))
                        / cv.Length;

            for (int ci = 0; ci < cc - 1; ci++)
            {
                cv  = V3d.Cross(cpa[ci + 1], cpa[ci]);
                ff += V3d.Dot(n, cv)
                      * Fun.AcosC(V3d.Dot(cpa[ci + 1], cpa[ci])
                                  / (cpr[ci + 1] * cpr[ci]))
                      / cv.Length;
            }
            return(ff);
        }
コード例 #7
0
        public void TestConvexClipped()
        {
            var points      = new[] { V3d.OOO, V3d.IOO, V3d.OIO };
            var poly        = new Polygon3d(points);
            var box         = Box3d.FromMinAndSize(-V3d.OOI, new V3d(1, 0.5, 2));
            var newHull     = Hull3d.Create(box).Reversed(); // requires non-intuitive reversed (or using obsolte Hull3d constructor that points inside)
            var polyClipped = poly.ConvexClipped(newHull);   // will return positive part of planes (outside of Hull3d)
            var clippedBox  = polyClipped.BoundingBox3d;
            var test        = new Box3d(0, 0, 0, 1, 0.5, 0);

            Test.IsTrue(clippedBox == test);
        }
コード例 #8
0
        public static Box3d BoundingBox3d(
            this Polygon3d self, double eps)
        {
            var bb = Box3d.Invalid;
            var v  = self.ComputeNormal() * eps;

            foreach (var p in self.Points)
            {
                bb.ExtendBy(p + v);
                bb.ExtendBy(p - v);
            }
            return(bb);
        }
コード例 #9
0
        public void CanQueryPointsNotNearPolygon_3()
        {
            var q = new Polygon3d(
                new V3d(.0, .0, .3), new V3d(.25, .0, .3), new V3d(.5, .5, .3), new V3d(.0, .5, .3)
                );

            var rs = CreateRegularPointsInUnitCube(4, 1)
                     .QueryPointsNotNearPolygon(q, 0.2)
                     .SelectMany(x => x.Positions)
                     .ToArray()
            ;

            Assert.IsTrue(rs.Length == 64 - 2 * 3);
        }
コード例 #10
0
        /// <summary>
        /// Compute the triangulation of the supplied concave polygon and put
        /// the triangle vertex indices into the supplied array starting at
        /// the supplied triangle vertex index.
        /// </summary>
        /// <returns>the number of triangles in the triangulation</returns>
        private static int ComputeTriangulationOfConcavePolygon(
            this Polygon3d polygon, double absoluteEpsilon,
            int triangleVertexIndex, int[] triangleIndexArray)
        {
            var polyList = polygon.ComputeNonConcaveSubPolygons(absoluteEpsilon);

            foreach (var pia in polyList)
            {
                int tc = polygon.GetPointArray().ComputeTriangulationOfNonConcavePolygon(
                    pia, absoluteEpsilon, triangleVertexIndex,
                    triangleIndexArray);
                triangleVertexIndex += 3 * tc;
            }
            return(polygon.PointCount - 2);
        }
コード例 #11
0
        /// <summary>
        /// Count points approximately NOT within maxDistance of given polygon.
        /// Result is always equal or greater than exact number.
        /// Faster than CountPointsNotNearPolygon.
        /// </summary>
        public static long CountPointsApproximatelyNotNearPolygon(
            this IPointCloudNode node, Polygon3d polygon, double maxDistance, int minCellExponent = int.MinValue
            )
        {
            var bounds = polygon.BoundingBox3d(maxDistance);
            var plane  = polygon.GetPlane3d();
            var w2p    = plane.GetWorldToPlane();
            var poly2d = new Polygon2d(polygon.GetPointArray().Map(p => w2p.TransformPos(p).XY));

            return(CountPointsApproximately(node,
                                            n => !n.BoundingBoxExactGlobal.Intersects(bounds),
                                            n => false,
                                            minCellExponent
                                            ));
        }
コード例 #12
0
        public static List <int[]> ComputeNonConcaveSubPolygons(
            this Polygon3d polygon, double absoluteEpsilon)
        {
            V3d    normal = polygon.ComputeDoubleAreaNormal();
            double len2   = normal.LengthSquared;

            if (len2 < absoluteEpsilon * absoluteEpsilon)
            {
                return(new int[polygon.PointCount].SetByIndex(i => i).IntoList());
            }

            M44d.NormalFrame(V3d.Zero, normal * (1.0 / Fun.Sqrt(len2)), out M44d local2global, out M44d global2local);
            var polygon2d = polygon.ToPolygon2d(p => global2local.TransformPos(p).XY);

            return(polygon2d.ComputeNonConcaveSubPolygons(absoluteEpsilon));
        }
コード例 #13
0
        /// <summary>
        /// All points NOT within maxDistance of given polygon.
        /// </summary>
        public static IEnumerable <Chunk> QueryPointsNotNearPolygon(
            this IPointCloudNode node, Polygon3d polygon, double maxDistance, int minCellExponent = int.MinValue
            )
        {
            var bounds = polygon.BoundingBox3d(maxDistance);
            var plane  = polygon.GetPlane3d();
            var w2p    = plane.GetWorldToPlane();
            var poly2d = new Polygon2d(polygon.GetPointArray().Map(p => w2p.TransformPos(p).XY));

            return(QueryPoints(node,
                               n => !n.BoundingBoxExactGlobal.Intersects(bounds),
                               n => false,
                               p => !polygon.Contains(plane, w2p, poly2d, maxDistance, p, out double d),
                               minCellExponent
                               ));
        }
コード例 #14
0
        /// <summary>
        /// Count points within maxDistance of given polygon.
        /// </summary>
        public static long CountPointsNearPolygon(
            this PointSetNode node, Polygon3d polygon, double maxDistance, int minCellExponent = int.MinValue
            )
        {
            var bounds = polygon.BoundingBox3d(maxDistance);
            var plane  = polygon.GetPlane3d();
            var w2p    = plane.GetWorldToPlane();
            var poly2d = new Polygon2d(polygon.GetPointArray().Map(p => w2p.TransformPos(p).XY));

            return(CountPoints(node,
                               n => false,
                               n => !n.BoundingBox.Intersects(bounds),
                               p => polygon.Contains(plane, w2p, poly2d, maxDistance, p, out double d),
                               minCellExponent
                               ));
        }
コード例 #15
0
        public void CanQueryPointsNotNearPolygon_1()
        {
            var pointset = CreateRandomPointsInUnitCube(1024, 64);

            var q = new Polygon3d(new V3d(0.4, 0.4, 0.5), new V3d(0.6, 0.4, 0.5), new V3d(0.6, 0.6, 0.5), new V3d(0.4, 0.6, 0.5));

            var ps = pointset.QueryPointsNotNearPolygon(q, 0.1).SelectMany(x => x.Positions).ToList();

            Assert.IsTrue(pointset.PointCount > ps.Count);

            var bb = new Box3d(new V3d(0.4, 0.4, 0.4), new V3d(0.6, 0.6, 0.6));

            foreach (var p in ps)
            {
                Assert.IsTrue(!bb.Contains(p));
            }
        }
コード例 #16
0
        public void CanQueryPointsNearPolygon_Performance()
        {
            var sw       = new Stopwatch();
            var pointset = CreateRandomPointsInUnitCube(1024 * 1024, 32);

            var q     = new Polygon3d(new V3d(0.4, 0.4, 0.5), new V3d(0.41, 0.4, 0.5), new V3d(0.41, 0.41, 0.5), new V3d(0.4, 0.41, 0.5));
            var plane = new Plane3d(new V3d(0.4, 0.4, 0.5), new V3d(0.41, 0.4, 0.5), new V3d(0.41, 0.41, 0.5));

            sw.Restart();
            var ps0 = pointset.QueryPointsNearPolygon(q, 0.01).SelectMany(x => x.Positions).ToList();
            var t0  = sw.Elapsed.TotalSeconds;

            sw.Restart();
            var ps1 = pointset.QueryPointsNearPlane(plane, 0.01).ToList();
            var t1  = sw.Elapsed.TotalSeconds;

            Assert.IsTrue(t0 * 10 < t1);
        }
コード例 #17
0
ファイル: GJK.cs プロジェクト: bonomali/Ibasa
        public static Vector3d Support(Polygon3d hull, Vector3d direction)
        {
            Vector3d result = Vector3d.Zero;
            double   maxdot = double.NegativeInfinity;

            for (int i = 0; i < hull.Count; ++i)
            {
                var point = (Vector3d)hull[i];

                double dot = Vector.Dot(point, direction);
                if (dot > maxdot)
                {
                    maxdot = dot;
                    result = point;
                }
            }
            return(result);
        }
コード例 #18
0
        /// <summary>
        /// Enumerates all pairs of coincident vertices (as pairs of vertex indices).
        /// </summary>
        public static IEnumerable <Pair <int> > GetCoincidentPoints(
            this Polygon3d polygon, double toleranceAbsolute)
        {
            if (toleranceAbsolute < 0.0)
            {
                throw new ArgumentOutOfRangeException();
            }
            var pc = polygon.PointCount;

            for (int pi = 0; pi < pc; pi++)
            {
                for (int pj = pi + 1; pj < pc; pj++)
                {
                    if (polygon[pi].ApproxEqual(polygon[pj], toleranceAbsolute))
                    {
                        yield return(Pair.Create(pi, pj));
                    }
                }
            }
        }
コード例 #19
0
        /// <summary>
        /// Computes the normal with the length of twice the polygon area as
        /// the sum of  the simple triangulation cross-product normals.
        /// NOTE: This has been tested to be slightly faster and slightly more
        /// accurate than the computation via the 3d Newell normal
        /// (see Math.Tests/GeometryTests, rft 2013-05-04).
        /// </summary>
        public static V3d ComputeDoubleAreaNormal(this Polygon3d polygon)
        {
            var pc = polygon.PointCount;

            if (pc < 3)
            {
                return(V3d.Zero);
            }
            V3d p0     = polygon[0];
            V3d e0     = polygon[1] - p0;
            V3d normal = V3d.Zero;

            for (int pi = 2; pi < pc; pi++)
            {
                var e1 = polygon[pi] - p0;
                normal += e0.Cross(e1);
                e0      = e1;
            }
            return(normal);
        }
コード例 #20
0
        /// <summary>
        /// The geometric center of a 3-dimensional, flat polygon.
        /// WARNING: UNTESTED!
        /// </summary>
        public static V3d ComputeCentroid(this Polygon3d polygon)
        {
            var pc = polygon.PointCount;

            if (pc < 3)
            {
                return(V3d.Zero);
            }
            V3d p0 = polygon[0], p1 = polygon[1];
            V3d e0       = p1 - p0;
            var p2       = polygon[2];
            var e1       = p2 - p0;
            var normal   = e0.Cross(e1);
            var area2    = normal.Length;
            var centroid = area2 * (p0 + p1 + p2);

            p1 = p2; e0 = e1;
            for (int pi = 3; pi < pc; pi++)
            {
                p2 = polygon[pi]; e1 = p2 - p0;
                var n  = e0.Cross(e1);
                var a2 = Fun.Sign(normal.Dot(n)) * n.Length;
                area2    += a2;
                centroid += a2 * (p0 + p1 + p2);
                p1        = p2; e0 = e1;
            }
            if (area2 > Constant <double> .PositiveTinyValue)
            {
                return(centroid * (Constant.OneThird / area2));
            }
            else if (area2 < Constant <double> .NegativeTinyValue)
            {
                return(centroid * (-Constant.OneThird / area2));
            }
            else
            {
                return(V3d.Zero);
            }
        }
コード例 #21
0
        /// <summary>
        /// Enumerates all pairs of edges that intersect (as pairs of edge indices).
        /// </summary>
        public static IEnumerable <Pair <int> > GetSelfIntersections(
            this Polygon3d polygon, double toleranceAbsolute)
        {
            if (toleranceAbsolute < 0.0)
            {
                throw new ArgumentOutOfRangeException();
            }
            var pc = polygon.PointCount;
            var la = polygon.GetEdgeLineArray();

            for (int i = 0; i < pc; i++)
            {
                int jmax = (i > 0) ? pc : pc - 1;
                for (int j = i + 2; j < jmax; j++)
                {
                    if (la[i].Intersects(la[j], toleranceAbsolute))
                    {
                        yield return(Pair.Create(i, j));
                    }
                }
            }
        }
コード例 #22
0
 /// <summary>
 /// Computes the supporting plane of the polygon via the vertex centroid
 /// and the sum of  the simple triangulation cross-product normals.
 /// NOTE: This has been tested to be slightly faster and slightly more
 /// accurate than the computation via the 3d Newell normal
 /// (see Math.Tests/GeometryTests, rft 2013-05-04).
 /// </summary>
 public static Plane3d ComputePlane3d(this Polygon3d polygon)
 {
     return(new Plane3d(polygon.ComputeNormal(), polygon.ComputeVertexCentroid()));
 }
コード例 #23
0
 /// <summary>
 /// Computes the normalized normal as the sum of  the simple
 /// triangulation cross-product normals.
 /// NOTE: This has been tested to be slightly faster and slightly more
 /// accurate than the computation via the 3d Newell normal
 /// (see Math.Tests/GeometryTests, rft 2013-05-04).
 /// </summary>
 public static V3d ComputeNormal(this Polygon3d polygon)
 {
     return(polygon.ComputeDoubleAreaNormal().Normalized);
 }
コード例 #24
0
 /// <summary>
 /// Returns true if at least one vertex
 /// both outgoing edges meet at an angle that
 /// is less than the given threshold.
 /// </summary>
 public static bool HasSpikes(
     this Polygon3d self, double toleranceInDegrees = 0.1)
 {
     return(GetSpikes(self, toleranceInDegrees).Any());
 }
コード例 #25
0
 /// <summary>
 /// Computes the area as the length of the sum of  the simple
 /// triangulation cross-product normals.
 /// NOTE: This has been tested to be slightly faster and slightly more
 /// accurate than the computation via the 3d Newell normal
 /// (see Math.Tests/GeometryTests, rft 2013-05-04).
 /// </summary>
 public static double ComputeArea(this Polygon3d polygon)
 {
     return(0.5 * polygon.ComputeDoubleAreaNormal().Length);
 }
コード例 #26
0
ファイル: Polygon3d.cs プロジェクト: lcl1153406/aardvark.base
 public static V3d ComputeNormal(this Polygon3d polygon)
 => polygon.ComputeDoubleAreaNormal().Normalized;
コード例 #27
0
 /// <summary>
 /// Returns true if at least two edges intersect.
 /// </summary>
 public static bool IsSelfIntersecting(
     this Polygon3d self, double toleranceAbsolute = 1e-10)
 {
     return(GetSelfIntersections(self, toleranceAbsolute).Any());
 }
コード例 #28
0
 /// <summary>
 /// Returns true if at least two vertices are coincident.
 /// </summary>
 public static bool HasCoincidentPoints(
     this Polygon3d polygon, double toleranceAbsolute)
 {
     return(GetCoincidentPoints(polygon, toleranceAbsolute).Any());
 }
コード例 #29
0
 /// <summary>
 /// Returns the plane through the first 3 points of the polygon.
 /// </summary>
 public static Plane3d GetPlane3d(this Polygon3d polygon)
 {
     return(new Plane3d(polygon[0], polygon[1], polygon[2]));
 }
コード例 #30
0
 public static Polygon2d ToPolygon2d(
     this Polygon3d polygon, Func <V3d, int, V2d> point_index_copyFun)
 {
     return(new Polygon2d(polygon.GetPointArray(point_index_copyFun)));
 }