public IsPointInside ( Vector2 point ) : bool | ||
point | Vector2 | |
return | bool |
/// <summary> /// Returns whether this instance collides with the argument Polygon. /// </summary> /// <param name="polygon">The Polygon to test collision against.</param> /// <returns>Whether a collision has occurred.</returns> #endregion public bool CollideAgainst(Polygon polygon) { UpdateDependencies(TimeManager.CurrentTime); polygon.UpdateDependencies(TimeManager.CurrentTime); Point transformedPoint1 = new Point(RelativePoint1.X, RelativePoint1.Y); Point transformedPoint2 = new Point(RelativePoint2.X, RelativePoint2.Y); FlatRedBall.Math.MathFunctions.TransformPoint(ref transformedPoint1, ref mRotationMatrix); FlatRedBall.Math.MathFunctions.TransformPoint(ref transformedPoint2, ref mRotationMatrix); Point tp1 = new Point(transformedPoint1.X, transformedPoint1.Y); Point tp2 = new Point(transformedPoint2.X, transformedPoint2.Y); // Get world-positioned segment Segment a = new Segment( new Point(Position.X + transformedPoint1.X, Position.Y + transformedPoint1.Y), new Point(Position.X + transformedPoint2.X, Position.Y + transformedPoint2.Y)); // Check if one of the segment's endpoints is inside the Polygon if (polygon.IsPointInside(ref tp1, ref Position, ref mIdentityMatrix)) { polygon.mLastCollisionPoint = tp1; mLastCollisionPoint = tp1; return(true); } if (polygon.IsPointInside(ref tp2, ref Position, ref mIdentityMatrix)) { polygon.mLastCollisionPoint = tp2; mLastCollisionPoint = tp2; return(true); } Point intersectionPoint; // Check if one of the polygon's edges intersects the line segment for (int i = 0; i < polygon.Points.Count - 1; i++) { int indexAfter = i + 1; var point1 = new Point(polygon.Vertices[i].Position.X, polygon.Vertices[i].Position.Y); var point2 = new Point(polygon.Vertices[indexAfter].Position.X, polygon.Vertices[indexAfter].Position.Y); if (a.Intersects(new Segment(point1, point2), out intersectionPoint)) { mLastCollisionPoint = intersectionPoint; polygon.mLastCollisionPoint = intersectionPoint; return(true); } } // No collision return(false); }
public List <TriangulationPoint> GenerateGridPoints(Bounds bounds, float subdivLevel, Polygon _polygon) { List <TriangulationPoint> GridPoints = new List <TriangulationPoint>(); float numberDivisions = 6; float width = bounds.max.x - bounds.min.x; float height = bounds.max.y - bounds.min.y; float subdivWidth = width / (subdivLevel * numberDivisions); float subdivHeight = height / ((subdivLevel * numberDivisions)); float averagedLength = (subdivWidth + subdivHeight) / 2; float widthHeight = (width + height) / 2; for (int i = 1; i < (subdivLevel * numberDivisions / widthHeight) * width; i++) { for (int j = 1; j < (subdivLevel * numberDivisions / widthHeight) * height; j++) { float xPos = (i * averagedLength) + bounds.min.x; float yPos = (j * averagedLength) + bounds.min.y; TriangulationPoint t = new TriangulationPoint(xPos, yPos); if (_polygon.IsPointInside(t)) { GridPoints.Add(t); } } } return(GridPoints); }
// createFluidBody public void createFluidBody(List <Vector2> polygonPoints) { List <PolygonPoint> P2TPoints = new List <PolygonPoint>(); Polygon polygon; Vector2 topLeft = polygonPoints[0]; Vector2 bottomRight = polygonPoints[0]; float spacing = RADIUS / 3.7f; Random random = new Random(); foreach (Vector2 point in polygonPoints) { topLeft = Vector2.Min(topLeft, point); bottomRight = Vector2.Max(bottomRight, point); P2TPoints.Add(new PolygonPoint(point.X, point.Y)); } polygon = new Polygon(P2TPoints); for (float i = topLeft.X; i < bottomRight.X; i += spacing) { for (float j = topLeft.Y; j < bottomRight.Y; j += spacing) { Vector2 jitter = new Vector2(-1 + (float)random.NextDouble() * 2, -1 + (float)random.NextDouble() * 2) * (spacing * 0.2f); Vector2 point = new Vector2(i, j) + jitter; if (polygon.IsPointInside(new PolygonPoint(point.X, point.Y))) { createParticle(point, Vector2.Zero); } } } }
private static bool FruitPolygonCollision(Fruit fruit, Polygon polygon, CCPoint polygonVelocity) { bool didCollide = polygon.CollideAgainst(fruit.Collision); if (didCollide) { bool isCircleCenterInPolygon = polygon.IsPointInside( fruit.PositionWorldspace.X, fruit.PositionWorldspace.Y); float distance; var normal = polygon.GetNormalClosestTo(fruit.PositionWorldspace, out distance); if (isCircleCenterInPolygon) { distance += fruit.Radius; } else { distance = fruit.Radius - distance; } // increase the distance by a small amount to make sure that the objects do separate: distance += .5f; fruit.Position += normal * distance; fruit.Velocity = ApplyBounce(fruit.Velocity, polygonVelocity, normal, GameCoefficients.FruitCollisionElasticity); } return(didCollide); }
public void If_point_is_in_within_polygon_return_true_else_return_false(double longitude, double latitude, bool inside) { var point = new Point(longitude, latitude); var polygon = new Polygon(new[] { new LineString(new[] { new Point(17.02721, 58.747865), new Point(17.0272217, 58.7477883), new Point(17.0272233, 58.7477767), new Point(17.027224, 58.747765), new Point(17.02717, 58.7476967), new Point(17.027155, 58.7476867), new Point(17.0243233, 58.74786), new Point(17.0242817, 58.74787), new Point(17.0242533, 58.7478783), new Point(17.0242083, 58.7478967), new Point(17.024185, 58.7479067), new Point(17.024181, 58.74791), new Point(17.024147, 58.74794), new Point(17.024342, 58.748081), new Point(17.0271167, 58.7478783), new Point(17.02721, 58.747865) }) }); point.IsIntersects(polygon).Should().Be(inside); polygon.IsIntersects(point).Should().Be(inside); polygon.IsPointInside(point).Should().Be(inside); }
private static void MinMaxDistanceForEdge( Vector point, Polygon convexHull, VertexConstraints constraints1, VertexConstraints constraints2, out double minDistanceSqr, out double maxDistanceSqr) { if (convexHull.IsPointInside(point)) { minDistanceSqr = 0; } else { minDistanceSqr = Double.PositiveInfinity; for (int i = 0; i < convexHull.Vertices.Count; ++i) { double distanceSqr = point.DistanceToSegmentSquared( convexHull.Vertices[i], convexHull.Vertices[(i + 1) % convexHull.Vertices.Count]); minDistanceSqr = Math.Min(minDistanceSqr, distanceSqr); } } maxDistanceSqr = 0; foreach (Vector vertex1 in constraints1.Corners) { foreach (Vector vertex2 in constraints2.Corners) { double distanceSqr = point.DistanceToSegmentSquared(vertex1, vertex2); maxDistanceSqr = Math.Max(maxDistanceSqr, distanceSqr); } } }
/// <summary> /// Checks if a point is inside the board. /// </summary> /// <param name="point">The point to check.</param> /// <returns>Is the point inside?</returns> public bool IsPointInside(Vector3 point) { if (point.Y > 0 || point.Y < -Thickness) { return(false); } return(mPolygon.IsPointInside(new Poly2Tri.Triangulation.TriangulationPoint(point.X, point.Z))); }
public bool CollideAgainst(Polygon polygon) { polygon.UpdateDependencies(TimeManager.CurrentTime); // Check if one of the segment's endpoints is inside the Polygon if (polygon.IsPointInside(Point1.X, Point1.Y)) { polygon.mLastCollisionPoint = Point1; return(true); } if (polygon.IsPointInside(Point2.X, Point2.Y)) { polygon.mLastCollisionPoint = Point2; return(true); } Point intersectionPoint; // Check if one of the polygon's edges intersects the line segment for (int i = 0; i < polygon.Vertices.Length - 1; i++) { var vertexBefore = polygon.Vertices[i]; var vertexAfter = polygon.Vertices[i + 1]; var currentPolygonSegment = new Segment( new Point(vertexBefore.Position.X, vertexBefore.Position.Y), new Point(vertexAfter.Position.X, vertexAfter.Position.Y)); if (Intersects(currentPolygonSegment, out intersectionPoint)) { polygon.mLastCollisionPoint = intersectionPoint; return(true); } } // No collision return(false); }
public void If_point_with_a_polygon_with_whole_then_should_return_intersect_check_correctly(double longitude, double latitude, bool inside) { var point = new Point(longitude, latitude); var polygon = new Polygon(new[] { new LineString(new[] { new Point(20, 35), new Point(10, 30), new Point(10, 10), new Point(30, 5), new Point(45, 20), new Point(20, 35) }), new LineString(new[] { new Point(30, 20), new Point(20, 15), new Point(20, 25), new Point(30, 20) }) }); point.IsIntersects(polygon).Should().Equals(inside); polygon.IsIntersects(point).Should().Equals(inside); polygon.IsPointInside(point).Should().Equals(inside); }
public void KeepThisInsideOf(Polygon polygon) { UpdateDependencies(TimeManager.CurrentTime); polygon.UpdateDependencies(TimeManager.CurrentTime); Point3D fromCircleToThis = polygon.VectorFrom(Position.X, Position.Y); // The fromCircleToThis will be less than circle.Radius units in length. // However much less it is is how far the objects should be moved. double length = fromCircleToThis.Length(); double distanceToMove = Radius - length; if (!polygon.IsPointInside(ref Position)) { // If the circle falls inside of the shape, then it should be moved // outside. That means moving to the edge of the polygon then also moving out // the distance of the radius. distanceToMove = -(Radius + length); } else if (System.Math.Abs(length) > Radius) { return; } double amountToMoveOnX = distanceToMove * fromCircleToThis.X / length; double amountToMoveOnY = distanceToMove * fromCircleToThis.Y / length; float thisMass = 0; float otherMass = 1; float totalMass = thisMass + otherMass; LastMoveCollisionReposition.X = -(float)(amountToMoveOnX * otherMass / totalMass); LastMoveCollisionReposition.Y = -(float)(amountToMoveOnY * otherMass / totalMass); TopParent.Position.X += LastMoveCollisionReposition.X; TopParent.Position.Y += LastMoveCollisionReposition.Y; polygon.mLastMoveCollisionReposition.X = (float)((thisMass / totalMass) * amountToMoveOnX); polygon.mLastMoveCollisionReposition.Y = (float)((thisMass / totalMass) * amountToMoveOnY); polygon.TopParent.Position.X += polygon.mLastMoveCollisionReposition.X; polygon.TopParent.Position.Y += polygon.mLastMoveCollisionReposition.Y; ForceUpdateDependencies(); polygon.ForceUpdateDependencies(); }
private static int GetPointToStartAt(Polygon polygon, Polygon otherPolygon) { int firstPointToStartAt = 0; double furthestAwayDistance = otherPolygon.VectorFrom(polygon.mVertices[0].Position.X, polygon.mVertices[0].Position.Y).LengthSquared(); for (int i = 1; i < polygon.mVertices.Length - 1; i++) { double distance = otherPolygon.VectorFrom(polygon.mVertices[i].Position.X, polygon.mVertices[i].Position.Y).LengthSquared(); if (distance > furthestAwayDistance && !otherPolygon.IsPointInside(ref polygon.mVertices[i].Position)) { firstPointToStartAt = i; furthestAwayDistance = distance; } } return(firstPointToStartAt); }
public void If_point_with_a_simple_polygon_then_should_return_intersect_check_correctly(double longitude, double latitude, bool inside) { var point = new Point(longitude, latitude); var polygon = new Polygon(new List <Point> { new Point(0, 0), new Point(5, 0), new Point(5, 5), new Point(3, 5), new Point(3, 3), new Point(1, 3), new Point(1, 5), new Point(0, 5), new Point(0, 0), }); point.IsIntersects(polygon).Should().Equals(inside); polygon.IsIntersects(point).Should().Equals(inside); polygon.IsPointInside(point).Should().Equals(inside); }
static bool TryInsertHole(Polygon parent, Polygon hole) { //Can't go in. if (!parent.IsPointInside(hole[0])) { return(false); } if (parent.Holes != null) { foreach (var item in parent.Holes) { if (TryInsertHole(item, hole)) { return(true); } } } //it doesn't fit into any of the daughter holes. parent.AddHole(hole); return(true); }
static void MainForConvexHull() { List <Vector> points = new List <Vector>(); points.Add(new Vector(0, 0)); points.Add(new Vector(1, 2)); points.Add(new Vector(2, 1)); points.Add(new Vector(3, 2)); points.Add(new Vector(4, 2)); points.Add(new Vector(3, -1)); Polygon p = Polygon.ConvexHull(points); Console.WriteLine(p.IsPointInside(new Vector(2, 1))); Console.WriteLine(p.IsPointInside(new Vector(2, -1))); Console.WriteLine(p.IsPointInside(new Vector(0, -1))); Console.WriteLine(p.IsPointInside(new Vector(-1, 0))); Console.WriteLine(p.IsPointInside(new Vector(2, 0))); Console.WriteLine(p.IsPointInside(new Vector(3, 1))); }
/// <summary> /// Creates a triangulation of the vertices given, and gives you the indices of it. /// </summary> /// <param name="aPoints">A list of points to triangulate.</param> /// <param name="aTreatAsPath">Should we discard any triangles at all? Use this if you want to get rid of triangles that are outside the path.</param> /// <param name="aInvert">if we're treating it as a path, should we instead sicard triangles inside the path?</param> /// <returns>A magical list of indices describing the triangulation!</returns> /// public static void GetVerticesAndIndices(List <Vector2> inputPoints, out List <Vector2> outputPoints, out List <int> outputIndices, float chunkWidth, float chunkHeight, float jitterX, float jitterY) { Polygon poly; List <PolygonPoint> points = new List <PolygonPoint>(); List <Vector2> interpolatedPoints = new List <Vector2>(); float edgeCutLength = (chunkWidth + chunkHeight) * 0.5f; int triangleIndex = 0; int numChunksX; int numChunksY; outputPoints = new List <Vector2>(); outputIndices = new List <int>(); // Cut all the edges into smaller segments (so triangulation won't create long, thin shards along the edges) for (int i = 0; i < inputPoints.Count; i++) { Vector2 a; Vector2 b; float distance; int numCuts; float cutLength; a = i == 0 ? inputPoints[inputPoints.Count - 1] : inputPoints[i - 1]; b = inputPoints[i]; distance = (b - a).magnitude; numCuts = (int)(distance / edgeCutLength); cutLength = distance / (float)numCuts; for (int j = 0; j < numCuts; j++) { Vector2 p = Vector2.Lerp(a, b, Mathf.Max(0f, Mathf.Min(1f, (j * cutLength / distance)))); interpolatedPoints.Add(p); } } // Convert points to P2T, and create polygon foreach (Vector2 p in interpolatedPoints) { points.Add(new PolygonPoint(p.x, p.y)); } poly = new Polygon(points); // Calculate number of chunks to split the polygon up into numChunksX = (int)(poly.Bounds.Width / chunkWidth); numChunksY = (int)(poly.Bounds.Height / chunkHeight); // Add steiner points (this is the reason for using Poly2Tri) UnityEngine.Random.seed = (int)(poly.Bounds.Left * poly.Bounds.Top); for (int i = 0; i < numChunksX; i++) { for (int j = 0; j < numChunksY; j++) { TriangulationPoint p = new TriangulationPoint( i * chunkWidth + poly.Bounds.Left + UnityEngine.Random.Range(-jitterX, jitterX), j * -chunkHeight + poly.Bounds.Top + UnityEngine.Random.Range(-jitterY, jitterY)); if (poly.IsPointInside(p)) { poly.AddSteinerPoint(p); } } } // Triangulate P2T.Triangulate(poly); // Build output from triangulated polygon foreach (DelaunayTriangle triangle in poly.Triangles) { TriangulationPoint p1 = triangle.Points[0]; TriangulationPoint p2 = triangle.PointCWFrom(p1); TriangulationPoint p3 = triangle.PointCWFrom(p2); outputPoints.Add(new Vector2(p1.Xf, p1.Yf)); outputPoints.Add(new Vector2(p2.Xf, p2.Yf)); outputPoints.Add(new Vector2(p3.Xf, p3.Yf)); outputIndices.Add(triangleIndex++); outputIndices.Add(triangleIndex++); outputIndices.Add(triangleIndex++); } }
public bool CollideAgainst(Polygon polygon) { polygon.UpdateDependencies(TimeManager.CurrentTime); // Check if one of the segment's endpoints is inside the Polygon if (polygon.IsPointInside(Point1.X, Point1.Y)) { polygon.mLastCollisionPoint = Point1; return true; } if (polygon.IsPointInside(Point2.X, Point2.Y)) { polygon.mLastCollisionPoint = Point2; return true; } Point intersectionPoint; // Check if one of the polygon's edges intersects the line segment for (int i = 0; i < polygon.Points.Count - 1; i++) { if (Intersects(new Segment( new Point(polygon.Position.X + polygon.Points[i].X, polygon.Position.Y + polygon.Points[i].Y), new Point(polygon.Position.X + polygon.Points[i + 1].X, polygon.Position.Y + polygon.Points[i + 1].Y)), out intersectionPoint)) { polygon.mLastCollisionPoint = intersectionPoint; return true; } } // No collision return false; }
public List<TriangulationPoint> GenerateGridPoints(Bounds bounds, float subdivLevel, Polygon _polygon) { List<TriangulationPoint> GridPoints = new List<TriangulationPoint> (); float numberDivisions = 6; float width = bounds.max.x - bounds.min.x; float height = bounds.max.y - bounds.min.y; float subdivWidth = width / (subdivLevel*numberDivisions); float subdivHeight = height / ((subdivLevel*numberDivisions) ); float averagedLength = (subdivWidth + subdivHeight) / 2; float widthHeight = (width + height) / 2; for(int i=1;i<(subdivLevel*numberDivisions/widthHeight)*width;i++) { for(int j=1;j<(subdivLevel*numberDivisions/widthHeight)*height;j++) { float xPos = (i*averagedLength) + bounds.min.x; float yPos = (j*averagedLength) + bounds.min.y; TriangulationPoint t = new TriangulationPoint (xPos, yPos); if(_polygon.IsPointInside(t)) GridPoints.Add(t); } } return GridPoints; }
public bool IsOn(Polygon polygon, Camera camera) { return(polygon.IsPointInside(WorldXAt(polygon.Z, camera), WorldYAt(polygon.Z, camera))); }
private static void SetPointsFromContactPointsAndVertices(Polygon polygon, Polygon otherPolygon, List<ContactPoint> contactPoints, int polygonPointToStartAt, List<Vector3> thisVertices, List<Vector3> otherVertices) { Polygon currentPolygon = polygon; List<Vector3> newPolygonPoints = new List<Vector3>(); int otherIndex = 0; int otherIndexToStartAt = -1; int thisIndex = polygonPointToStartAt; while (true) { if (newPolygonPoints.Count > 3 * (polygon.Points.Count + otherPolygon.Points.Count)) { // just break here for now break; } bool isThereAContactPoint = false; if (currentPolygon == polygon) { newPolygonPoints.Add(thisVertices[thisIndex]); isThereAContactPoint = DoesContactPointsHaveThisIndex(thisIndex, contactPoints); } else { newPolygonPoints.Add(otherVertices[otherIndex]); isThereAContactPoint = DoesContactPointsHaveOtherIndex(otherIndex, contactPoints); } if (isThereAContactPoint) { ContactPoint cp = new ContactPoint(); if (currentPolygon == polygon) { cp = GetContactPointAtThisIndex(thisIndex, contactPoints, thisVertices[thisIndex]); } else { cp = GetContactPointAtOtherIndex(otherIndex, contactPoints, otherVertices[otherIndex]); } #region If it's a segment intersection, drop the point and swap the current polygon if (cp.ContactType == ContactType.SegmentIntersection) { if (currentPolygon == polygon) { currentPolygon = otherPolygon; otherIndex = cp.OtherIndex + 1; if (otherIndex == otherVertices.Count - 1) { otherIndex = 0; } if (otherIndex == otherIndexToStartAt) { newPolygonPoints.Add(newPolygonPoints[0]); break; } if (otherIndexToStartAt == -1) { otherIndexToStartAt = otherIndex; } } else { currentPolygon = polygon; thisIndex = cp.ThisIndex + 1; if (thisIndex == polygon.Points.Count - 1) { thisIndex = 0; } if (thisIndex == polygonPointToStartAt) { // close off the polygon and stop adding points newPolygonPoints.Add(newPolygonPoints[0]); break; } } newPolygonPoints.Add(cp.Position); } #endregion else if(cp.ContactType == ContactType.PointOnSegment) { // See which next point is the furthest away, and decide based off of that. int nextOtherIndex = cp.OtherIndex + 1; if (cp.OtherEndpoint != -1) { nextOtherIndex = cp.OtherEndpoint + 1; } if (nextOtherIndex >= otherVertices.Count - 1) { nextOtherIndex -= (otherVertices.Count - 1); } int nextThisIndex = cp.ThisIndex + 1; if (cp.ThisEndpoint != -1) { nextThisIndex = cp.ThisEndpoint + 1; } if (nextThisIndex >= thisVertices.Count - 1) { nextThisIndex -= (thisVertices.Count - 1); } Vector3 nextThisVector = thisVertices[nextThisIndex] - cp.Position; Vector3 nextOtherVector = otherVertices[nextOtherIndex] - cp.Position; double distanceAwayFromThis = 0; double distanceAwayFromOther = 0; bool doWhile = true; int numberOfExtraDoWhiles = 0; int thisIndexBeforeDoWhile = nextThisIndex; int otherIndexBeforeDoWhile = nextOtherIndex; // The doWhile section will find out which path will take us // furtest away from the other Polygon. This works most of the time // but in some cases (like if the initial two paths are parallel), we'll // want to special case which we use bool forceUseThis = false; bool forceUseOther = false; while (doWhile) { if (nextThisVector.Length() < .0001f) { nextThisIndex++; if (nextThisIndex == thisVertices.Count - 1) { nextThisIndex = 0; } nextThisVector = thisVertices[nextThisIndex] - cp.Position; } if (nextOtherVector.Length() < .0001f) { nextOtherIndex++; if (nextOtherIndex == otherVertices.Count - 1) { nextOtherIndex = 0; } nextOtherVector = otherVertices[nextOtherIndex] - cp.Position; } float thisVectorLength = nextThisVector.Length(); float otherVectorLength = nextOtherVector.Length(); float smallestDistance = System.Math.Min(thisVectorLength, otherVectorLength); nextThisVector.Normalize(); nextOtherVector.Normalize(); nextThisVector *= smallestDistance / 2.0f; nextOtherVector *= smallestDistance / 2.0f; nextThisVector += cp.Position; nextOtherVector += cp.Position; if (nextThisVector == nextOtherVector) { forceUseThis = thisVectorLength < otherVectorLength; forceUseOther = !forceUseThis; break; } double minimumDistance = .00001; if (polygon.IsPointInside(ref nextOtherVector)) { distanceAwayFromThis = 0; } else { distanceAwayFromThis = polygon.VectorFrom(nextOtherVector.X, nextOtherVector.Y).Length(); if (distanceAwayFromThis < minimumDistance) { distanceAwayFromThis = 0; } } if (otherPolygon.IsPointInside(ref nextThisVector)) { distanceAwayFromOther = 0; } else { distanceAwayFromOther = otherPolygon.VectorFrom(nextThisVector.X, nextThisVector.Y).Length(); if (distanceAwayFromOther < minimumDistance) { distanceAwayFromOther = 0; } } if (distanceAwayFromOther == distanceAwayFromThis) { // We need a tiebreaker. Let's move an extra index and see what happens, shall we? nextThisIndex++; if (nextThisIndex == thisVertices.Count - 1) { nextThisIndex = 0; } nextThisVector = thisVertices[nextThisIndex] - cp.Position; nextOtherIndex++; if (nextOtherIndex == otherVertices.Count - 1) { nextOtherIndex = 0; } nextOtherVector = otherVertices[nextOtherIndex] - cp.Position; numberOfExtraDoWhiles++; } else { doWhile = false; } } nextThisIndex = thisIndexBeforeDoWhile; nextOtherIndex = otherIndexBeforeDoWhile; bool useThis = distanceAwayFromThis < distanceAwayFromOther; if (forceUseThis) useThis = true; else if (forceUseOther) useThis = false; if (useThis && currentPolygon == polygon) { // make sure there are no other contact points on the current segment on this for (int i = 0; i < contactPoints.Count; i++) { ContactPoint otherCp = contactPoints[i]; if (otherCp.Position != cp.Position && otherCp.ThisIndex == cp.ThisIndex) { useThis = false; break; } } } else if (!useThis && currentPolygon == otherPolygon) { // make sure there are no other contact points on the current segment on this for (int i = 0; i < contactPoints.Count; i++) { ContactPoint otherCp = contactPoints[i]; if (otherCp.Position != cp.Position && otherCp.OtherIndex == cp.OtherIndex) { useThis = true; break; } } } newPolygonPoints.Add(cp.Position); if (distanceAwayFromThis == distanceAwayFromOther) { useThis = currentPolygon == polygon; } if (useThis) { currentPolygon = polygon; thisIndex = nextThisIndex; if (thisIndex == polygonPointToStartAt) { // close off the polygon and stop adding points newPolygonPoints.Add(newPolygonPoints[0]); break; } } else { currentPolygon = otherPolygon; otherIndex = nextOtherIndex; if (otherIndex == otherIndexToStartAt) { newPolygonPoints.Add(newPolygonPoints[0]); break; } if (otherIndexToStartAt == -1) { otherIndexToStartAt = otherIndex; } } } } else { if (currentPolygon == polygon) { thisIndex++; if (thisIndex == polygon.Points.Count - 1) { thisIndex = 0; } if (thisIndex == polygonPointToStartAt) { // close off the polygon and stop adding points newPolygonPoints.Add(newPolygonPoints[0]); break; } } else { otherIndex++; if (otherIndex == otherPolygon.Points.Count - 1) { otherIndex = 0; } if (otherIndex == otherIndexToStartAt) { // close off the polygon and stop adding points newPolygonPoints.Add(newPolygonPoints[0]); break; } } } } SetPolygonPoints(polygon, newPolygonPoints); }
private static void SetPointsFromContactPointsAndVertices(Polygon polygon, Polygon otherPolygon, List <ContactPoint> contactPoints, int polygonPointToStartAt, List <Vector3> thisVertices, List <Vector3> otherVertices) { Polygon currentPolygon = polygon; List <Vector3> newPolygonPoints = new List <Vector3>(); int otherIndex = 0; int otherIndexToStartAt = -1; int thisIndex = polygonPointToStartAt; while (true) { if (newPolygonPoints.Count > 3 * (polygon.Points.Count + otherPolygon.Points.Count)) { // just break here for now break; } bool isThereAContactPoint = false; if (currentPolygon == polygon) { newPolygonPoints.Add(thisVertices[thisIndex]); isThereAContactPoint = DoesContactPointsHaveThisIndex(thisIndex, contactPoints); } else { newPolygonPoints.Add(otherVertices[otherIndex]); isThereAContactPoint = DoesContactPointsHaveOtherIndex(otherIndex, contactPoints); } if (isThereAContactPoint) { ContactPoint cp = new ContactPoint(); if (currentPolygon == polygon) { cp = GetContactPointAtThisIndex(thisIndex, contactPoints, thisVertices[thisIndex]); } else { cp = GetContactPointAtOtherIndex(otherIndex, contactPoints, otherVertices[otherIndex]); } #region If it's a segment intersection, drop the point and swap the current polygon if (cp.ContactType == ContactType.SegmentIntersection) { if (currentPolygon == polygon) { currentPolygon = otherPolygon; otherIndex = cp.OtherIndex + 1; if (otherIndex == otherVertices.Count - 1) { otherIndex = 0; } if (otherIndex == otherIndexToStartAt) { newPolygonPoints.Add(newPolygonPoints[0]); break; } if (otherIndexToStartAt == -1) { otherIndexToStartAt = otherIndex; } } else { currentPolygon = polygon; thisIndex = cp.ThisIndex + 1; if (thisIndex == polygon.Points.Count - 1) { thisIndex = 0; } if (thisIndex == polygonPointToStartAt) { // close off the polygon and stop adding points newPolygonPoints.Add(newPolygonPoints[0]); break; } } newPolygonPoints.Add(cp.Position); } #endregion else if (cp.ContactType == ContactType.PointOnSegment) { // See which next point is the furthest away, and decide based off of that. int nextOtherIndex = cp.OtherIndex + 1; if (cp.OtherEndpoint != -1) { nextOtherIndex = cp.OtherEndpoint + 1; } if (nextOtherIndex >= otherVertices.Count - 1) { nextOtherIndex -= (otherVertices.Count - 1); } int nextThisIndex = cp.ThisIndex + 1; if (cp.ThisEndpoint != -1) { nextThisIndex = cp.ThisEndpoint + 1; } if (nextThisIndex >= thisVertices.Count - 1) { nextThisIndex -= (thisVertices.Count - 1); } Vector3 nextThisVector = thisVertices[nextThisIndex] - cp.Position; Vector3 nextOtherVector = otherVertices[nextOtherIndex] - cp.Position; double distanceAwayFromThis = 0; double distanceAwayFromOther = 0; bool doWhile = true; int numberOfExtraDoWhiles = 0; int thisIndexBeforeDoWhile = nextThisIndex; int otherIndexBeforeDoWhile = nextOtherIndex; // The doWhile section will find out which path will take us // furtest away from the other Polygon. This works most of the time // but in some cases (like if the initial two paths are parallel), we'll // want to special case which we use bool forceUseThis = false; bool forceUseOther = false; while (doWhile) { if (nextThisVector.Length() < .0001f) { nextThisIndex++; if (nextThisIndex == thisVertices.Count - 1) { nextThisIndex = 0; } nextThisVector = thisVertices[nextThisIndex] - cp.Position; } if (nextOtherVector.Length() < .0001f) { nextOtherIndex++; if (nextOtherIndex == otherVertices.Count - 1) { nextOtherIndex = 0; } nextOtherVector = otherVertices[nextOtherIndex] - cp.Position; } float thisVectorLength = nextThisVector.Length(); float otherVectorLength = nextOtherVector.Length(); float smallestDistance = System.Math.Min(thisVectorLength, otherVectorLength); nextThisVector.Normalize(); nextOtherVector.Normalize(); nextThisVector *= smallestDistance / 2.0f; nextOtherVector *= smallestDistance / 2.0f; nextThisVector += cp.Position; nextOtherVector += cp.Position; if (nextThisVector == nextOtherVector) { forceUseThis = thisVectorLength < otherVectorLength; forceUseOther = !forceUseThis; break; } double minimumDistance = .00001; if (polygon.IsPointInside(ref nextOtherVector)) { distanceAwayFromThis = 0; } else { distanceAwayFromThis = polygon.VectorFrom(nextOtherVector.X, nextOtherVector.Y).Length(); if (distanceAwayFromThis < minimumDistance) { distanceAwayFromThis = 0; } } if (otherPolygon.IsPointInside(ref nextThisVector)) { distanceAwayFromOther = 0; } else { distanceAwayFromOther = otherPolygon.VectorFrom(nextThisVector.X, nextThisVector.Y).Length(); if (distanceAwayFromOther < minimumDistance) { distanceAwayFromOther = 0; } } if (distanceAwayFromOther == distanceAwayFromThis) { // We need a tiebreaker. Let's move an extra index and see what happens, shall we? nextThisIndex++; if (nextThisIndex == thisVertices.Count - 1) { nextThisIndex = 0; } nextThisVector = thisVertices[nextThisIndex] - cp.Position; nextOtherIndex++; if (nextOtherIndex == otherVertices.Count - 1) { nextOtherIndex = 0; } nextOtherVector = otherVertices[nextOtherIndex] - cp.Position; numberOfExtraDoWhiles++; } else { doWhile = false; } } nextThisIndex = thisIndexBeforeDoWhile; nextOtherIndex = otherIndexBeforeDoWhile; bool useThis = distanceAwayFromThis < distanceAwayFromOther; if (forceUseThis) { useThis = true; } else if (forceUseOther) { useThis = false; } if (useThis && currentPolygon == polygon) { // make sure there are no other contact points on the current segment on this for (int i = 0; i < contactPoints.Count; i++) { ContactPoint otherCp = contactPoints[i]; if (otherCp.Position != cp.Position && otherCp.ThisIndex == cp.ThisIndex) { useThis = false; break; } } } else if (!useThis && currentPolygon == otherPolygon) { // make sure there are no other contact points on the current segment on this for (int i = 0; i < contactPoints.Count; i++) { ContactPoint otherCp = contactPoints[i]; if (otherCp.Position != cp.Position && otherCp.OtherIndex == cp.OtherIndex) { useThis = true; break; } } } newPolygonPoints.Add(cp.Position); if (distanceAwayFromThis == distanceAwayFromOther) { useThis = currentPolygon == polygon; } if (useThis) { currentPolygon = polygon; thisIndex = nextThisIndex; if (thisIndex == polygonPointToStartAt) { // close off the polygon and stop adding points newPolygonPoints.Add(newPolygonPoints[0]); break; } } else { currentPolygon = otherPolygon; otherIndex = nextOtherIndex; if (otherIndex == otherIndexToStartAt) { newPolygonPoints.Add(newPolygonPoints[0]); break; } if (otherIndexToStartAt == -1) { otherIndexToStartAt = otherIndex; } } } } else { if (currentPolygon == polygon) { thisIndex++; if (thisIndex == polygon.Points.Count - 1) { thisIndex = 0; } if (thisIndex == polygonPointToStartAt) { // close off the polygon and stop adding points newPolygonPoints.Add(newPolygonPoints[0]); break; } } else { otherIndex++; if (otherIndex == otherPolygon.Points.Count - 1) { otherIndex = 0; } if (otherIndex == otherIndexToStartAt) { // close off the polygon and stop adding points newPolygonPoints.Add(newPolygonPoints[0]); break; } } } } SetPolygonPoints(polygon, newPolygonPoints); }
private static int GetPointToStartAt(Polygon polygon, Polygon otherPolygon) { int firstPointToStartAt = 0; double furthestAwayDistance = otherPolygon.VectorFrom(polygon.mVertices[0].Position.X, polygon.mVertices[0].Position.Y).LengthSquared(); for (int i = 1; i < polygon.mVertices.Length - 1; i++) { double distance = otherPolygon.VectorFrom(polygon.mVertices[i].Position.X, polygon.mVertices[i].Position.Y).LengthSquared(); if(distance > furthestAwayDistance && !otherPolygon.IsPointInside(ref polygon.mVertices[i].Position)) { firstPointToStartAt = i; furthestAwayDistance = distance; } } return firstPointToStartAt; }
public bool IsOn(Polygon polygon) { return(polygon.IsPointInside(WorldXAt(polygon.Z), WorldYAt(polygon.Z))); }
static bool TryInsertHole(Polygon parent, Polygon hole) { //Can't go in. if (!parent.IsPointInside(hole[0])) return false; if (parent.Holes != null) foreach (var item in parent.Holes) { if (TryInsertHole(item, hole)) return true; } //it doesn't fit into any of the daughter holes. parent.AddHole(hole); return true; }
private static bool Check( Triangle tri, Polygon boundary ) { if( boundary == null || (boundary.IsPointInside( tri.a ) && boundary.IsPointInside( tri.b ) && boundary.IsPointInside( tri.c )) ) return true; return false; }