private void OnDrawGizmos()
        {
            Polygon2 pol0 = CreatePolygon2(Points0);
            Polygon2 pol1 = CreatePolygon2(Points1);

            Orientations orientation0;
            bool         pol0Convex = pol0.IsConvex(out orientation0);
            Orientations orientation1;
            bool         pol1Convex = pol1.IsConvex(out orientation1);

            FiguresColor();
            DrawPolygon(pol0);
            DrawPolygon(pol1);

            if (pol0Convex && pol1Convex && orientation0 == Orientations.CCW && orientation1 == Orientations.CCW)
            {
                bool test = Intersection.TestConvexPolygon2ConvexPolygon2(pol0, pol1);
                Logger.LogInfo("Intersection: " + test);
            }
            else
            {
                Logger.LogError("Polygons are incorrect." +
                                "   Pol0Convex: " + pol0Convex + "   Pol0Ori: " + orientation0 + "   Pol1Convex: " + pol1Convex + "   Pol1Ori: " + orientation1);
            }
        }
示例#2
0
        List <Polygon2> TileColliderDataToPolygons(TileColliderData tileColliderData, Vector2 scale)
        {
            List <Polygon2> polygons = new List <Polygon2>();

            if (tileColliderData.vertices.Length > 0)
            {
                Polygon2 polygon = new Polygon2(tileColliderData.vertices.Length);

                for (int i = 0; i < tileColliderData.vertices.Length; i++)
                {
                    Vector2 v = tileColliderData.vertices[i];

                    polygon.points[i] = v;
                }

                if (scale != Vector2.one)
                {
                    polygon.ToScaleSelf(scale);
                }

                polygons.Add(polygon);
            }

            return(polygons);
        }
示例#3
0
        /// <summary>
        /// Checks what entities if any intersect any of the specified traces
        /// </summary>
        /// <param name="traces">The set of traces to check</param>
        /// <param name="from">Where the traces start at</param>
        /// <param name="excludeIds">The set of collidable ids which are excluded from this search</param>
        /// <param name="excludeFlags">Collidables with any of these flags are excluded</param>
        /// <returns>A list of all collidables inside any of the specified traces</returns>
        public List <T> TraceExhaust(List <Polygon2> traces, Vector2 from, HashSet <int> excludeIds, long excludeFlags)
        {
            List <T> result    = new List <T>();
            int      tracesLen = traces.Count;

            for (int i = 0, len = Collidables.Count; i < len; i++)
            {
                T collidable = Collidables[i];
                if (excludeIds.Contains(collidable.ID))
                {
                    continue;
                }
                if ((collidable.Flags & excludeFlags) != 0)
                {
                    continue;
                }

                for (int j = 0; j < tracesLen; j++)
                {
                    if (Polygon2.Intersects(collidable.Bounds, traces[j], collidable.Position, from, true))
                    {
                        result.Add(collidable);
                        break;
                    }
                }
            }

            return(result);
        }
示例#4
0
        /// <summary>
        /// Checks if there are any entities intersecting any of the given polygons which do not have an ID
        /// in excludeIds and do not have any of the exclude flags.
        ///
        /// Returns true if there are no intersecting entities, returns false if there are intersecting entities
        /// </summary>
        /// <param name="traces">The polygons to check if any entities intersect</param>
        /// <param name="from">The offset for the traces</param>
        /// <param name="excludeIds">Ids of collidables which will be excluded in this check</param>
        /// <param name="excludeFlags">Any collibable which has any of these flags is excluded from this check</param>
        /// <returns>True if there are entities in traces located at from, False otherwise</returns>
        public bool Trace(List <Polygon2> traces, Vector2 from, HashSet <int> excludeIds, long excludeFlags)
        {
            int tracesLen = traces.Count;

            for (int i = 0, len = Collidables.Count; i < len; i++)
            {
                T collidable = Collidables[i];
                if (excludeIds.Contains(collidable.ID))
                {
                    continue;
                }
                if ((collidable.Flags & excludeFlags) != 0)
                {
                    continue;
                }

                for (int j = 0; j < tracesLen; j++)
                {
                    if (Polygon2.Intersects(collidable.Bounds, traces[j], collidable.Position, from, true))
                    {
                        return(false);
                    }
                }
            }
            return(true);
        }
示例#5
0
    public static List <Polygon2> CreateFromCompositeCollider(CompositeCollider2D compositeCollider)
    {
        List <Polygon2> list = new List <Polygon2>();

        if (compositeCollider != null)
        {
            int pathCount = compositeCollider.pathCount;


            for (int i = 0; i < pathCount; i++)
            {
                int pointCount = compositeCollider.GetPathPointCount(i);

                Vector2[] pointsInPath = new Vector2[pointCount];

                compositeCollider.GetPath(i, pointsInPath);

                Polygon2 polygon = new Polygon2(pointsInPath);

                polygon.Normalize();

                list.Add(polygon);
            }
        }

        return(list);
    }
示例#6
0
        public void InitializeColliders()
        {
            localColliders.Clear();
            worldColliders.Clear();
            colliderTransform.Clear();

            foreach (Transform transform in gameObject.transform)
            {
                EdgeCollider2D[]    edgeColliders    = transform.GetComponents <EdgeCollider2D>();
                PolygonCollider2D[] polygonColliders = transform.GetComponents <PolygonCollider2D>();

                if (edgeColliders.Length > 0)
                {
                    foreach (EdgeCollider2D collider in edgeColliders)
                    {
                        Polygon2 poly = Polygon2ListCollider2D.CreateFromEdgeCollider(collider);

                        localColliders.Add(poly);
                        colliderTransform.Add(transform);
                    }
                }

                if (polygonColliders.Length > 0)
                {
                    foreach (PolygonCollider2D collider in polygonColliders)
                    {
                        Polygon2 poly = Polygon2ListCollider2D.CreateFromPolygonColliderToLocalSpace(collider)[0];

                        localColliders.Add(poly);
                        colliderTransform.Add(transform);
                    }
                }
            }
        }
示例#7
0
        static private void ShadowForVertex(Polygon2 polygon, Vector2 position)
        {
            Vector2[] pointsList  = polygon.points;
            int       pointsCount = pointsList.Length;

            for (int x = 0; x < pointsCount; x++)
            {
                pair.A.x = pointsList[(x) % pointsCount].x + position.x;
                pair.A.y = pointsList[(x) % pointsCount].y + position.y;

                pair.B.x = pointsList[(x + 2) % pointsCount].x + position.x;
                pair.B.y = pointsList[(x + 2) % pointsCount].y + position.y;

                Pair2D edge_world = pair;

                Vector2 edgePosition;
                edgePosition.x = (float)(pair.A.x + pair.B.x) / 2;
                edgePosition.y = (float)(pair.A.y + pair.B.y) / 2;

                float edgeRotation = (float)Math.Atan2(pair.B.y - pair.A.y, pair.B.x - pair.A.x);

                float edgeSize = (float)Vector2D.Distance(pair.A, pair.B) / 2;

                pass.edgePosition = edgePosition;
                pass.edgeRotation = edgeRotation;
                pass.edgeSize     = edgeSize;
                pass.coreSize     = ShadowEngine.light.coreSize;

                pass.Generate();
                pass.SetVars();
                pass.Draw();
            }
        }
示例#8
0
        public static void Main(string[] args)
        {
//         var canvas = host.CreateAndAddCanvas(0);
//         var smp = SectorMetadataPresets.Blank2D;
//         var punchResult = PolygonOperations.Punch()
//                                            .Include(smp.LocalIncludedContours)
////                          .Exclude(smp.LocalExcludedContours)
//                                            .Exclude(Polygon2.CreateRect(-10000, -10000, 20000, 20000))
//                                            .Exclude(new []{(Polygon2.CreateRect(-8000, -8000, 16000, 16000), true)})
//                                            .Execute();
//
//         canvas.Transform = Matrix4x4.CreateScale(500 / 60000.0f) * Matrix4x4.CreateTranslation(500, 300, 0);
//         canvas.DrawPolyNode(punchResult);
//         return;

            //var subjectPolygon = Polygon2.CreateCircle(0, 0, 100, 16);
            var n              = 128;
            var random         = new Random(0);
            var subjectPolygon = new Polygon2(
                Util.Generate(
                    n,
                    i => DoubleVector2.FromRadiusAngle(random.Next(10, 150), -i * Math.PI * 2 / n).LossyToIntVector2())
                .ToList());

            var clipPolygon = Polygon2.CreateRect(-80, -80, 160, 160);

            RenderSomething(0, subjectPolygon, clipPolygon);

            var offsetSubjectPolygon = new Polygon2(subjectPolygon.Points.Map(p => new IntVector2(0, 240) + p).ToList());

            RenderSomething(1, offsetSubjectPolygon, clipPolygon);
        }
示例#9
0
 public PolyPairTestData(string name, Polygon2 a, Polygon2 b, Polygon2 r)
 {
     Name = name;
     A    = a;
     B    = b;
     R    = r;
 }
示例#10
0
        void TryCastHealingStrike(JToken parsed)
        {
            if (Entity.SpellCooldowns.ContainsKey(SpellFactory.HEALING_STRIKE_INDEX))
            {
                return;
            }

            var currWorld = Program.State.World;
            var currEnt   = currWorld.GetByID(Entity.ID);

            if (!ManaCheck(currEnt, SpellFactory.HEALING_STRIKE_MANA))
            {
                return;
            }
            Vector2 target = new Vector2((float)parsed[2]["x"], (float)parsed[2]["y"]);
            var     mind   = Polygon2.MinDistance(currEnt.Attributes.Bounds, currEnt.Location, target);

            if (mind != null && mind.Item2 > SpellFactory.HEALING_STRIKE_RANGE)
            {
                return;
            }

            var mut = new EntityCastSpellMutation(Entity.ID, SpellFactory.CreateHealingStrike(target));

            Program.QueuedMutations[mut.Time].Enqueue(mut);
            _CastingSpell = true;
            UpdateVelocity();
        }
示例#11
0
        static void Main(string[] args)
        {
            Console.WriteLine("Fact: " + (GeometryFactory2Double.Instance != null));
            GeometryFactory2Base <double> factory = GeometryFactory2Double.Instance;

            Console.WriteLine("Factory is " + (factory == null ? "null" : "not null"));

            if (factory != null)
            {
                Point2 <double> pt = factory.ConstructPoint(43, 22);
                Console.WriteLine("Created point: " + pt.ToString());
                Ring2 <double>    rg = factory.ConstructRing(new Point2 <double>[] { factory.ConstructPoint(22.45, 33.33), factory.ConstructPoint(23.45, 33.33), factory.ConstructPoint(22.45, 35.33) });
                Polygon2 <double> pl = factory.ConstructPolygon(rg);

                if (rg != null)
                {
                    Console.WriteLine("Created ring: " + rg.ToString());
                    object o = Osrs.Numerics.Spatial.Postgres.NpgSpatialUtils.ToPGis(rg);
                    Console.WriteLine("Created PG Geometry: " + (o != null).ToString());
                }

                if (pl != null)
                {
                    Console.WriteLine(GeoJsonUtils.ToGeoJson(pl).ToString());
                }
            }

            Console.WriteLine("ALL DONE");
            Console.ReadLine();
        }
示例#12
0
            private Polygon2 FindUntouchedRingsB()
            {
                Contract.Ensures(Contract.Result <IEnumerable <Ring2> >() != null);
                if (VisitedCrossingsRingIndicesB.Count == 0)
                {
                    return(B);
                }

                var missingCount = B.Count - VisitedCrossingsRingIndicesB.Count;
                var results      = new Polygon2(missingCount);

                if (missingCount == 0)
                {
                    return(results);
                }

                for (int i = 0; i < B.Count; i++)
                {
                    if (!VisitedCrossingsRingIndicesB.Contains(i))
                    {
                        results.Add(B[i]);
                    }
                }
                return(results);
            }
示例#13
0
            private IntersectionResults BuildFinalResults(Polygon2 intersectedPolygon)
            {
                Contract.Requires(intersectedPolygon != null);
                Contract.Ensures(Contract.Result <IntersectionResults>() != null);
                Contract.Ensures(intersectedPolygon.Count >= Contract.OldValue(intersectedPolygon).Count);

                if (intersectedPolygon.Count == 0)
                {
                    var untouchedA = FindUntouchedRingsA();
                    var untouchedB = FindUntouchedRingsB();
                    intersectedPolygon.AddRange(QualifyRings(untouchedA, untouchedB, true));
                    intersectedPolygon.AddRange(QualifyRings(untouchedB, untouchedA, false));
                }
                else
                {
                    var intersectedResultTree = new RingBoundaryTree(intersectedPolygon);
                    intersectedPolygon.AddRange(
                        FilterQualifiedRingsToBoundaryTree(
                            QualifyRings(FindUntouchedRingsA(), B, true),
                            intersectedResultTree
                            )
                        );
                    intersectedPolygon.AddRange(
                        FilterQualifiedRingsToBoundaryTree(
                            QualifyRings(FindUntouchedRingsB(), A, false),
                            intersectedResultTree
                            )
                        );
                }
                return(new IntersectionResults {
                    Polygon = intersectedPolygon
                });
            }
示例#14
0
        private void OnDrawGizmos()
        {
            List <Vector2> pointsList = new List <Vector2>();

            foreach (Transform tr in Points)
            {
                if (tr != null)
                {
                    pointsList.Add(tr.position);
                }
            }
            Polygon2 pol = new Polygon2(pointsList.ToArray());

            Gizmos.color = Color.gray;

            for (int i0 = 0, i1 = pol.VertexCount - 1; i0 < pol.VertexCount; i1 = i0, i0++)
            {
                Gizmos.DrawLine(pol[i0], pol[i1]);
            }

            Orientations or;
            bool         convex   = pol.IsConvex(out or);
            bool         hasDegen = pol.HasZeroCorners();

            Logger.LogInfo("Area: " + pol.CalcArea() + "     Per: " + pol.CalcPerimeter() + "     Convex: " + convex + "     Orient: " + or + "     ZeroCorners: " + hasDegen);
        }
    static public List <Polygon2> CreateFromPolygonColliderToLocalSpace(PolygonCollider2D collider)
    {
        List <Polygon2> result = new List <Polygon2>();

        if (collider != null && collider.pathCount > 0)
        {
            Vector2[] array = collider.GetPath(0);

            Polygon2 newPolygon = new Polygon2(array.Length);

            for (int i = 0; i < array.Length; i++)
            {
                Vector2 p = array[i];

                newPolygon.points[i] = (p + collider.offset);
            }

            result.Add(newPolygon);

            for (int i = 1; i < collider.pathCount; i++)
            {
                Vector2[] arrayHole = collider.GetPath(i);

                Polygon2 hole = new Polygon2(arrayHole.Length);

                for (int x = 0; x < arrayHole.Length; x++)
                {
                    hole.points[i] = arrayHole[x] + collider.offset;
                }

                result.Add(hole);
            }
        }
        return(result);
    }
示例#16
0
        private static List <Ring2> QualifyRings(
            Polygon2 untouchedRings,
            Polygon2 polygon,
            bool qualifyEqual
            )
        {
            Contract.Requires(untouchedRings != null);
            Contract.Requires(polygon != null);
            Contract.Ensures(Contract.Result <List <Ring2> >() != null);
            Contract.Ensures(Contract.ForAll(Contract.Result <List <Ring2> >(), x => null != x));

            var result   = new List <Ring2>();
            var ringTree = new RingBoundaryTree(polygon);

            foreach (var ring in untouchedRings)
            {
                Contract.Assume(ring != null);
                // TODO: speed this up through some kind of magic, like RingBoundaryTree or something
                // TODO: var eq = new SpatialEqualityComparerThing(ringA); var stuff = otherRings.Where(r = > eq.SpatiallyEqual(r));
                if (polygon.Any(r => ring.SpatiallyEqual(r)))
                {
                    if (qualifyEqual)
                    {
                        result.Add(ring.Clone());
                    }
                }
                else if (ringTree.NonIntersectingContains(ring))
                {
                    result.Add(ring.Clone());
                }
            }
            Contract.Assume(Contract.ForAll(result, x => null != x));
            return(result);
        }
示例#17
0
        /// <summary>
        /// Find a smallest bounding rectangle.
        /// </summary>
        /// <returns></returns>
        public Vector2[] FindBounds(Polygon2 polygon)
        {
            if (polygon == null)
            {
                throw new ArgumentNullException("polygon");
            }

            var minified = new Polygon2(polygon.ToVertices().Distinct());

            minified.OrientCounterClockwise();
            var vertices = minified.ToVertices().ToArray();

            if (vertices.Count() == 0)
            {
                return(new Vector2[0]);
            }

            // This algorithm assumes the polygon is oriented counter-clockwise.

            // Get ready;
            ResetBoundingRect(vertices);

            // Check all possible bounding rectangles.
            for (int i = 0; i < vertices.Count(); i++)
            {
                CheckNextBoundingRectangle(vertices);
            }

            // Return the best result.
            return(_bestRectangle);
        }
示例#18
0
        /// <summary>
        /// Load existing collision
        /// </summary>
        /// <param name="buffer"></param>
        public void Load(byte[] buffer)
        {
            try
            {
                using (BinaryReader b = new BinaryReader(new MemoryStream(buffer)))
                {
                    var polygonCount = b.ReadInt32();

                    for (int i = 0; i < polygonCount; i++)
                    {
                        var polygon  = new Polygon2();
                        var pointNum = b.ReadInt32();

                        for (int p = 0; p < pointNum; p++)
                        {
                            var point = new K2DPosition();
                            point.X = b.ReadInt32();
                            point.Y = b.ReadInt32();
                            polygon.Points.Add(point);
                        }

                        Polygons.Add(polygon);
                    }
                }

                XLog.WriteLine(Levels.Good, "Ok");
            }
            catch (Exception exception)
            {
                Blank();
                XLog.WriteLine(Levels.Error, "Failed");
                XLog.WriteLine(Levels.Fatal, "NfaManager::Load<Exception> -> {0}", exception);
            }
        }
示例#19
0
    static public List <Polygon2> CreateFromMeshCollider(MeshCollider meshCollider)
    {
        List <Polygon2> newPolygons = new List <Polygon2>();

        Vector2 size = new Vector2(1, 1);

        Vector2 offset = Vector2.zero;

        Mesh mesh = meshCollider.sharedMesh;

        int length = mesh.triangles.GetLength(0);

        for (int i = 0; i < length; i = i + 3)
        {
            Vector2 vecA = mesh.vertices [mesh.triangles [i]];
            Vector2 vecB = mesh.vertices [mesh.triangles [i + 1]];
            Vector2 vecC = mesh.vertices [mesh.triangles [i + 2]];

            Polygon2 poly = new Polygon2(3);
            poly.points[0] = vecA;
            poly.points[1] = vecB;
            poly.points[2] = vecC;

            newPolygons.Add(poly);
        }

        return(newPolygons);
    }
 protected void DrawPolygon(Polygon2 polygon)
 {
     for (int i0 = 0, i1 = polygon.VertexCount - 1; i0 < polygon.VertexCount; i1 = i0, ++i0)
     {
         Gizmos.DrawLine(polygon[i0], polygon[i1]);
     }
 }
示例#21
0
        private void OnDrawGizmos()
        {
            Ray2     ray     = CreateRay2(Ray);
            Polygon2 polygon = CreatePolygon2(Polygon);

            Ray2Polygon2Intr info;
            bool             find = Intersection.FindRay2Polygon2(ref ray, polygon, out info);

            FiguresColor();
            DrawRay(ref ray);
            DrawPolygon(polygon);

            if (find)
            {
                ResultsColor();
                if (info.IntersectionType == IntersectionTypes.Point)
                {
                    DrawPoint(info.Point0);
                }
                else if (info.IntersectionType == IntersectionTypes.Segment)
                {
                    DrawSegment(info.Point0, info.Point1);
                    DrawPoint(info.Point0);
                    DrawPoint(info.Point1);
                }
            }

            LogInfo(info.IntersectionType);
        }
示例#22
0
 public static void DrawPolygonContour(this IDebugCanvas canvas, Polygon2 poly, StrokeStyle strokeStyle)
 {
     for (var i = 0; i < poly.Points.Count - 1; i++)
     {
         canvas.DrawLineStrip(poly.Points.Map(ToDV3), strokeStyle);
     }
 }
示例#23
0
 public PolyPairTestData(RingPairTestData data, Polygon2 result) {
     Name = data.Name;
     A = new Polygon2(data.A);
     B = new Polygon2(data.B);
     R = null == result ? null : new Polygon2(result);
     CrossingPoints = (data.CrossingPoints ?? Enumerable.Empty<Point2>()).ToList();
 }
示例#24
0
		private Polygon2 GetRectPolygon() {
			if (rectPolygon == null) {
				rectPolygon = new Polygon2(4);
			}

        	return(rectPolygon);
		}
示例#25
0
    public List <Polygon2> GetWorldPolygons(LightTilemapCollider.Base tilemap)
    {
        if (worldPolygons == null)
        {
            List <Polygon2> localPolygons = GetLocalPolygons(tilemap);
            if (worldPolygonsCache == null)
            {
                worldPolygons      = new List <Polygon2>();
                worldPolygonsCache = worldPolygons;

                UpdateTransform(tilemap);

                foreach (Polygon2 polygon in localPolygons)
                {
                    Polygon2 worldPolygon = polygon.Copy();

                    if (scale != Vector2.one)
                    {
                        worldPolygon.ToScaleSelf(scale);
                    }

                    worldPolygon.ToScaleSelf(worldScale);
                    worldPolygon.ToRotationSelf((tilemap.transform.eulerAngles.z + rotation) * Mathf.Deg2Rad);
                    worldPolygon.ToOffsetSelf(worldPosition.Value);

                    worldPolygons.Add(worldPolygon);
                }
            }
            else
            {
                worldPolygons = worldPolygonsCache;

                UpdateTransform(tilemap);

                for (int i = 0; i < localPolygons.Count; i++)
                {
                    Polygon2 polygon      = localPolygons[i];
                    Polygon2 worldPolygon = worldPolygons[i];

                    for (int j = 0; j < polygon.points.Length; j++)
                    {
                        worldPolygon.points[j].x = polygon.points[j].x;
                        worldPolygon.points[j].y = polygon.points[j].y;
                    }

                    if (scale != Vector2.one)
                    {
                        worldPolygon.ToScaleSelf(scale);
                    }

                    worldPolygon.ToScaleSelf(worldScale);
                    worldPolygon.ToRotationSelf(tilemap.transform.eulerAngles.z * Mathf.Deg2Rad);
                    worldPolygon.ToOffsetSelf(worldPosition.Value);
                }
            }
        }

        return(worldPolygons);
    }
示例#26
0
 public static VisualPolygon Create(Polygon2 poly, Pen pen = null, Brush brush = null)
 {
     return(new VisualPolygon(poly)
     {
         Pen = pen,
         FillBrush = brush
     });
 }
示例#27
0
 internal override bool Overlaps(OverlapShape otherShape)
 {
     if (otherShape is OverlapBox b)
     {
         return(Polygon2.Intersects(b.Poly, Poly, b.Pos, Pos, b.Rot, Rot, false));
     }
     return(false);
 }
示例#28
0
 public PolyPairTestData(RingPairTestData data, Polygon2 result)
 {
     Name           = data.Name;
     A              = new Polygon2(data.A);
     B              = new Polygon2(data.B);
     R              = null == result ? null : new Polygon2(result);
     CrossingPoints = (data.CrossingPoints ?? Enumerable.Empty <Point2>()).ToList();
 }
 private static Polygon2 ReverseWinding(Polygon2 p)
 {
     if (null == p)
     {
         return(null);
     }
     return(new Polygon2(p.Select(ReverseWinding)));
 }
示例#30
0
 public static PostgisPolygon ToPGis(Polygon2 <double> geom)
 {
     if (geom != null)
     {
         return(new PostgisPolygon(Points(geom)));
     }
     return(null);
 }
示例#31
0
    public Polygon2 ToWorldSpace(Transform transform)
    {
        Polygon2 newPolygon = this.Copy();

        newPolygon.ToWorldSpaceSelf(transform);

        return(newPolygon);
    }
示例#32
0
 private static string PolygonToString(Polygon2 poly) {
     var sb = new StringBuilder();
     for (int index = 0; index < poly.Count; index++) {
         var ring = poly[index];
         sb.AppendFormat("Ring {0}:\n", index);
         sb.AppendLine(RingToString(ring));
     }
     return sb.ToString();
 }
        /// <summary>
        /// Calculates the resulting union of two polygon geometries.
        /// </summary>
        /// <param name="a">A polygon.</param>
        /// <param name="b">A polygon.</param>
        /// <returns>The union of <paramref name="a"/> and <paramref name="b"/>.</returns>
        public IPlanarGeometry Union(Polygon2 a, Polygon2 b) {
            Contract.Ensures((a != null || b != null) || Contract.Result<IPlanarGeometry>() == null);
            if (null == a)
                return b;
            if (null == b)
                return a;

            var result = InverseIntersectionOperation.Intersect(a, b) as Polygon2;
            return result;
        }
示例#34
0
        /// <summary>
        /// Calculates the symmetric difference between two polygons.
        /// </summary>
        /// <param name="a">A polygon.</param>
        /// <param name="b">A polygon.</param>
        /// <returns>The symmetric difference of <paramref name="a"/> and <paramref name="b"/>.</returns>
        public IPlanarGeometry Xor(Polygon2 a, Polygon2 b) {
            if (null == a)
                return b;
            if (null == b)
                return a;

            var removedFromA = _differenceOperation.Difference(a, b) as Polygon2;
            var removedFromB = _differenceOperation.Difference(b, a) as Polygon2;
            var unionedLeftovers = _unionOperation.Union(removedFromA, removedFromB);
            return unionedLeftovers;
        }
示例#35
0
 public void TestPolygon()
 {
     Polygon2 poly = new Polygon2() {
         vertices = new Vector2[]{
             new Vector2(1, 1),
             new Vector2(2, 1),
             new Vector2(1, 2)
         }
     };
     Assert.IsTrue(poly.Contains(new Vector2(1.1f, 1.1f)));
     Assert.IsTrue(poly.Contains(new Vector2(1.1f, 1.8f)));
     Assert.IsTrue(poly.Contains(new Vector2(1.49f, 1.49f)));
     Assert.IsFalse(poly.Contains(new Vector2(1.51f, 1.51f)));
     Assert.IsFalse(poly.Contains(new Vector2(0f, 0f)));
     Assert.IsTrue(poly.Contains(new Vector2(1f, 1f)));
 }
 private static Polygon2 ReverseWinding(Polygon2 p) {
     if (null == p)
         return null;
     return new Polygon2(p.Select(ReverseWinding));
 }
        /// <summary>
        /// Builds required crossing data. 
        /// </summary>
        /// <param name="crossings">The crossings to calculate. (Note: collection is modified)</param>
        /// <param name="a">The left hand polygon.</param>
        /// <param name="b">The right hand polygon.</param>
        private PolygonCrossingsAlgorithmKernel CreateIntersectionKernelFromCrossings(List<PolygonCrossing> crossings, Polygon2 a, Polygon2 b) {
            Contract.Requires(crossings != null);
            Contract.Requires(a != null);
            Contract.Requires(b != null);
            Contract.Ensures(Contract.Result<PolygonCrossingsAlgorithmKernel>() != null);

            var kernel = new PolygonCrossingsAlgorithmKernel(a, b, crossings);

            if (crossings.Count == 0)
                return kernel;

            foreach (var currentCrossing in crossings) {
                var ringIndexA = currentCrossing.LocationA.RingIndex;
                Contract.Assume(ringIndexA < a.Count);
                var ringA = a[ringIndexA];
                Contract.Assume(ringA != null);
                var crossingsOnRingA = kernel.RingCrossingsA.Get(ringIndexA);

                var priorPointA = FindPreviousRingPoint(currentCrossing, crossingsOnRingA, ringA, GetLocationA, PolygonCrossing.LocationAComparer.Default);
                var nextPointA = FindNextRingPoint(currentCrossing, crossingsOnRingA, ringA, GetLocationA, PolygonCrossing.LocationAComparer.Default);

                var ringIndexB = currentCrossing.LocationB.RingIndex;
                Contract.Assume(ringIndexB < b.Count);
                var ringB = b[ringIndexB];
                Contract.Assume(ringB != null);
                var crossingsOnRingB = kernel.RingCrossingsB.Get(ringIndexB);

                var priorPointB = FindPreviousRingPoint(currentCrossing, crossingsOnRingB, ringB, GetLocationB, PolygonCrossing.LocationBComparer.Default);
                var nextPointB = FindNextRingPoint(currentCrossing, crossingsOnRingB, ringB, GetLocationB, PolygonCrossing.LocationBComparer.Default);

                // based on the vectors, need to classify the crossing type
                currentCrossing.CrossType = PolygonCrossing.DetermineCrossingType(
                    (nextPointA - currentCrossing.Point).GetNormalized(),
                    (priorPointA - currentCrossing.Point).GetNormalized(),
                    (nextPointB - currentCrossing.Point).GetNormalized(),
                    (priorPointB - currentCrossing.Point).GetNormalized()
                );
            }

            foreach (var ringCrossings in kernel.RingCrossingsA.RingCrossings) {
                Contract.Assume(ringCrossings.Key >= 0 && ringCrossings.Key < a.Count);
                if (a[ringCrossings.Key].FillSide == RelativeDirectionType.Right) {
                    foreach (var crossing in ringCrossings.Value) {
                        Contract.Assume(crossing != null);
                        var crossLegType = crossing.CrossType & CrossingType.Parallel;
                        if (crossLegType == CrossingType.CrossToRight || crossLegType == CrossingType.DivergeRight)
                            kernel.Entrances.Add(crossing);
                        else if (crossLegType == CrossingType.CrossToLeft || crossLegType == CrossingType.ConvergeRight)
                            kernel.Exits.Add(crossing);
                    }
                }
                else {
                    foreach (var crossing in ringCrossings.Value) {
                        Contract.Assume(crossing != null);
                        var crossLegType = crossing.CrossType & CrossingType.Parallel;
                        if (crossLegType == CrossingType.CrossToLeft || crossLegType == CrossingType.DivergeLeft)
                            kernel.Entrances.Add(crossing);
                        else if (crossLegType == CrossingType.CrossToRight || crossLegType == CrossingType.ConvergeLeft)
                            kernel.Exits.Add(crossing);
                    }
                }
            }

            var sortedEntrances = kernel.Entrances.ToArray();
            Array.Sort(sortedEntrances, PolygonCrossing.LocationAComparer.CompareNonNull);
            Contract.Assume(kernel.Exits != null);
            var sortedExits = kernel.Exits.ToArray();
            Array.Sort(sortedExits, PolygonCrossing.LocationBComparer.CompareNonNull);

            for (int i = 0; i < sortedExits.Length; i++) {
                var exit = sortedExits[i];
                var locationIndex = Array.BinarySearch(sortedEntrances, exit, PolygonCrossing.LocationAComparer.Default);
                if(locationIndex >= 0)
                    kernel.ExitHops.Add(exit, sortedEntrances[locationIndex]);
            }
            for (int i = 0; i < sortedEntrances.Length; i++) {
                var entrance = sortedEntrances[i];
                var locationIndex = Array.BinarySearch(sortedExits, entrance, PolygonCrossing.LocationBComparer.Default);
                if(locationIndex >= 0)
                    kernel.EntranceHops.Add(entrance, sortedExits[locationIndex]);
            }

            return kernel;
        }
 /// <summary>
 /// Inverts a polygon.
 /// </summary>
 /// <param name="polygon">The polygon to get the inverse of.</param>
 /// <returns>An inverted polygon.</returns>
 public static Polygon2 Invert(Polygon2 polygon) {
     Contract.Ensures(polygon == null ? Contract.Result<Polygon2>() == null : Contract.Result<Polygon2>() != null);
     return null == polygon ? null : new Polygon2(polygon.Select(Invert));
 }
示例#39
0
 public PolyPairTestData(string name, Polygon2 a, Polygon2 b, Polygon2 r) {
     Name = name;
     A = a;
     B = b;
     R = r;
 }
 /// <summary>
 /// Determines the points that would need to be inserted into the resulting
 /// intersection geometry between the two given polygons, at the location where
 /// their boundaries cross.
 /// </summary>
 /// <param name="a">The first polygon to test.</param>
 /// <param name="b">The second polygon to test.</param>
 public List<PolygonCrossing> FindPointCrossings(Polygon2 a, Polygon2 b) {
     Contract.Ensures(Contract.Result<List<PolygonCrossing>>() != null);
     if (null == a || null == b)
         return new List<PolygonCrossing>(0);
     var crossingGenerator = new PolygonPointCrossingGenerator(a, b);
     var allCrossings = crossingGenerator.GenerateCrossings();
     return allCrossings;
 }
        public static void can_perform_box_and_donut_intersection_without_exception() {
            var donut = new Polygon2 {
				// outer boundary
				new Ring2(
					Enumerable.Range(0,8)
					.Select(i => i * 45 / 180.0 * Math.PI)
					.Select(t => new Point2(Math.Cos(t),Math.Sin(t)))
				){Hole = false},
				// inner hole
				new Ring2(
					Enumerable.Range(0,8)
					.Reverse()
					.Select(i => i * 45/ 180.0 * Math.PI)
					.Select(t => new Point2(Math.Cos(t)*0.5,Math.Sin(t)*0.5))
				) {Hole = true}
			};

            var box = new Polygon2(new Ring2(new[]{
				new Point2(0,0),
				new Point2(1,0),
				new Point2(1,1),
				new Point2(0,1)
			}) { Hole = false });

            var intersectionOperation = new PolygonIntersectionOperation();
            var result = intersectionOperation.Intersect(box, donut);
        }
 /// <summary>
 /// Calculates the resulting difference of polygon <paramref name="b"/> subtracted from polygon <paramref name="a"/>.
 /// </summary>
 /// <param name="a">The polygon to be subtracted from.</param>
 /// <param name="b">The polygon used to subtract from a.</param>
 /// <returns>The difference resulting from subtracting <paramref name="b"/> from <paramref name="a"/>.</returns>
 public IPlanarGeometry Difference(Polygon2 a, Polygon2 b) {
     var result = RightInverseIntersectionOperation.Intersect(a, b);
     return result;
 }
        public static void boxes_overlapping_top_half_holes() {
            var sourceData = _polyPairData["Boxes Overlapping: top half"];
            var inverseA = new Polygon2(sourceData.A[0].Reverse(), true);
            var inverseB = new Polygon2(sourceData.B[0].Reverse(), true);
            var expectedResult = inverseA;
            var result = _intersectionOperation.Intersect(inverseA, inverseB) as Polygon2;
            Assert.True(result.SpatiallyEqual(expectedResult));

            result = _intersectionOperation.Intersect(inverseB, inverseA) as Polygon2;
            Assert.True(result.SpatiallyEqual(expectedResult));
        }
        private static List<Ring2> QualifyRings(
            Polygon2 untouchedRings,
            Polygon2 polygon,
            bool qualifyEqual
        ) {
            Contract.Requires(untouchedRings != null);
            Contract.Requires(polygon != null);
            Contract.Ensures(Contract.Result<List<Ring2>>() != null);
            Contract.Ensures(Contract.ForAll(Contract.Result<List<Ring2>>(), x => null != x));

            var result = new List<Ring2>();
            var ringTree = new RingBoundaryTree(polygon);
            foreach (var ring in untouchedRings) {
                Contract.Assume(ring != null);
                // TODO: speed this up through some kind of magic, like RingBoundaryTree or something
                // TODO: var eq = new SpatialEqualityComparerThing(ringA); var stuff = otherRings.Where(r = > eq.SpatiallyEqual(r));
                if (polygon.Any(r => ring.SpatiallyEqual(r))) {
                    if (qualifyEqual)
                        result.Add(ring.Clone());
                }
                else if (ringTree.NonIntersectingContains(ring))
                    result.Add(ring.Clone());
            }
            Contract.Assume(Contract.ForAll(result, x => null != x));
            return result;
        }
示例#45
0
文件: Graphics.cs 项目: kgroat/Valor
 public abstract void DrawPolygon(FillMode fill, Polygon2 polygon);
 private PolygonCrossingsAlgorithmKernel CreateIntersectionKernel(Polygon2 a, Polygon2 b) {
     Contract.Requires(a != null);
     Contract.Requires(b != null);
     Contract.Ensures(Contract.Result<PolygonCrossingsAlgorithmKernel>() != null);
     var allCrossings = FindPointCrossings(a,b);
     return CreateIntersectionKernelFromCrossings(allCrossings, a, b);
 }
            public IntersectionResults Turtle(PointWinding fillWinding) {
                Contract.Ensures(Contract.Result<IntersectionResults>() != null);

                // now that it is all sorted the turtle starts scooting around, making new rings:
                //
                //           --==  .-----.                     |             ~ard
                //          --==  /       \                    |
                //      A  --==  <_______(`~`)   B             |   D         E
                //   ---*---------//-----//------*-------------*---*---------*---
                //                                             C   |
                //                                                 |
                //
                //         please wait while SPEED TURTLE!!! assembles your new rings

                var rings = new Polygon2();

                PolygonCrossing startEntrance;
                while ((startEntrance = FindNextStartableEntrance()) != null) {
                    var buildingRing = new List<Point2>();
                    var entrance = startEntrance;
                    do {
                        var exit = TraverseBSide(entrance, buildingRing);
                        if (exit == null) {
                            VisitEntrance(startEntrance); // may need to do this to be safe
                            break; // unmatched entrance
                        }
                        VisitExit(exit);
                        entrance = TraverseASide(exit, buildingRing);
                        if (entrance == null) {
                            break; // unmatched exit
                        }
                        VisitEntrance(entrance);
                    } while (entrance != startEntrance);
                    if (buildingRing.Count >= 3)
                        rings.Add(new Ring2(buildingRing)); // here is a new ring
                }

                if (fillWinding != PointWinding.Unknown)
                    rings.ForceFillWinding(fillWinding);

                return BuildFinalResults(rings);
            }
            [ContractVerification(false)] // TODO: remove when CC bugs are fixed
            public PolygonCrossingsAlgorithmKernel(Polygon2 a, Polygon2 b, List<PolygonCrossing> crossings) {
                Contract.Requires(a != null);
                Contract.Requires(b != null);
                Contract.Requires(crossings != null);
                Contract.Requires(Contract.ForAll(crossings, x => x != null));
                A = a;
                B = b;

                var ringCrossingsABuilder = new Dictionary<int, List<PolygonCrossing>>(a.Count);
                var ringCrossingsBBuilder = new Dictionary<int, List<PolygonCrossing>>(b.Count);
                foreach (var crossing in crossings) {
                    List<PolygonCrossing> list;
                    if (!ringCrossingsABuilder.TryGetValue(crossing.LocationA.RingIndex, out list)) {
                        list = new List<PolygonCrossing>();
                        ringCrossingsABuilder.Add(crossing.LocationA.RingIndex, list);
                    }
                    Contract.Assume(list != null);
                    list.Add(crossing);
                    Contract.Assume(crossing.LocationB != null);
                    if (!ringCrossingsBBuilder.TryGetValue(crossing.LocationB.RingIndex, out list)) {
                        Contract.Assume(crossing.LocationB != null);
                        list = new List<PolygonCrossing>();
                        ringCrossingsBBuilder.Add(crossing.LocationB.RingIndex, list);
                    }
                    Contract.Assume(list != null);
                    list.Add(crossing);
                }
                RingCrossingsA = PolygonRingCrossingLookup.Build(ringCrossingsABuilder, PolygonCrossing.LocationAComparer.CompareNonNull);
                RingCrossingsB = PolygonRingCrossingLookup.Build(ringCrossingsBBuilder, PolygonCrossing.LocationBComparer.CompareNonNull);

                Entrances = new HashSet<PolygonCrossing>();
                Exits = new HashSet<PolygonCrossing>();
                EntranceHops = new Dictionary<PolygonCrossing, PolygonCrossing>();
                ExitHops = new Dictionary<PolygonCrossing, PolygonCrossing>();
                VisitedCrossings = new List<PolygonCrossing>();
                VisitedCrossingsRingIndicesA = new HashSet<int>();
                VisitedCrossingsRingIndicesB = new HashSet<int>();
            }
        /// <summary>
        /// Calculates the intersection between two polygons.
        /// </summary>
        /// <param name="a">A polygon.</param>
        /// <param name="b">A polygon.</param>
        /// <returns>The intersection result, which may be a geometry collection containing points, segments, and polygons.</returns>
        public IPlanarGeometry Intersect(Polygon2 a, Polygon2 b) {
            if (null == a || a.Count == 0 || null == b || b.Count == 0)
                return null;
            if (ReferenceEquals(a, b))
                return a.Clone();

            if (Options.InvertLeftHandSide)
                a = PolygonInverseOperation.Invert(a);
            if (Options.InvertRightHandSide)
                b = PolygonInverseOperation.Invert(b);

            // find all the crossings
            var fillWinding = DetermineFillWinding(a.Concat(b));

            var kernel = CreateIntersectionKernel(a, b);
            // traverse the rings
            var results = kernel.Turtle(fillWinding);
            if (null == results.Polygon)
                return null;

            // TODO: this stuff is not so great
            results.Polygon = (results.Polygon.Count == 0 ? null : results.Polygon);
            if (null != results.Polygon) {
                if (fillWinding != PointWinding.Unknown)
                    results.Polygon.ForceFillWinding(fillWinding);
            }

            if (Options.InvertResult)
                results.Polygon = PolygonInverseOperation.Invert(results.Polygon);

            return results.Polygon;
        }
            private IntersectionResults BuildFinalResults(Polygon2 intersectedPolygon) {
                Contract.Requires(intersectedPolygon != null);
                Contract.Ensures(Contract.Result<IntersectionResults>() != null);
                Contract.Ensures(intersectedPolygon.Count >= Contract.OldValue(intersectedPolygon).Count);

                if (intersectedPolygon.Count == 0) {
                    var untouchedA = FindUntouchedRingsA();
                    var untouchedB = FindUntouchedRingsB();
                    intersectedPolygon.AddRange(QualifyRings(untouchedA, untouchedB, true));
                    intersectedPolygon.AddRange(QualifyRings(untouchedB, untouchedA, false));
                }
                else {
                    var intersectedResultTree = new RingBoundaryTree(intersectedPolygon);
                    intersectedPolygon.AddRange(
                        FilterQualifiedRingsToBoundaryTree(
                            QualifyRings(FindUntouchedRingsA(), B, true),
                            intersectedResultTree
                        )
                    );
                    intersectedPolygon.AddRange(
                        FilterQualifiedRingsToBoundaryTree(
                            QualifyRings(FindUntouchedRingsB(), A, false),
                            intersectedResultTree
                        )
                    );
                }
                return new IntersectionResults {
                    Polygon = intersectedPolygon
                };
            }
示例#51
0
文件: Geometry.cs 项目: CjShu/L-CC
            public Polygon2 ToPolygon(int offset = 0, float overrideWidth = -1)
            {
                var result = new Polygon2();
                var outRadius = (overrideWidth > 0
                    ? overrideWidth
                    : (offset + this.Radius) / (float)Math.Cos(2 * Math.PI / MaxLineSegmentN));

                for (var i = MaxLineSegmentN; i >= CurrentLineSegmentN; i--)
                {
                    var angle = i * 2 * Math.PI / MaxLineSegmentN;
                    var point = new Vector2(this.Center.X + outRadius * (float)Math.Cos(angle),
                        this.Center.Y + outRadius * (float)Math.Sin(angle));
                    result.Add(point);
                }

                return result;
            }
            private Polygon2 FindUntouchedRingsB() {
                Contract.Ensures(Contract.Result<IEnumerable<Ring2>>() != null);
                if (VisitedCrossingsRingIndicesB.Count == 0)
                    return B;

                var missingCount = B.Count - VisitedCrossingsRingIndicesB.Count;
                var results = new Polygon2(missingCount);
                if (missingCount == 0)
                    return results;

                for (int i = 0; i < B.Count; i++) {
                    if (!VisitedCrossingsRingIndicesB.Contains(i))
                        results.Add(B[i]);
                }
                return results;
            }