/// <summary> /// Decompose the polygon into several smaller non-concave polygons. /// </summary> /// <param name="vertices">The polygon to decompose.</param> /// <param name="sheer">The sheer to use if you get bad results, try using a higher value.</param> /// <returns>A list of triangles</returns> public static List<Vertices> ConvexPartition(Vertices vertices, float sheer = 0.001f) { Debug.Assert(vertices.Count > 3); List<Point> compatList = new List<Point>(vertices.Count); foreach (Vector2 vertex in vertices) { compatList.Add(new Point(vertex.X, vertex.Y)); } Triangulator t = new Triangulator(compatList, sheer); List<Vertices> list = new List<Vertices>(); foreach (List<Point> triangle in t.Triangles) { Vertices outTriangles = new Vertices(triangle.Count); foreach (Point outTriangle in triangle) { outTriangles.Add(new Vector2(outTriangle.X, outTriangle.Y)); } list.Add(outTriangles); } return list; }
public override void Initialize() { Vector2 trans = new Vector2(); _polygons = new List<Vertices>(); _polygons.Add(PolygonTools.CreateGear(5f, 10, 0f, 6f)); _polygons.Add(PolygonTools.CreateGear(4f, 15, 100f, 3f)); trans.X = 0f; trans.Y = 8f; _polygons[0].Translate(ref trans); _polygons[1].Translate(ref trans); _polygons.Add(PolygonTools.CreateGear(5f, 10, 50f, 5f)); trans.X = 22f; trans.Y = 17f; _polygons[2].Translate(ref trans); AddRectangle(5, 10); AddCircle(5, 32); trans.X = -20f; trans.Y = 8f; _polygons[3].Translate(ref trans); trans.Y = 20f; _polygons[4].Translate(ref trans); _subject = _polygons[0]; _clip = _polygons[1]; base.Initialize(); }
/// <summary> /// Decompose the polygon into several smaller non-concave polygons. /// </summary> /// <param name="vertices">The polygon to decompose.</param> /// <param name="sheer">The sheer to use if you get bad results, try using a higher value.</param> /// <returns>A list of trapezoids</returns> public static List<Vertices> ConvexPartitionTrapezoid(Vertices vertices, float sheer = 0.001f) { List<Point> compatList = new List<Point>(vertices.Count); foreach (Vector2 vertex in vertices) { compatList.Add(new Point(vertex.X, vertex.Y)); } Triangulator t = new Triangulator(compatList, sheer); List<Vertices> list = new List<Vertices>(); foreach (Trapezoid trapezoid in t.Trapezoids) { Vertices verts = new Vertices(); List<Point> points = trapezoid.GetVertices(); foreach (Point point in points) { verts.Add(new Vector2(point.X, point.Y)); } list.Add(verts); } return list; }
public Entity BuildEntity(Entity e, params object[] args) { e.Tag = "Chassis"; #region Body Body Chassis = e.AddComponent<Body>(new Body(_World, e)); { Vertices vertices = new Vertices(8); vertices.Add(new Vector2(-2.5f, 0.08f)); vertices.Add(new Vector2(-2.375f, -0.46f)); vertices.Add(new Vector2(-0.58f, -0.92f)); vertices.Add(new Vector2(0.46f, -0.92f)); vertices.Add(new Vector2(2.5f, -0.17f)); vertices.Add(new Vector2(2.5f, 0.205f)); vertices.Add(new Vector2(2.3f, 0.33f)); vertices.Add(new Vector2(-2.25f, 0.35f)); PolygonShape chassisShape = new PolygonShape(vertices, 2f); Chassis.BodyType = BodyType.Dynamic; Chassis.Position = new Vector2(0.0f, -1.0f); Chassis.CreateFixture(chassisShape); } #endregion #region Sprite e.AddComponent<Sprite>(new Sprite(args[0] as Texture2D, (Rectangle)args[1], Chassis, 1, Color.White, 0f)); #endregion return e; }
public Goalie(World world, GoalieData spawn) { var body = new Body(world); var angle = spawn.End - spawn.Begin; body.Rotation = FMath.Atan2(angle.Y, angle.X); segment.A = spawn.Begin; segment.B = spawn.End; var normal = new Vector2(-angle.Y, angle.X); normal.Normalize(); delta = normal * .5f; segmentOut.A = spawn.Begin + delta; segmentOut.B = spawn.End + delta; segmentIn.A = spawn.Begin - delta; segmentIn.B = spawn.End - delta; body.Position = spawn.Begin; var verts = new Vertices(); verts.Add(new Vector2(left, bottom)); verts.Add(new Vector2(right, bottom)); verts.Add(new Vector2(right, top)); verts.Add(new Vector2(left, top)); var shape = new PolygonShape(verts, 1f); body.FixedRotation = true; body.BodyType = BodyType.Dynamic; Fixture = body.CreateFixture(shape); }
/// <summary> /// Create a new chainshape from the vertices. /// </summary> /// <param name="vertices">The vertices to use. Must contain 2 or more vertices.</param> /// <param name="createLoop">Set to true to create a closed loop. It connects the first vertice to the last, and automatically adjusts connectivity to create smooth collisions along the chain.</param> public ChainShape(Vertices vertices, bool createLoop = false) : base(0) { ShapeType = ShapeType.Chain; _radius = Settings.PolygonRadius; Debug.Assert(vertices != null && vertices.Count >= 3); Debug.Assert(vertices[0] != vertices[vertices.Count - 1]); // FPE. See http://www.box2d.org/forum/viewtopic.php?f=4&t=7973&p=35363 for (int i = 1; i < vertices.Count; ++i) { Vector2 v1 = vertices[i - 1]; Vector2 v2 = vertices[i]; // If the code crashes here, it means your vertices are too close together. Debug.Assert(Vector2.DistanceSquared(v1, v2) > Settings.LinearSlop * Settings.LinearSlop); } Vertices = new Vertices(vertices); if (createLoop) { Vertices.Add(vertices[0]); PrevVertex = Vertices[Vertices.Count - 2]; //FPE: We use the properties instead of the private fields here. NextVertex = Vertices[1]; //FPE: We use the properties instead of the private fields here. } }
/// <summary> /// Constructs a FPE Body from the given list of vertices and density /// </summary> /// <param name="game"></param> /// <param name="world"></param> /// <param name="vertices">The collection of vertices in display units (pixels)</param> /// <param name="bodyType"></param> /// <param name="density"></param> public PhysicsGameEntity(Game game, World world, Category collisionCategory, Vertices vertices, BodyType bodyType, float density) : this(game,world,collisionCategory) { ConstructFromVertices(world,vertices,density); Body.BodyType = bodyType; Body.CollisionCategories = collisionCategory; }
/// <summary> /// Decompose the polygon into several smaller non-concave polygon. /// If the polygon is already convex, it will return the original polygon, unless it is over Settings.MaxPolygonVertices. /// </summary> public static List<Vertices> ConvexPartition(Vertices vertices) { Debug.Assert(vertices.Count > 3); Debug.Assert(vertices.IsCounterClockWise()); return TriangulatePolygon(vertices); }
public override Body CreateBody(World world) { var unithull = new Vertices((Vector2[])this.ResourceDictionary.GetResource(_resource.CollisionHullKey)); var scaledVertices = new List<Vector2>(); foreach (var vertex in unithull) { scaledVertices.Add(new Vector2(vertex.X * _resource.Width, vertex.Y * _resource.Height)); } var vertices = new Vertices(scaledVertices); var body = new Body(world); body.BodyType = BodyType.Dynamic; body.IgnoreGravity = true; body.LinearDamping = 0.0f; body.FixedRotation = true; body.Mass = 0; var location = ((ILocatable)_actor).Location; body.Position = new Vector2(location.X, location.Y); var shape = new PolygonShape(vertices, 1f); var fixture = body.CreateFixture(shape, 0f); fixture.CollisionGroup = _resource.CollisionGroup; fixture.UserData = new CollisionData { Actor = _actor }; fixture.OnCollision += OnCollision; _body = body; return body; }
public cRigidBodyGameObject(float mass, Vertices v) { _rigidBody = new PolygonRigidBody(mass, v); cPhysics.Instance.addObject(this); _canAttachPortalTo = false; _portaling = false; }
public static Body CreateLoopShape(World world, Vertices vertices, Vector2 position, DebugMaterial userData) { Body body = CreateBody(world, position); FixtureFactory.AttachLoopShape(vertices, body, userData); return body; }
public override Body CreateBody(World world) { var unitHull = (Vector2[])ResourceDictionary.GetResource("UnitHull"); var scaledVertices = new List<Vector2>(); foreach (var vertex in unitHull) { scaledVertices.Add(new Vector2(vertex.X * _resource.Width, vertex.Y * _resource.Height)); } var vertices = new Vertices(scaledVertices); var body = new Body(world); body.BodyType = BodyType.Static; var location = ((ILocatable)_actor).Location; body.Position = new Vector2(location.X, location.Y); var shape = new PolygonShape(vertices, 1f); var fixture = body.CreateFixture(shape, 0f); fixture.UserData = new CollisionData { Actor = _actor }; fixture.CollisionGroup = _resource.CollisionGroup; fixture.OnCollision += OnCollision; _body = body; return body; }
/// <summary> /// Cut a the contour and add a triangle into V to describe the /// location of the cut /// </summary> /// <param name="contour">The list of points defining the polygon</param> /// <param name="u">The index of the first point</param> /// <param name="v">The index of the second point</param> /// <param name="w">The index of the third point</param> /// <param name="n">The number of elements in the array.</param> /// <param name="V">The array to populate with indicies of triangles.</param> /// <returns>True if a triangle was found</returns> private static bool Snip(Vertices contour, int u, int v, int w, int n, int[] V) { if (Settings.Epsilon > MathUtils.Area(ref _tmpA, ref _tmpB, ref _tmpC)) { return false; } for (int p = 0; p < n; p++) { if ((p == u) || (p == v) || (p == w)) { continue; } Vector2 point = contour[V[p]]; if (InsideTriangle(ref _tmpA, ref _tmpB, ref _tmpC, ref point)) { return false; } } return true; }
public SquareStack(Vector2 pos, Vector2 size, Vector2 subSize, float rot, SpriteBatch batch, Texture2D texture, World world) : base(pos, batch, texture, world) { this.size = size; this.subSize = subSize; this.rot = rot; this.texture = texture; this.color = Color.Green; this.spriteOrigin = new Vector2(texture.Width / 2, texture.Height / 2); this.backCol = new Color(color.R / 2, color.G / 2, color.B / 2); rMat = Matrix.CreateRotationZ(rot); if (Settings.MaxPolygonVertices < 24) Settings.MaxPolygonVertices = 24; Vector2 leftTop = Vector2.Transform(new Vector2(-size.X / 2, -size.Y / 2), rMat); Vector2 rightTop = Vector2.Transform(new Vector2(size.X / 2, -size.Y / 2), rMat); Vector2 leftBottom = Vector2.Transform(new Vector2(-size.X / 2, size.Y / 2), rMat); Vector2 rightBottom = Vector2.Transform(new Vector2(size.X / 2, size.Y / 2), rMat); Vertices verts = new Vertices(); verts.Add(leftTop); verts.Add(rightTop); verts.Add(rightBottom); verts.Add(leftBottom); FixtureFactory.AttachPolygon(verts, density, body); this.width = max(max(leftTop.X, rightTop.X), max(leftBottom.X, rightBottom.X)) - min(min(leftTop.X, rightTop.X), min(leftBottom.X, rightBottom.X)); this.height = max(max(leftTop.Y, rightTop.Y), max(leftBottom.Y, rightBottom.Y)) - min(min(leftTop.Y, rightTop.Y), min(leftBottom.Y, rightBottom.Y)); }
/// <summary> /// Create static collidable bodies from vertices in each layer /// sent with the parameter /// </summary> /// <param name="layers">List of layers ment for making collisionboxes</param> void CreateStaticCollidables(List<Layer> layers, World world) { foreach (Layer layer in layers) { TileArray tileArray = layer.Tiles; Size tileSize = layer.TileSize; Size amntOfTiles = layer.LayerSize; Vertices vertices = new Vertices(); for (int x = 0; x < amntOfTiles.Width; x++) { for (int y = 0; y < amntOfTiles.Height; y++) { Location tileLocation = new Location(x, y); Tile thisTile = tileArray[tileLocation]; if (thisTile != null) { //Vector2 vertex = new Vector2(x * tileSize.Width, y * tileSize.Height); Vector2 vertex = new Vector2(ConvertUnits.ToSimUnits(x * tileSize.Width), ConvertUnits.ToSimUnits(y * tileSize.Height)); vertices.Add(vertex); } } } layerVertices.Add(vertices); Vertices hull = GiftWrap.GetConvexHull(vertices); Body body = BodyFactory.CreateLoopShape(world, hull); body.BodyType = BodyType.Static; body.Friction = 0.8f; body.Restitution = 0; } }
public RectanglePhysicsComponent(Engine engine, Rectangle rectangle, Vector2 gameWorldPosition, bool dynamic) : base(engine) { // create vertices to create a rectangle in the physics world with Vertices vertices = new Vertices(); vertices.Add(Engine.Physics.PositionToPhysicsWorld(new Vector2(rectangle.Left, rectangle.Top))); vertices.Add(Engine.Physics.PositionToPhysicsWorld(new Vector2(rectangle.Right, rectangle.Top))); vertices.Add(Engine.Physics.PositionToPhysicsWorld(new Vector2(rectangle.Right, rectangle.Bottom))); vertices.Add(Engine.Physics.PositionToPhysicsWorld(new Vector2(rectangle.Left, rectangle.Bottom))); MainFixture = FixtureFactory.CreatePolygon(Engine.Physics.World, vertices, 1.0f); MainFixture.Body.Position = Engine.Physics.PositionToPhysicsWorld(gameWorldPosition); if (dynamic) { MainFixture.Body.BodyType = BodyType.Dynamic; } else { MainFixture.Body.BodyType = BodyType.Static; } MainFixture.Restitution = 0.5f; // adding some linear damping gives a max speed and seems to smooth out player motion really well MainFixture.Body.LinearDamping = 1.0f; }
/// <summary> /// Removes all collinear points on the polygon. /// </summary> /// <param name="vertices">The polygon that needs simplification.</param> /// <param name="collinearityTolerance">The collinearity tolerance.</param> /// <returns>A simplified polygon.</returns> public static Vertices CollinearSimplify(Vertices vertices, float collinearityTolerance) { //We can't simplify polygons under 3 vertices if (vertices.Count < 3) return vertices; Vertices simplified = new Vertices(); for (int i = 0; i < vertices.Count; i++) { int prevId = vertices.PreviousIndex(i); int nextId = vertices.NextIndex(i); Vector2 prev = vertices[prevId]; Vector2 current = vertices[i]; Vector2 next = vertices[nextId]; //If they collinear, continue if (MathUtils.Collinear(ref prev, ref current, ref next, collinearityTolerance)) continue; simplified.Add(current); } return simplified; }
public TestRendering(IoCContainer container) { camera = new Camera2D(); RenderDelegateChainStep renderStep = new RenderDelegateChainStep("TestRendering", Render); container.Resolve<IUIRenderChain>().RegisterStep(renderStep); IInput input = container.Resolve<IInput>(); input.AddBinding(string.Empty, false, false, false, System.Windows.Forms.Keys.Up, null, (s, e) => { camera.Position += Vector3.UnitY; }); input.AddBinding(string.Empty, false, false, false, System.Windows.Forms.Keys.Down, null, (s, e) => { camera.Position -= Vector3.UnitY; }); input.AddBinding(string.Empty, false, false, false, System.Windows.Forms.Keys.Left, null, (s, e) => { camera.Position += Vector3.UnitX; }); input.AddBinding(string.Empty, false, false, false, System.Windows.Forms.Keys.Right, null, (s, e) => { camera.Position -= Vector3.UnitX; }); IDeviceContextService deviceContextService = container.Resolve<IDeviceContextService>(); DeviceContext context = deviceContextService.Context; deviceContextService.Form.ResizeEnd += new EventHandler(Form_ResizeEnd); _texture = Texture2D.FromFile(context, "Resources\\Helix.jpg", Usage.None, Pool.Managed); _elements = new TexturedElement[250]; for (int i = 0; i < _elements.Length; i++) { _elements[i] = new TexturedElement(new SharpDX.Vector2(50, 50)); _elements[i].Position = new Vector2(i * 20, i * 20); } _vertices = new Vertices<VertexPositionTexture>(context, new VertexPositionTexture() { Position = new Vector3(-0.5f, -0.5f, 0), TextureCoordinate = new Vector2(0, 0) }, new VertexPositionTexture() { Position = new Vector3(-0.5f, 0.5f, 0), TextureCoordinate = new Vector2(1, 0) }, new VertexPositionTexture() { Position = new Vector3( 0.5f, -0.5f, 0), TextureCoordinate = new Vector2(0, 1) }, new VertexPositionTexture() { Position = new Vector3( 0.5f, 0.5f, 0), TextureCoordinate = new Vector2(1, 1) }); }
private static bool CanSee(int i, int j, Vertices vertices) { if (Reflex(i, vertices)) { if (LeftOn(At(i, vertices), At(i - 1, vertices), At(j, vertices)) && RightOn(At(i, vertices), At(i + 1, vertices), At(j, vertices))) return false; } else { if (RightOn(At(i, vertices), At(i + 1, vertices), At(j, vertices)) || LeftOn(At(i, vertices), At(i - 1, vertices), At(j, vertices))) return false; } if (Reflex(j, vertices)) { if (LeftOn(At(j, vertices), At(j - 1, vertices), At(i, vertices)) && RightOn(At(j, vertices), At(j + 1, vertices), At(i, vertices))) return false; } else { if (RightOn(At(j, vertices), At(j + 1, vertices), At(i, vertices)) || LeftOn(At(j, vertices), At(j - 1, vertices), At(i, vertices))) return false; } for (int k = 0; k < vertices.Count; ++k) { if ((k + 1) % vertices.Count == i || k == i || (k + 1) % vertices.Count == j || k == j) continue; // ignore incident edges Vector2 intersectionPoint; if (LineTools.LineIntersect(At(i, vertices), At(j, vertices), At(k, vertices), At(k + 1, vertices), out intersectionPoint)) return false; } return true; }
public override void Placed() { placed = true; dragable = false; //reset color color = Color.White; //Compute Vertices top = new Vector2((float)position.X, (float)position.Y - (float)size.Y / 2f); bottomLeft = new Vector2((float)position.X - (float)size.X / 2f, (float)position.Y + (float)size.Y / 2f); bottomRight = new Vector2((float)position.X + (float)size.X / 2f, (float)position.Y + (float)size.Y / 2f); //initialize body physics parameters Vertices vertices = new Vertices(); vertices.Add(UnitConverter.toSimSpace(top)); vertices.Add(UnitConverter.toSimSpace(bottomLeft)); vertices.Add(UnitConverter.toSimSpace(bottomRight)); brickBody = BodyFactory.CreatePolygon(Game1.world, vertices, 1.0f, "TriangleBrick"); //brickBody = BodyFactory.CreateRectangle(Game1.world, UnitConverter.toSimSpace(brickWidth), UnitConverter.toSimSpace(brickHeight), 1.0f, UnitConverter.toSimSpace(position)); brickBody.BodyType = BodyType.Static; brickBody.OnCollision += BrickBody_OnCollision; brickBody.Restitution = 0.1f; brickBody.AngularDamping = 20; brickBody.Friction = 0.5f; }
private ConvexHullTest2() { _pointCloud1 = new Vertices(32); for (int i = 0; i < 32; i++) { float x = Rand.RandomFloat(-10, 10); float y = Rand.RandomFloat(-10, 10); _pointCloud1.Add(new Vector2(x, y)); } _pointCloud2 = new Vertices(_pointCloud1); _pointCloud3 = new Vertices(_pointCloud1); //Melkman DOES NOT work on point clouds. It only works on simple polygons. _pointCloud1.Translate(new Vector2(-20, 30)); _melkman = Melkman.GetConvexHull(_pointCloud1); //Giftwrap works on point clouds _pointCloud2.Translate(new Vector2(20, 30)); _giftWrap = GiftWrap.GetConvexHull(_pointCloud2); _pointCloud3.Translate(new Vector2(20, 10)); _chainHull = ChainHull.GetConvexHull(_pointCloud3); }
void Initialize() { Vertices vertices = new Vertices(); vertices.Add(new Vector2(1, 749)); vertices.Add(new Vector2(999, 749)); vertices.Add(new Vector2(999, 550)); vertices.Add(new Vector2(900, 530)); vertices.Add(new Vector2(800, 540)); vertices.Add(new Vector2(700, 530)); vertices.Add(new Vector2(620, 450)); vertices.Add(new Vector2(580, 420)); vertices.Add(new Vector2(500, 410)); vertices.Add(new Vector2(470, 500)); vertices.Add(new Vector2(400, 550)); vertices.Add(new Vector2(370, 540)); vertices.Add(new Vector2(300, 550)); vertices.Add(new Vector2(1, 510)); this.Body = BodyFactory.Instance.CreatePolygonBody(this.simulator, vertices, 10); this.Body.IsStatic = true; Geom geometry; geometry = GeomFactory.Instance.CreatePolygonGeom(this.simulator, this.Body, vertices, 1f); geometry.RestitutionCoefficient = .1f; geometry.FrictionCoefficient = 1f; geometry.Tag = this; this.brush = new Round4GroundBrush(); this.brush.Extender.Body = this.Body; }
private static void SimplifySection(Vertices vertices, int i, int j) { if ((i + 1) == j) return; Vector2 A = vertices[i]; Vector2 B = vertices[j]; double maxDistance = -1.0; int maxIndex = i; for (int k = i + 1; k < j; k++) { double distance = DistancePointLine(vertices[k], A, B); if (distance > maxDistance) { maxDistance = distance; maxIndex = k; } } if (maxDistance <= _distanceTolerance) for (int k = i + 1; k < j; k++) _usePt[k] = false; else { SimplifySection(vertices, i, maxIndex); SimplifySection(vertices, maxIndex, j); } }
/// <summary> /// Decomposes a non-convex polygon into a number of convex polygons, up /// to maxPolys (remaining pieces are thrown out). /// Each resulting polygon will have no more than Settings.MaxPolygonVertices /// vertices. /// Warning: Only works on simple polygons /// </summary> /// <param name="vertices">The vertices.</param> /// <param name="maxPolys">The maximum number of polygons.</param> /// <param name="tolerance">The tolerance.</param> /// <returns></returns> public static List<Vertices> ConvexPartition(Vertices vertices, int maxPolys, float tolerance) { if (vertices.Count < 3) return new List<Vertices> {vertices}; List<Triangle> triangulated; if (vertices.IsCounterClockWise()) { Vertices tempP = new Vertices(vertices); tempP.Reverse(); triangulated = TriangulatePolygon(tempP); } else { triangulated = TriangulatePolygon(vertices); } if (triangulated.Count < 1) { //Still no luck? Oh well... throw new Exception("Can't triangulate your polygon."); } List<Vertices> polygonizedTriangles = PolygonizeTriangles(triangulated, maxPolys, tolerance); //The polygonized triangles are not guaranteed to be without collinear points. We remove //them to be sure. for (int i = 0; i < polygonizedTriangles.Count; i++) { polygonizedTriangles[i] = SimplifyTools.CollinearSimplify(polygonizedTriangles[i], 0); } return polygonizedTriangles; }
//box2D rev 32 - for details, see http://www.box2d.org/forum/viewtopic.php?f=4&t=83&start=50 /// <summary> /// Decompose the polygon into several smaller non-concave polygon. /// Each resulting polygon will have no more than Settings.MaxPolygonVertices vertices. /// </summary> /// <param name="vertices">The vertices.</param> /// <param name="tolerance">The tolerance.</param> public static List<Vertices> ConvexPartition(Vertices vertices, float tolerance = 0.001f) { Debug.Assert(vertices.Count > 3); Debug.Assert(!vertices.IsCounterClockWise()); return TriangulatePolygon(vertices, tolerance); }
public static Body createPolygon( World world, Vertices vertices, float density, Vector2 position = new Vector2(), float rotation = 0, BodyType bodyType = BodyType.Static, object userData = null ) { for( var i = 0; i < vertices.Count; i++ ) vertices[i] *= FSConvert.displayToSim; return FarseerPhysics.Factories.BodyFactory.CreatePolygon( world, vertices, density, FSConvert.toSimUnits( position ), rotation, bodyType, userData ); }
public static Body createLoopShape( World world, Vertices vertices, Vector2 position = new Vector2(), object userData = null ) { for( var i = 0; i < vertices.Count; i++ ) vertices[i] *= FSConvert.displayToSim; return FarseerPhysics.Factories.BodyFactory.CreateLoopShape( world, vertices, FSConvert.toSimUnits( position ), userData ); }
/// <summary> /// Implements "A new algorithm for Boolean operations on general polygons" /// available here: http://liama.ia.ac.cn/wiki/_media/user:dong:dong_cg_05.pdf /// Merges two polygons, a subject and a clip with the specified operation. Polygons may not be /// self-intersecting. /// /// Warning: May yield incorrect results or even crash if polygons contain collinear points. /// </summary> /// <param name="subject">The subject polygon.</param> /// <param name="clip">The clip polygon, which is added, /// substracted or intersected with the subject</param> /// <param name="clipType">The operation to be performed. Either /// Union, Difference or Intersection.</param> /// <param name="error">The error generated (if any)</param> /// <returns>A list of closed polygons, which make up the result of the clipping operation. /// Outer contours are ordered counter clockwise, holes are ordered clockwise.</returns> private static List<Vertices> Execute(Vertices subject, Vertices clip, PolyClipType clipType, out PolyClipError error) { Debug.Assert(subject.IsSimple() && clip.IsSimple(), "Non simple input!", "Input polygons must be simple (cannot intersect themselves)."); // Copy polygons Vertices slicedSubject; Vertices slicedClip; // Calculate the intersection and touch points between // subject and clip and add them to both CalculateIntersections(subject, clip, out slicedSubject, out slicedClip); // Translate polygons into upper right quadrant // as the algorithm depends on it Vector2 lbSubject = subject.GetAABB().LowerBound; Vector2 lbClip = clip.GetAABB().LowerBound; Vector2 translate; Vector2.Min(ref lbSubject, ref lbClip, out translate); translate = Vector2.One - translate; if (translate != Vector2.Zero) { slicedSubject.Translate(ref translate); slicedClip.Translate(ref translate); } // Enforce counterclockwise contours slicedSubject.ForceCounterClockWise(); slicedClip.ForceCounterClockWise(); List<Edge> subjectSimplices; List<float> subjectCoeff; List<Edge> clipSimplices; List<float> clipCoeff; // Build simplical chains from the polygons and calculate the // the corresponding coefficients CalculateSimplicalChain(slicedSubject, out subjectCoeff, out subjectSimplices); CalculateSimplicalChain(slicedClip, out clipCoeff, out clipSimplices); List<Edge> resultSimplices; // Determine the characteristics function for all non-original edges // in subject and clip simplical chain and combine the edges contributing // to the result, depending on the clipType CalculateResultChain(subjectCoeff, subjectSimplices, clipCoeff, clipSimplices, clipType, out resultSimplices); List<Vertices> result; // Convert result chain back to polygon(s) error = BuildPolygonsFromChain(resultSimplices, out result); // Reverse the polygon translation from the beginning // and remove collinear points from output translate *= -1f; for (int i = 0; i < result.Count; ++i) { result[i].Translate(ref translate); SimplifyTools.CollinearSimplify(result[i]); } return result; }
public PathTile(List<Vector2> localPoints, Vector2 position, World world, bool MakroCollision = false) { body = new Body(world); body.Position = ConvertUnits.ToSimUnits(position); body.UserData = "Wall"; body.IsStatic = true; Vertices terrain = new Vertices(); foreach (Vector2 point in localPoints) { terrain.Add(ConvertUnits.ToSimUnits(point)); } for (int i = 0; i < terrain.Count - 1; ++i) { FixtureFactory.AttachEdge(terrain[i], terrain[i + 1], body); body.FixtureList[i].UserData = "Wall"; } body.Restitution = 0f; body.Friction = float.MaxValue; if (!MakroCollision) body.CollisionCategories = Category.Cat15 & ~Category.Cat3; else body.CollidesWith = Category.Cat29; }
public FSCollisionPolygon(List <Vector2> vertices) : this() { _verts = new Vertices(vertices); _verts.Scale(new Vector2(FSConvert.DisplayToSim)); }
public static List<Vertices> ConvexPartition(Vertices vertices) { Polygon poly = new Polygon(); foreach (FVector2 vertex in vertices) { poly.Points.Add(new TriangulationPoint(vertex.X, vertex.Y)); } DTSweepContext tcx = new DTSweepContext(); tcx.PrepareTriangulation(poly); DTSweep.Triangulate(tcx); List<Vertices> results = new List<Vertices>(); foreach (DelaunayTriangle triangle in poly.Triangles) { Vertices v = new Vertices(); foreach (TriangulationPoint p in triangle.Points) { v.Add(new FVector2((float)p.X, (float)p.Y)); } results.Add(v); } return results; }