private void button2_Click(object sender, EventArgs e) { try { var sides = textBox2.Text; if (!string.IsNullOrEmpty(textBox2.Text)) { var points = sides.Split(new [] { ' ' }); var side1 = int.Parse(points[0]); var side2 = int.Parse(points[1]); var side3 = int.Parse(points[2]); triangle = new Triangle(side1, side2, side3); isScaleneLbl.Text = triangle.IsScalene() ? "yes" : "no"; isIsolescenesLbl.Text = triangle.IsIsosceles() ? "yes" : "no"; isEquilateralLbl.Text = triangle.IsEquilateral() ? "yes" : "no"; Refresh(); } } catch (FormatException ex) { MessageBox.Show("Couldn't parse input!"); } catch (ArgumentException ex) { MessageBox.Show(ex.Message); } }
public static void Main(string[] args) { string results = ""; int x= 0; Triangle[]ta = new Triangle[4]; while( x < 4 ) { ta[x] = new Triangle(); ta[x].height = (x + 1) * 2; ta[x].length = x + 4; ta[x].setArea(); results += "triangle" + x + ", area"; results += " = " + ta[x].area + "\n"; x = x + 1; } int y = x; x = 27; Triangle t5 = ta[2]; ta[2].area = 343; results += "y = " + y; MessageBox.Show(results + ", t5 area = " + t5.area); }
protected void AddVertex(Face face, Vertex vertex) { base.AddVertex(vertex); Faces.Remove(face); HalfEdge h1 = face.HalfEdge; HalfEdge h2 = h1.Next; HalfEdge h3 = h2.Next; HalfEdge h4 = new HalfEdge(h1.Origin); HalfEdge h5 = new HalfEdge(h2.Origin); HalfEdge h6 = new HalfEdge(h3.Origin); HalfEdge h7 = new HalfEdge(vertex); HalfEdge h8 = new HalfEdge(vertex); HalfEdge h9 = new HalfEdge(vertex); HalfEdges.AddRange(new List<HalfEdge> {h4, h5, h6, h7, h8, h9}); h4.Twin = h7; h7.Twin = h4; h5.Twin = h8; h8.Twin = h5; h6.Twin = h9; h9.Twin = h6; // Set all next h1.Next = h5; h5.Prev = h1; h5.Next = h7; h7.Prev = h5; h7.Next = h1; h1.Prev = h7; h2.Next = h6; h6.Prev = h2; h6.Next = h8; h8.Prev = h6; h8.Next = h2; h2.Prev = h8; h3.Next = h4; h4.Prev = h3; h4.Next = h9; h9.Prev = h4; h9.Next = h3; h3.Prev = h9; Triangle t1 = new Triangle(h1); Triangle t2 = new Triangle(h2); Triangle t3 = new Triangle(h3); Faces.Add(t1); Faces.Add(t2); Faces.Add(t3); Tree.Add(vertex, t1, t2, t3); LogEntry logEntry = new LogEntry("Adding edges.", this); logEntry.Objects.Add(vertex); Log.Add(logEntry); }
public Mesh Clone() { Mesh result = new Mesh(); #if COLLIDER_ODE result.PBS = PBS; #endif foreach (Vertex v in vertices) { if (v == null) result.vertices.Add(null); else result.vertices.Add(v.Clone()); } foreach (Triangle t in triangles) { int iV1, iV2, iV3; iV1 = vertices.IndexOf(t.v1); iV2 = vertices.IndexOf(t.v2); iV3 = vertices.IndexOf(t.v3); Triangle newT = new Triangle(result.vertices[iV1], result.vertices[iV2], result.vertices[iV3]); result.Add(newT); } return result; }
public MeshGrid(int sizeX, int sizeZ, float squareSideSize) { //this.device = device; //basicEffect = new BasicEffect(device); this.sizeX = sizeX; this.sizeZ = sizeZ; this.Vertices = new VertexPositionNormalTexture[sizeX + 1, sizeZ + 1]; this.Triangles = new Triangle[sizeX*sizeZ*2]; var rand = new Random(); int texParam = 2; for (int x = 0; x < sizeX+1; x++) for (int z = 0; z < sizeZ+1; z++) this.Vertices[x, z] = new VertexPositionNormalTexture( new Vector3(squareSideSize*x, Noise.Generate(x, z)/4, squareSideSize*z), Vector3.Up, new Vector2(texParam * (float)x/(float)SizeX,texParam * (float)z/(float)SizeZ)); for (int x = 0; x < sizeX; x++) for (int z = 0; z < sizeZ; z++) { Triangles[x * 2 * sizeZ + z] = new Triangle(x, z, x, z + 1, x + 1, z); Triangles[x * 2 * sizeZ + sizeZ + z] = new Triangle(x, z + 1, x + 1, z, x + 1, z + 1); } }
public void badTrianglePointConstructorTest() { Point pointa = new Point(1, 0); Point pointb = new Point(1, 0); Point pointc = new Point(3, 5); Triangle tria = new Triangle(pointa, pointb, pointc); }
/// <summary> /// Checks if a given set of points forms an ear for a given polygon /// </summary> /// <param name="polygonPoints">The points describing the polygon</param> /// <param name="ear">The resulting ear, if applicable</param> /// <returns>True if these points form an ear</returns> private static bool IsEar(Point2D p1, Point2D p2, Point2D p3, List<Point2D> polygonPoints, out Triangle ear) { // for now, assign null to the ear ear = null; // Check if these points form a concave angle //if (Point2D.CalculateAngle(p1, p2, p3) > 0) // return false; // Can't be an ear // Make a triangle from the given points Triangle t = new Triangle(p1, p2, p3); // Check all other points of the polygon, if one falls within this triangle, this isn't an ear foreach (Point2D p in polygonPoints) if (!p.Equals(p1) && !p.Equals(p2) && !p.Equals(p3)) if (Triangle.PointInTriangle(t, p)) return false; // Sort our points counter-clockwise (this is how wpf indices-triangles face 'up') t.Points = Point2D.SortPoints(true, p1, p2, p3).ToArray(); // This is an ear ear = t; // Remove the center point out of the polygon polygonPoints.Remove(p1); // Report succes return true; }
/// <summary> /// Optimized Heightmap, using cells to optimize process of drawing and modifying. /// The heightmap is divided into cells which are each surrounded by a bounding box and /// hidden if they are outside of the field of view or too far away. The bounding boxes /// are also used to speed up the ray detection test when making modifications to the terrain. /// </summary> /// <param name="divisions">Size of the map, ex: 256x256</param> /// <param name="cellsize">The size of a single quad, ex: 50x50</param> /// <param name="cellDivisions">Number of quads in each heightmap cell, ex: 16x16</param> public Optimized_Heightmap(GraphicsDevice graphicsDevice, Point divisions, Vector2 cellsize, Point cellDivisions) { this.size = divisions; this.cellSize = cellsize; this.cellDivisions = cellDivisions; //basicEffect = new BasicEffect(graphicsDevice, null); //basicEffect.VertexColorEnabled = true; effect = Editor.content.Load<Effect>(@"content\shaders\opt_heightmap"); effectParams = new EffectParams(ref effect, "TransformWireframe"); int w = (int)((float)divisions.X / (float)cellDivisions.X); int h = (int)((float)divisions.Y / (float)cellDivisions.Y); cell = new HeightmapCell[w, h]; //Build the cells for (int y = 0; y < w; y++) { for (int x = 0; x < h; x++) { //get the adjacent cells (max 3) : [0,0],[0,1],[1,0] HeightmapCell[,] adjacent_cell = new HeightmapCell[2, 2]; if (x > 0) adjacent_cell[0, 1] = cell[x - 1, y]; if (y > 0) adjacent_cell[1, 0] = cell[x, y - 1]; if (x > 0 && y > 0) adjacent_cell[0, 0] = cell[x - 1, y - 1]; cell[x, y] = new HeightmapCell(graphicsDevice, new Point(x, y), cellDivisions, cellsize, adjacent_cell); } } HeightmapCell.Tri collisionTri = cell[0,0].triangle[0]; testTri = new Triangle(collisionTri.p1, collisionTri.p2, collisionTri.p3, Color.White); }
public void BasicCase2ShouldReturnBasicTriangles() { var vol1 = new Mock<IVolume>(); vol1.SetupAllProperties(); vol1.Setup(x => x.Height).Returns(1); vol1.Setup(x => x.Depth).Returns(1); vol1.Setup(x => x.Width).Returns(1); vol1.Setup(x => x.GetVoxelValueAt(0, 0, 0)).Returns(FullBlack); vol1.Setup(x => x.GetVoxelValueAt(0, 1, 0)).Returns(FullBlack); var t1 = new Triangle { Edge1 = new Point3D { X = 0.5, Y = 0.0, Z = 0.0 }, Edge2 = new Point3D { X = 0.0, Y = 0.5, Z = 1.0 }, Edge3 = new Point3D { X = 0.5, Y = 1.0, Z = 0.5 } }; var t2 = new Triangle { Edge1 = new Point3D { X = 0.5, Y = 0.0, Z = 0.0 }, Edge2 = new Point3D { X = 0.0, Y = 0.0, Z = 0.5 }, Edge3 = new Point3D { X = 0.5, Y = 1.0, Z = 0.5 } }; var expected = new List<ITriangle> { t1, t2 }; Assert.AreEqual(expected, MarchingCubes.Instance.GetTriangles(vol1.Object, Threshold, GridSize)); }
public void arrayConstructorTest() { double[] arraySides; arraySides = new double[] { 1.3, 3.5, 2.3 }; Triangle tria = new Triangle(arraySides); Assert.IsTrue(tria.isCorrectTriangle()); }
public void isScalenetest() { Triangle tri = new Triangle(1.0, 2.0, 3.0); Assert.IsTrue(tri.isScalene()); Assert.IsFalse(tri.isIsosceles()); Assert.IsFalse(tri.isEquilateral()); }
public void AssignChildren(Triangle cm, Triangle ct, Triangle cl, Triangle cr) { childMid = cm; childTop = ct; childLeft = cl; childRight = cr; }
public void BarycentricTest() { var t = new Triangle(new Vector3F(0, 0, 0), new Vector3F(1, 0, 0), new Vector3F(0, 1, 0)); Assert.AreEqual(true, GeometryHelper.IsOver(t, new Vector3F(0, 0, 0))); Assert.AreEqual(true, GeometryHelper.IsOver(t, new Vector3F(1, 0, 0))); Assert.AreEqual(true, GeometryHelper.IsOver(t, new Vector3F(0, 1, 0))); Assert.AreEqual(true, GeometryHelper.IsOver(t, new Vector3F(0, 0.3f, 2))); Assert.AreEqual(true, GeometryHelper.IsOver(t, new Vector3F(0.1f, 0.1f, -1))); Assert.AreEqual(false, GeometryHelper.IsOver(t, new Vector3F(0, 2, 0))); Assert.AreEqual(false, GeometryHelper.IsOver(t, new Vector3F(1, 1, 0))); t = new Triangle(new Vector3F(0, 0, 0), new Vector3F(0, 1, 0), new Vector3F(0, 0, 1)); Assert.AreEqual(true, GeometryHelper.IsOver(t, new Vector3F(0, 0, 0))); Assert.AreEqual(true, GeometryHelper.IsOver(t, new Vector3F(0, 1, 0))); Assert.AreEqual(true, GeometryHelper.IsOver(t, new Vector3F(0, 0, 1))); Assert.AreEqual(true, GeometryHelper.IsOver(t, new Vector3F(2, 0.3f, 0))); Assert.AreEqual(true, GeometryHelper.IsOver(t, new Vector3F(-1, 0.1f, 0.1f))); Assert.AreEqual(false, GeometryHelper.IsOver(t, new Vector3F(0, 2, 0))); Assert.AreEqual(false, GeometryHelper.IsOver(t, new Vector3F(1, 2, 1))); t = new Triangle(new Vector3F(0, 0, 0), new Vector3F(1, 0, 0), new Vector3F(0, 0, 1)); Assert.AreEqual(true, GeometryHelper.IsOver(t, new Vector3F(0, 0, 0))); Assert.AreEqual(true, GeometryHelper.IsOver(t, new Vector3F(1, 0, 0))); Assert.AreEqual(true, GeometryHelper.IsOver(t, new Vector3F(0, 0, 1))); Assert.AreEqual(true, GeometryHelper.IsOver(t, new Vector3F(0.3f, 2, 0))); Assert.AreEqual(true, GeometryHelper.IsOver(t, new Vector3F(0.1f, -1, 0.1f))); Assert.AreEqual(false, GeometryHelper.IsOver(t, new Vector3F(0, 0, 2))); Assert.AreEqual(false, GeometryHelper.IsOver(t, new Vector3F(1, 0, 1))); }
static void Main() { var trianlgle = new Triangle(3, 4, 5); Console.WriteLine(trianlgle.CalcTriangleArea(new HeronsFormulaArea())); Console.WriteLine(ConvertNumberToString(5)); Console.WriteLine(FindMaxNumber(5, -1, 3, 2, 14, 2, 3)); PrintInNumericFormat(1.3, "fixed-point"); PrintInNumericFormat(0.75, "percentage"); PrintInNumericFormat(2.30, "leftIndented"); bool horizontal, vertical; Console.WriteLine(CalcPointDistance(3, -1, 3, 2.5)); Console.WriteLine("Horizontal? " + CheckIfHorizontal(3, -1, 3, 2.5, out horizontal)); Console.WriteLine("Vertical? " + CheckIfVertical(3, -1, 3, 2.5, out vertical)); Student peter = new Student("Peter", "Ivanov", "From Sofia, born at 17.03.1992"); Student stella = new Student("Stella", "Markova", "From Vidin, gamer, high results, born at 03.11.1993"); Console.WriteLine("{0} older than {1} -> {2}", peter.FirstName, stella.FirstName, peter.IsOlderThan(stella)); }
public VoronoiDiagram(MeshFilter mesh, Transform transform) { _initial = new Triangle(new Pnt(-10000, -10000), new Pnt(10000, -10000), new Pnt(0, 10000)); _delaunay = new Triangulation(_initial); _mesh = mesh; _transform = transform; }
public void TestInterpolatedEmissiveWorldTriangle() { Triangle triangle = new Triangle( new Point( 0.0f, 0.0f, 3.0f ), new Point( 1.0f, 0.0f, 3.0f ), new Point( 1.0f, 1.0f, 3.0f ) ); BarycentricInterpolatedEmissiveMaterial I = new BarycentricInterpolatedEmissiveMaterial( new Color3( 1.0f, 0.0f, 0.0f ), new Color3( 0.0f, 1.0f, 0.0f ), new Color3( 0.0f, 0.0f, 1.0f ) ); SimpleObject so = new SimpleObject( triangle, null, new EmissiveMaterialBase[] { I, I }, null, null, null ); ListScene scene = new ListScene(); scene.Add( so ); Framebuffer fb = new Framebuffer( Color3.Black, 500, 500 ); Cameras.Pinhole( scene, RenderMethod.RecursiveRayTrace, fb, 0, 0.0001f, 0, 1.0f, true, 1.0f, 1.0f, 1.0f, new Point( 0.0f, 0.0f, -2.0f ), new Vector( 0.0f, 0.0f, 1.0f ), new Vector( 0.0f, 1.0f, 0.0f ), 1, 1, false ); Assert.IsTrue( Pfm.Compare( fb, 0.01f, 0.02f, "..\\..\\TestImages\\TestInterpolatedEmissiveWorldTriangle.pfm" ) ); }
/// <summary> /// Individual puzzle. Create a square from 4 triangles. /// </summary> /// <param name="game">The game object associated with this puzzle.</param> /// <param name="player">The player who may complete this puzzle.</param> public CreateASquare(Game game, Player player) : base(game, player) { Triangles = new List<Triangle>(); countUpdates = 0; tri1 = new Triangle(); tri2 = new Triangle(); tri3 = new Triangle(); tri4 = new Triangle(); tri1.Location = new Rectangle(120, 37, 84, 42); tri2.Location = new Rectangle(78, 79, 84, 42); tri3.Location = new Rectangle(162, 79, 84, 42); tri4.Location = new Rectangle(120, 121, 84, 42); //Are you proud of me yet? tri1.Rot = (randNum = Game1.random.Next(0,2)) == 0 ? Orientation.Up : randNum == 1 ? Orientation.Left : Orientation.Right; tri2.Rot = (randNum = Game1.random.Next(0,2)) == 0 ? Orientation.Left : randNum == 1 ? Orientation.Up : Orientation.Down; tri3.Rot = (randNum = Game1.random.Next(0,2)) == 0 ? Orientation.Right : randNum == 1 ? Orientation.Up : Orientation.Down; tri4.Rot = (randNum = Game1.random.Next(0,2)) == 0 ? Orientation.Down : randNum == 1 ? Orientation.Left : Orientation.Right; tri1.Stat = Status.Waiting; tri2.Stat = Status.Waiting; tri3.Stat = Status.Waiting; tri4.Stat = Status.Waiting; Triangles.Add(tri1); Triangles.Add(tri2); Triangles.Add(tri3); Triangles.Add(tri4); leftClick = new LeftClick(game, player); }
public void Initialize(Microsoft.Xna.Framework.Game game, Color color, IEnumerable<IEnumerable<Vector3>> verticeLists, IEnumerable<IEnumerable<Triangle<byte>>> triangleLists) { int listCount = verticeLists.Count(); var vertCount = verticeLists.Sum(l => l.Count()); var triCount = triangleLists.Sum(l => l.Count()); var verts = new Vector3[vertCount]; var tris = new Triangle<uint>[triCount]; int c = 0; int tc = 0; for (int i = 0; i < listCount; i++) { var vertList = verticeLists.ElementAt(i); var triList = triangleLists.ElementAt(i); var vertOffset = (uint)c; foreach (var vert in vertList) verts[c++] = vert; foreach (var tri in triList) { tris[tc++] = new Triangle<uint>(tri.Type, tri.V0 + vertOffset, tri.V1 + vertOffset, tri.V2 + vertOffset); } } Initialize(game, color, verts, tris); }
public TriangleOver(Triangle t) { triangles = (float[][])Arrays.CreateJaggedArray(typeof(float), t.GetTriangleCount() * 6 * 3, 2); int tcount = 0; for (int i = 0; i < t.GetTriangleCount(); i++) { float cx = 0; float cy = 0; for (int p = 0; p < 3; p++) { float[] pt = t.GetTrianglePoint(i, p); cx += pt[0]; cy += pt[1]; } cx /= 3; cy /= 3; for (int p_0 = 0; p_0 < 3; p_0++) { int n = p_0 + 1; if (n > 2) { n = 0; } float[] pt1 = t.GetTrianglePoint(i, p_0); float[] pt2 = t.GetTrianglePoint(i, n); pt1[0] = (pt1[0] + pt2[0]) / 2; pt1[1] = (pt1[1] + pt2[1]) / 2; triangles[(tcount * 3) + 0][0] = cx; triangles[(tcount * 3) + 0][1] = cy; triangles[(tcount * 3) + 1][0] = pt1[0]; triangles[(tcount * 3) + 1][1] = pt1[1]; triangles[(tcount * 3) + 2][0] = pt2[0]; triangles[(tcount * 3) + 2][1] = pt2[1]; tcount++; } for (int p_1 = 0; p_1 < 3; p_1++) { int n_2 = p_1 + 1; if (n_2 > 2) { n_2 = 0; } float[] pt1_3 = t.GetTrianglePoint(i, p_1); float[] pt2_4 = t.GetTrianglePoint(i, n_2); pt2_4[0] = (pt1_3[0] + pt2_4[0]) / 2; pt2_4[1] = (pt1_3[1] + pt2_4[1]) / 2; triangles[(tcount * 3) + 0][0] = cx; triangles[(tcount * 3) + 0][1] = cy; triangles[(tcount * 3) + 1][0] = pt1_3[0]; triangles[(tcount * 3) + 1][1] = pt1_3[1]; triangles[(tcount * 3) + 2][0] = pt2_4[0]; triangles[(tcount * 3) + 2][1] = pt2_4[1]; tcount++; } } }
public static List<List<Vector2>> clip(List<Vector2> boundary, Triangle piece) { //create Boundary Polygon Polygons boundaryPoly = createPolygons(boundary); //create Polygon from the triangular piece Polygons subjPoly = createPolygons(piece); //clip triangular polygon against the boundary polygon Polygons result = new Polygons(); Clipper c = new Clipper(); c.AddPaths(subjPoly, PolyType.ptClip, true); c.AddPaths(boundaryPoly, PolyType.ptSubject, true); c.Execute(ClipType.ctIntersection, result, PolyFillType.pftEvenOdd, PolyFillType.pftEvenOdd); List<List<Vector2>> clippedPolygons = new List<List<Vector2>>(); foreach (Polygon poly in result) { List<Vector2> clippedPoly = new List<Vector2>(); foreach (IntPoint p in poly) { clippedPoly.Add(new Vector2(p.X, p.Y) / multiplier); } clippedPolygons.Add(clippedPoly); } return clippedPolygons; }
public void CoplanarAndDegenerate() { var tA = new Triangle(new Vector3F(0, 0, 0), new Vector3F(0, 0, 10), new Vector3F(0, 0, 10)); var tB = new Triangle(new Vector3F(-10, 0, 10), new Vector3F(-10, 0, 20), new Vector3F(10, 0, 20)); for (int i = 0; i < 2; i++) { for (int j = 0; j < 3; j++) { for (int k = 0; k < 3; k++) { Vector3F p, n; float d; bool haveContact = TriangleTriangleAlgorithm.GetContact(ref tA, ref tB, out p, out n, out d); Assert.AreEqual(false, haveContact); // "Rotate" triangle to test next edges. var oldB = tB; tB[0] = oldB[1]; tB[1] = oldB[2]; tB[2] = oldB[0]; } // "Rotate" triangle to test next edges. var oldA = tA; tA[0] = oldA[1]; tA[1] = oldA[2]; tA[2] = oldA[0]; } MathHelper.Swap(ref tA, ref tB); } }
// Button Methods private void btnCalculate_Click(object sender, EventArgs e) { double length; // TryParse method must be evaluated first so it can set the length variable if (Double.TryParse(txtLength.Text, out length) && length > 0) { RegularPolygon selectedPolygon; // Select child class based on what radio button the user has selected if (rbTriangle.Checked) { selectedPolygon = new Triangle(length); } else if (rbSquare.Checked) { selectedPolygon = new Square(length); } else { selectedPolygon = new Pentagon(length); } // Calculate and display the perimeter and area of the regular polygon lblCalculatedPerimeter.Text = String.Format("{0}", selectedPolygon.CalculatePerimeter()); lblCalculatedArea.Text = String.Format("{0}", selectedPolygon.CalculateArea()); } else { MessageBox.Show("You have entered an invaild length.\nPlease enter a positive numeric value and try agian.", "Invalid Length", MessageBoxButtons.OK, MessageBoxIcon.Warning); ClearAllFields(); } }
public void SetSize(float left, float right, float bottom, float top) { var tris = new Triangle<VertexTP2>[2]; var p1 = new Vector2(left , bottom); var p2 = new Vector2(right, bottom); var p3 = new Vector2(right, top); var p4 = new Vector2(left, top); var t1 = new Vector2(0f, 0f); var t2 = new Vector2(1f, 0f); var t3 = new Vector2(1f, 1f); var t4 = new Vector2(0f, 1f); tris[0].A.Position = p1; tris[0].A.TexCoord = t1; tris[0].B.Position = p2; tris[0].B.TexCoord = t2; tris[0].C.Position = p3; tris[0].C.TexCoord = t3; tris[1].A.Position = p3; tris[1].A.TexCoord = t3; tris[1].B.Position = p4; tris[1].B.TexCoord = t4; tris[1].C.Position = p1; tris[1].C.TexCoord = t1; GL.BindBuffer(BufferTarget.ArrayBuffer, vbo); var sizeInBytes = Marshal.SizeOf(new Triangle<VertexTP2>()); GL.BufferData(BufferTarget.ArrayBuffer, new IntPtr(sizeInBytes * 2), tris, BufferUsageHint.StaticDraw); }
public static void Main() { Triangle triangle = new Triangle(3, 4, 5); AreaCalculator areaCalculator = new AreaCalculator(triangle); double triangleArea = areaCalculator.CalcArea(); Console.WriteLine(triangleArea); }
public void isScaleneTest() { Triangle tritest = new Triangle(3.0, 4.0, 5.0); Assert.IsTrue(tritest.isScalene()); Assert.IsFalse(tritest.isIsosceles()); Assert.IsFalse(tritest.isEquilateral()); }
static void Main() { var shapes = new Shape[numberOfShapes]; for (int i = 0; i < shapes.Length; i++) { switch (vladoRandoma.Next() % 3) { case 0: shapes[i] = new Triangle(widths[vladoRandoma.Next(0, widths.Length)], heights[vladoRandoma.Next(0, heights.Length)]); break; case 1: shapes[i] = new Rectangle(widths[vladoRandoma.Next(0, widths.Length)], heights[vladoRandoma.Next(0, heights.Length)]); break; case 2: shapes[i] = new Circle(heights[vladoRandoma.Next(0, heights.Length)]); break; default: break; } } foreach (var item in shapes) { Console.WriteLine(item.ToString().Replace(',', '.')); } }
static void Main(string[] args) { List<String> triangles = new List<String>(); try { FileStream file = new FileStream("triangles.txt", FileMode.Open); StreamReader stream = new StreamReader(file); while(!stream.EndOfStream) { triangles.Add(stream.ReadLine()); } stream.Close(); file.Close(); } catch(Exception e) { Console.WriteLine(e); } int count = 0; for (int i = 0; i < triangles.Count; i++) { bool result = new Triangle(triangles[i]).Score(); if(result) { count++; } } Console.WriteLine(count); Console.ReadLine(); }
/*1. Define abstract class Shape with only one abstract method CalculateSurface() and fields width and height. * Define two new classes Triangle and Rectangle that implement the virtual method and * return the surface of the figure (height*width for rectangle and height*width/2 for triangle). * Define class Circle and suitable constructor so that * on initialization height must be kept equal to width and implement the CalculateSurface() method. * Write a program that tests the behavior of the CalculateSurface() method for different shapes (Circle, Rectangle, Triangle) stored in an array.*/ static void Main() { Shape rectangle = new Rectangle(4.0, 5.5); Console.WriteLine("Surface of rectangle is: {0}", rectangle.CalculateSurface()); Shape triangle = new Triangle(4.0, 5.5); Console.WriteLine("Surface of triangle is: {0}", triangle.CalculateSurface()); Shape circle = new Circle(4.5); Console.WriteLine("Surface of circle is: {0:F6}", circle.CalculateSurface()); Console.WriteLine(); Console.WriteLine("---different shapes---"); Shape[] shapes = {rectangle, triangle, circle, new Circle(6.3), new Triangle(4.6, 7.3) }; foreach (var shape in shapes) { Console.WriteLine("Surface of {0} is {1}", shape.GetType(), shape.CalculateSurface()); } }
public void ExpectArgumentExceptionWhenCreateInvalidTriangle() { var validExceptionsCount = 3; var exceptionCount = 0; var sideCases = new List<Sides> { new Sides(1.0, 2.0, 5.0), new Sides(-2.0, 4.0, 5.0), new Sides(0, 1.0, 2.0) }; foreach (var side in sideCases) { try { var triangle = new Triangle(side.A, side.B, side.C); } catch (ArgumentException) { exceptionCount++; } catch (Exception ex) { Assert.Fail("Возникло не ожидаемое исключение. Детали: {0}", ex.Message); } } Assert.AreEqual(validExceptionsCount, exceptionCount); }
public void PlotTriple(Site s1, Site s2, Site s3) { if (Debug) { Console.WriteLine("triple {0} {1} {2}", s1, s2, s3); } var triangle = new Triangle(s1, s2, s3) { New = true }; Triangles.Add(triangle); }
protected void DrawTriangle(TextureGL texture, Triangle vertexTriangle, ColourInfo drawColour, RectangleF?textureRect = null, Action <TexturedVertex2D> vertexAction = null, Vector2?inflationPercentage = null) => texture.DrawTriangle(vertexTriangle, drawColour, textureRect, vertexAction, inflationPercentage);
public static void CollDetectSphereStaticMeshOverlap(BoundingSphere oldSphere, BoundingSphere newSphere, TriangleMesh mesh, CollDetectInfo info, float collTolerance, CollisionFunctor collisionFunctor) { Vector3 body0Pos = (info.Skin0.Owner != null) ? info.Skin0.Owner.OldPosition : Vector3.Zero; Vector3 body1Pos = (info.Skin1.Owner != null) ? info.Skin1.Owner.OldPosition : Vector3.Zero; float sphereTolR = collTolerance + newSphere.Radius; float sphereTolR2 = sphereTolR * sphereTolR; unsafe { #if USE_STACKALLOC SmallCollPointInfo *collPts = stackalloc SmallCollPointInfo[MaxLocalStackSCPI]; int *potentialTriangles = stackalloc int[MaxLocalStackTris]; { { #else SmallCollPointInfo[] collPtArray = SCPIStackAlloc(); fixed(SmallCollPointInfo *collPts = collPtArray) { int[] potTriArray = IntStackAlloc(); fixed(int *potentialTriangles = potTriArray) { #endif int numCollPts = 0; Vector3 collNormal = Vector3.Zero; BoundingBox bb = BoundingBoxHelper.InitialBox; BoundingBoxHelper.AddSphere(newSphere, ref bb); int numTriangles = mesh.GetTrianglesIntersectingtAABox(potentialTriangles, MaxLocalStackTris, ref bb); // Deano : get the spheres centers in triangle mesh space Vector3 newSphereCen = Vector3.Transform(newSphere.Center, mesh.InverseTransformMatrix); Vector3 oldSphereCen = Vector3.Transform(oldSphere.Center, mesh.InverseTransformMatrix); for (int iTriangle = 0; iTriangle < numTriangles; ++iTriangle) { IndexedTriangle meshTriangle = mesh.GetTriangle(potentialTriangles[iTriangle]); float distToCentre = meshTriangle.Plane.DotCoordinate(newSphereCen); if (distToCentre <= 0.0f) { continue; } if (distToCentre >= sphereTolR) { continue; } int i0, i1, i2; meshTriangle.GetVertexIndices(out i0, out i1, out i2); Triangle triangle = new Triangle(mesh.GetVertex(i0), mesh.GetVertex(i1), mesh.GetVertex(i2)); float s, t; float newD2 = Distance.PointTriangleDistanceSq(out s, out t, newSphereCen, triangle); if (newD2 < sphereTolR2) { // have overlap - but actually report the old intersection float oldD2 = Distance.PointTriangleDistanceSq(out s, out t, oldSphereCen, triangle); float dist = (float)System.Math.Sqrt((float)oldD2); float depth = oldSphere.Radius - dist; Vector3 triPointSTNorm = oldSphereCen - triangle.GetPoint(s, t); JiggleMath.NormalizeSafe(ref triPointSTNorm); Vector3 collisionN = (dist > float.Epsilon) ? triPointSTNorm : triangle.Normal; // since impulse get applied at the old position Vector3 pt = oldSphere.Center - oldSphere.Radius * collisionN; if (numCollPts < MaxLocalStackSCPI) { collPts[numCollPts++] = new SmallCollPointInfo(pt - body0Pos, pt - body1Pos, depth); } collNormal += collisionN; } } if (numCollPts > 0) { JiggleMath.NormalizeSafe(ref collNormal); collisionFunctor.CollisionNotify(ref info, ref collNormal, collPts, numCollPts); } #if USE_STACKALLOC } } #else FreeStackAlloc(potTriArray); } FreeStackAlloc(collPtArray); } #endif } }
/// <summary> /// GetBoxTriangleIntersectionPoints /// Pushes intersection points onto the back of pts. Returns the /// number of points found. /// Points that are close together (compared to /// combinationDistance) get combined /// </summary> /// <param name="pts"></param> /// <param name="box"></param> /// <param name="triangle"></param> /// <param name="combinationDistance"></param> /// <returns>int</returns> private static int GetBoxTriangleIntersectionPoints(List <Vector3> pts, Box box, Triangle triangle, float combinationDistance) { // first intersect each edge of the box with the triangle Box.Edge[] edges; box.GetEdges(out edges); Vector3[] boxPts; box.GetCornerPoints(out boxPts); float tS; float tv1, tv2; // BEN-OPTIMISATION: Allocating just one Vector3 to be reused. Vector3 point = new Vector3(); int iEdge; for (iEdge = 0; iEdge < 12; ++iEdge) { Box.Edge edge = edges[iEdge]; Segment seg = new Segment(boxPts[(int)edge.Ind0], boxPts[(int)edge.Ind1] - boxPts[(int)edge.Ind0]); if (Intersection.SegmentTriangleIntersection(out tS, out tv1, out tv2, seg, triangle)) { // BEN-OPTIMISATION: Reusing the existing point variable instead allocating new ones. // This also allows point to be based by reference. seg.GetPoint(ref point, tS); AddPoint(pts, ref point, combinationDistance * combinationDistance); } } Vector3 pos, n; // now each edge of the triangle with the box for (iEdge = 0; iEdge < 3; ++iEdge) { #region "BEN-OPTIMISATION: Remove excess allocations and pass variables by reference." // ORIGINAL CODE: /*Vector3 pt0 = triangle.GetPoint(iEdge); * Vector3 pt1 = triangle.GetPoint((iEdge + 1) % 3); * Segment s1 = new Segment(pt0, pt1 - pt0); * Segment s2 = new Segment(pt1, pt0 - pt1);*/ // OPTIMISED CODE: Vector3 pt0 = triangle.GetPoint(iEdge); Vector3 pt1 = triangle.GetPoint((iEdge + 1) % 3); Vector3 difference1; Vector3 difference2; Vector3.Subtract(ref pt1, ref pt0, out difference1); Vector3.Subtract(ref pt0, ref pt1, out difference2); Segment s1 = new Segment(ref pt0, ref difference1); Segment s2 = new Segment(ref pt1, ref difference2); #endregion if (box.SegmentIntersect(out tS, out pos, out n, s1)) { AddPoint(pts, ref pos, combinationDistance * combinationDistance); } if (box.SegmentIntersect(out tS, out pos, out n, s2)) { AddPoint(pts, ref pos, combinationDistance * combinationDistance); } } return(pts.Count); }
public bool Equals(Triangle obj) { return(obj.A.Equals(A) && obj.B.Equals(B) && obj.C.Equals(C)); }
public TrigEnumerator(Triangle triangle) { this.t = triangle; }
/// <summary> /// Draws a triangle to the screen. /// </summary> /// <param name="vertexTriangle">The triangle to draw.</param> /// <param name="drawColour">The vertex colour.</param> /// <param name="textureRect">The texture rectangle.</param> /// <param name="vertexAction">An action that adds vertices to a <see cref="VertexBatch{T}"/>.</param> /// <param name="inflationPercentage">The percentage amount that <paramref name="textureRect"/> should be inflated.</param> internal abstract void DrawTriangle(Triangle vertexTriangle, ColourInfo drawColour, RectangleF?textureRect = null, Action <TexturedVertex2D> vertexAction = null, Vector2?inflationPercentage = null);
public Tuple <IEnumerable <Triangle>, IEnumerable <Triangle> > Split(Plane plane) { float[] distance = new float[] { plane.GetDistanceToPoint(this.V1), plane.GetDistanceToPoint(this.V2), plane.GetDistanceToPoint(this.V3) }; int onPlane = distance.Count(d => Mathf.Abs(d) <= smallDistance); int abovePlane = distance.Count(d => Mathf.Abs(d) > smallDistance && d > 0); int belowPlane = distance.Count(d => Mathf.Abs(d) > smallDistance && d < 0); if (belowPlane == 0) { return(new Tuple <IEnumerable <Triangle>, IEnumerable <Triangle> >(this.Yield(), Enumerable.Empty <Triangle>())); } if (abovePlane == 0) { return(new Tuple <IEnumerable <Triangle>, IEnumerable <Triangle> >(Enumerable.Empty <Triangle>(), this.Yield())); } if (onPlane == 0) { var single = abovePlane == 1 ? this.ToEnumerable().First(v => plane.GetDistanceToPoint(v) > 0) : this.ToEnumerable().First(v => plane.GetDistanceToPoint(v) < 0); var double1 = abovePlane == 1 ? this.ToEnumerable().First(v => plane.GetDistanceToPoint(v) < 0) : this.ToEnumerable().First(v => plane.GetDistanceToPoint(v) > 0); var double2 = abovePlane == 1 ? this.ToEnumerable().Where(v => plane.GetDistanceToPoint(v) < 0).Skip(1).First() : this.ToEnumerable().Where(v => plane.GetDistanceToPoint(v) > 0).Skip(1).First(); var intersect1 = Math3d.LinePlaneIntersection(plane, single, double1); var intersect2 = Math3d.LinePlaneIntersection(plane, single, double2); if (abovePlane == 1) { return(new Tuple <IEnumerable <Triangle>, IEnumerable <Triangle> >( Triangle.TryCreateEnum(single, intersect1, intersect2), Triangle.TryCreateEnum(double1, double2, intersect1) .Concat(Triangle.TryCreateEnum(double2, intersect1, intersect2)))); } else { return(new Tuple <IEnumerable <Triangle>, IEnumerable <Triangle> >( Triangle.TryCreateEnum(double1, double2, intersect1) .Concat(Triangle.TryCreateEnum(double2, intersect1, intersect2)), Triangle.TryCreateEnum(single, intersect1, intersect2))); } } if (onPlane == 1) { var vertexOn = this.ToEnumerable().First(v => Mathf.Abs(plane.GetDistanceToPoint(v)) <= smallDistance); var vertexBelow = this.ToEnumerable().First(v => plane.GetDistanceToPoint(v) < 0 && Mathf.Abs(plane.GetDistanceToPoint(v)) > smallDistance); var vertexAbove = this.ToEnumerable().First(v => plane.GetDistanceToPoint(v) > 0 && Mathf.Abs(plane.GetDistanceToPoint(v)) > smallDistance); var ray = new Ray(vertexAbove, vertexBelow - vertexAbove); float dst; plane.Raycast(ray, out dst); var intersect = ray.GetPoint(dst); return(new Tuple <IEnumerable <Triangle>, IEnumerable <Triangle> >(Triangle.TryCreateEnum(vertexBelow, vertexOn, intersect), Triangle.TryCreateEnum(vertexAbove, vertexOn, intersect))); } return(new Tuple <IEnumerable <Triangle>, IEnumerable <Triangle> >(Enumerable.Empty <Triangle>(), Enumerable.Empty <Triangle>())); }
/// <summary> /// Find the holes and infect them. Find the area constraints and infect /// them. Infect the convex hull. Spread the infection and kill triangles. /// Spread the area constraints. /// </summary> public void CarveHoles() { Otri searchtri = default(Otri); Vertex searchorg, searchdest; LocateResult intersect; Triangle[] regionTris = null; if (!mesh.behavior.Convex) { // Mark as infected any unprotected triangles on the boundary. // This is one way by which concavities are created. InfectHull(); } if (!mesh.behavior.NoHoles) { // Infect each triangle in which a hole lies. foreach (var hole in mesh.holes) { // Ignore holes that aren't within the bounds of the mesh. if (mesh.bounds.Contains(hole)) { // Start searching from some triangle on the outer boundary. searchtri.triangle = Mesh.dummytri; searchtri.orient = 0; searchtri.SymSelf(); // Ensure that the hole is to the left of this boundary edge; // otherwise, locate() will falsely report that the hole // falls within the starting triangle. searchorg = searchtri.Org(); searchdest = searchtri.Dest(); if (Primitives.CounterClockwise(searchorg, searchdest, hole) > 0.0) { // Find a triangle that contains the hole. intersect = mesh.locator.Locate(hole, ref searchtri); if ((intersect != LocateResult.Outside) && (!searchtri.IsInfected())) { // Infect the triangle. This is done by marking the triangle // as infected and including the triangle in the virus pool. searchtri.Infect(); viri.Add(searchtri.triangle); } } } } } // Now, we have to find all the regions BEFORE we carve the holes, because locate() won't // work when the triangulation is no longer convex. (Incidentally, this is the reason why // regional attributes and area constraints can't be used when refining a preexisting mesh, // which might not be convex; they can only be used with a freshly triangulated PSLG.) if (mesh.regions.Count > 0) { int i = 0; regionTris = new Triangle[mesh.regions.Count]; // Find the starting triangle for each region. foreach (var region in mesh.regions) { regionTris[i] = Mesh.dummytri; // Ignore region points that aren't within the bounds of the mesh. if (mesh.bounds.Contains(region.point)) { // Start searching from some triangle on the outer boundary. searchtri.triangle = Mesh.dummytri; searchtri.orient = 0; searchtri.SymSelf(); // Ensure that the region point is to the left of this boundary // edge; otherwise, locate() will falsely report that the // region point falls within the starting triangle. searchorg = searchtri.Org(); searchdest = searchtri.Dest(); if (Primitives.CounterClockwise(searchorg, searchdest, region.point) > 0.0) { // Find a triangle that contains the region point. intersect = mesh.locator.Locate(region.point, ref searchtri); if ((intersect != LocateResult.Outside) && (!searchtri.IsInfected())) { // Record the triangle for processing after the // holes have been carved. regionTris[i] = searchtri.triangle; regionTris[i].region = region.id; } } } i++; } } if (viri.Count > 0) { // Carve the holes and concavities. Plague(); } if (regionTris != null) { var iterator = new RegionIterator(mesh); for (int i = 0; i < regionTris.Length; i++) { if (regionTris[i] != Mesh.dummytri) { // Make sure the triangle under consideration still exists. // It may have been eaten by the virus. if (!Otri.IsDead(regionTris[i])) { // Apply one region's attribute and/or area constraint. iterator.Process(regionTris[i]); } } } } // Free up memory (virus pool should be empty anyway). viri.Clear(); }
/// <summary> /// Set the region attribute of all trianlges connected to given triangle. /// </summary> public void Process(Triangle triangle) { // Default action is to just set the region id for all trianlges. this.Process(triangle, (tri) => { tri.region = triangle.region; }); }
internal static void CollDetectSphereStaticMeshSweep(BoundingSphere oldSphere, BoundingSphere newSphere, TriangleMesh mesh, CollDetectInfo info, float collTolerance, CollisionFunctor collisionFunctor) { // really use a swept test - or overlap? Vector3 delta = newSphere.Center - oldSphere.Center; if (delta.LengthSquared() < (0.25f * newSphere.Radius * newSphere.Radius)) { CollDetectSphereStaticMeshOverlap(oldSphere, newSphere, mesh, info, collTolerance, collisionFunctor); } else { Vector3 body0Pos = (info.Skin0.Owner != null) ? info.Skin0.Owner.OldPosition : Vector3.Zero; Vector3 body1Pos = (info.Skin1.Owner != null) ? info.Skin1.Owner.OldPosition : Vector3.Zero; float sphereTolR = collTolerance + oldSphere.Radius; float sphereToR2 = sphereTolR * sphereTolR; Vector3 collNormal = Vector3.Zero; BoundingBox bb = BoundingBoxHelper.InitialBox; BoundingBoxHelper.AddSphere(oldSphere, ref bb); BoundingBoxHelper.AddSphere(newSphere, ref bb); // get the spheres centers in triangle mesh space Vector3 newSphereCen = Vector3.Transform(newSphere.Center, mesh.InverseTransformMatrix); Vector3 oldSphereCen = Vector3.Transform(oldSphere.Center, mesh.InverseTransformMatrix); unsafe { #if USE_STACKALLOC SmallCollPointInfo *collPts = stackalloc SmallCollPointInfo[MaxLocalStackSCPI]; int *potentialTriangles = stackalloc int[MaxLocalStackTris]; { { #else SmallCollPointInfo[] collPtArray = SCPIStackAlloc(); fixed(SmallCollPointInfo *collPts = collPtArray) { int[] potTriArray = IntStackAlloc(); fixed(int *potentialTriangles = potTriArray) { #endif int numCollPts = 0; int numTriangles = mesh.GetTrianglesIntersectingtAABox(potentialTriangles, MaxLocalStackTris, ref bb); for (int iTriangle = 0; iTriangle < numTriangles; ++iTriangle) { // first test the old sphere for being on the wrong side IndexedTriangle meshTriangle = mesh.GetTriangle(potentialTriangles[iTriangle]); float distToCentreOld = meshTriangle.Plane.DotCoordinate(oldSphereCen); if (distToCentreOld <= 0.0f) { continue; } // now test the new sphere for being clear float distToCentreNew = meshTriangle.Plane.DotCoordinate(newSphereCen); if (distToCentreNew > sphereTolR) { continue; } int i0, i1, i2; meshTriangle.GetVertexIndices(out i0, out i1, out i2); Triangle triangle = new Triangle(mesh.GetVertex(i0), mesh.GetVertex(i1), mesh.GetVertex(i2)); // If the old sphere is intersecting, just use that result float s, t; float d2 = Distance.PointTriangleDistanceSq(out s, out t, oldSphereCen, triangle); if (d2 < sphereToR2) { float dist = (float)System.Math.Sqrt(d2); float depth = oldSphere.Radius - dist; Vector3 triangleN = triangle.Normal; Vector3 normSafe = oldSphereCen - triangle.GetPoint(s, t); JiggleMath.NormalizeSafe(ref normSafe); Vector3 collisionN = (dist > float.Epsilon) ? normSafe : triangleN; // since impulse gets applied at the old position Vector3 pt = oldSphere.Center - oldSphere.Radius * collisionN; if (numCollPts < MaxLocalStackSCPI) { collPts[numCollPts++] = new SmallCollPointInfo(pt - body0Pos, pt - body1Pos, depth); } collNormal += collisionN; } else if (distToCentreNew < distToCentreOld) { // old sphere is not intersecting - do a sweep, but only if the sphere is moving into the // triangle Vector3 pt, N; // CHECK THIS float depth; if (Intersection.SweptSphereTriangleIntersection(out pt, out N, out depth, oldSphere, newSphere, triangle, distToCentreOld, distToCentreNew, Intersection.EdgesToTest.EdgeAll, Intersection.CornersToTest.CornerAll)) { // collision point etc must be relative to the old position because that's //where the impulses are applied float dist = (float)System.Math.Sqrt(d2); float depth2 = oldSphere.Radius - dist; Vector3 triangleN = triangle.Normal; Vector3 normSafe = oldSphereCen - triangle.GetPoint(s, t); JiggleMath.NormalizeSafe(ref normSafe); Vector3 collisionN = (dist > JiggleMath.Epsilon) ? normSafe : triangleN; // since impulse gets applied at the old position Vector3 pt2 = oldSphere.Center - oldSphere.Radius * collisionN; if (numCollPts < MaxLocalStackSCPI) { collPts[numCollPts++] = new SmallCollPointInfo(pt2 - body0Pos, pt2 - body1Pos, depth); } collNormal += collisionN; } } } if (numCollPts > 0) { JiggleMath.NormalizeSafe(ref collNormal); collisionFunctor.CollisionNotify(ref info, ref collNormal, collPts, numCollPts); } } #if USE_STACKALLOC } } #else FreeStackAlloc(potTriArray); } FreeStackAlloc(collPtArray); } #endif } }
private static bool IsOverlapping(Rectangle rectangle, Triangle triangle) { // Do specialised geometry return(true); }
public T Visit(Triangle triangle) => _ifTriangle(triangle);
public void Triangle_NotExists_Negative() { Triangle triangle = new Triangle(10, 10, 0); var result = _validator.Validate(triangle); }
public void CreateBadValueTriangleTest() { Triangle triangle = new Triangle(new Point(1, 1), new Point(1, 1), new Point(1, 1)); }
public void Triangle_Nigative_All_Parameter_Exception() { Triangle triangle = new Triangle(-1, -10, -2); _validator.Validate(triangle); }
void Update() { if (Input.GetKeyDown(KeyCode.R)) { t = new Triangle(UR.insideUnitSphere, UR.insideUnitSphere, UR.insideUnitSphere); s = new Segment(new Vector3(-1, 0, 0), new Vector3(1, 0, 0)); } }
public void TestTriangleCheckSquarenessFalse() { Triangle triangle = new Triangle(5, 3, 3); Assert.AreEqual(false, triangle.CheckSquareness()); }
public void Triangle_NotExist_Zero_All_Parameters() { Triangle triangle = new Triangle(0, 0, 0); var result = _validator.Validate(triangle); }
public void TestTriangleСalculatingArea() { Triangle triangle = new Triangle(5, 4, 3); Assert.AreEqual(6, triangle.GetArea()); }
/// <summary> /// Cuts a hole into a shape. /// </summary> /// <param name="shapeVerts">An array of vertices for the primary shape.</param> /// <param name="holeVerts">An array of vertices for the hole to be cut. It is assumed that these vertices lie completely within the shape verts.</param> /// <returns>The new array of vertices that can be passed to Triangulate to properly triangulate the shape with the hole.</returns> public static Vector2[] CutHoleInShape(Vector2[] shapeVerts, Vector2[] holeVerts) { Log("\nCutting hole into shape..."); //make sure the shape vertices are wound counter clockwise and the hole vertices clockwise shapeVerts = EnsureWindingOrder(shapeVerts, WindingOrder.CounterClockwise); holeVerts = EnsureWindingOrder(holeVerts, WindingOrder.Clockwise); //clear all of the lists polygonVertices.Clear(); earVertices.Clear(); convexVertices.Clear(); reflexVertices.Clear(); //generate the cyclical list of vertices in the polygon for (int i = 0; i < shapeVerts.Length; i++) { polygonVertices.AddLast(new Vertex(shapeVerts[i], (ushort)i)); } CyclicalList <Vertex> holePolygon = new CyclicalList <Vertex>(); for (int i = 0; i < holeVerts.Length; i++) { holePolygon.Add(new Vertex(holeVerts[i], (ushort)(i + polygonVertices.Count))); } #if DEBUG StringBuilder vString = new StringBuilder(); foreach (Vertex v in polygonVertices) { vString.Append(string.Format("{0}, ", v)); } Log("Shape Vertices: {0}", vString); vString = new StringBuilder(); foreach (Vertex v in holePolygon) { vString.Append(string.Format("{0}, ", v)); } Log("Hole Vertices: {0}", vString); #endif FindConvexAndReflexVertices(); FindEarVertices(); //find the hole vertex with the largest X value Vertex rightMostHoleVertex = holePolygon[0]; foreach (Vertex v in holePolygon) { if (v.Position.X > rightMostHoleVertex.Position.X) { rightMostHoleVertex = v; } } //construct a list of all line segments where at least one vertex //is to the right of the rightmost hole vertex with one vertex //above the hole vertex and one below List <LineSegment> segmentsToTest = new List <LineSegment>(); for (int i = 0; i < polygonVertices.Count; i++) { Vertex a = polygonVertices[i].Value; Vertex b = polygonVertices[i + 1].Value; if ((a.Position.X > rightMostHoleVertex.Position.X || b.Position.X > rightMostHoleVertex.Position.X) && ((a.Position.Y >= rightMostHoleVertex.Position.Y && b.Position.Y <= rightMostHoleVertex.Position.Y) || (a.Position.Y <= rightMostHoleVertex.Position.Y && b.Position.Y >= rightMostHoleVertex.Position.Y))) { segmentsToTest.Add(new LineSegment(a, b)); } } //now we try to find the closest intersection point heading to the right from //our hole vertex. float? closestPoint = null; LineSegment closestSegment = new LineSegment(); foreach (LineSegment segment in segmentsToTest) { float?intersection = segment.IntersectsWithRay(rightMostHoleVertex.Position, Vector2.UnitX); if (intersection != null) { if (closestPoint == null || closestPoint.Value > intersection.Value) { closestPoint = intersection; closestSegment = segment; } } } //if closestPoint is null, there were no collisions (likely from improper input data), //but we'll just return without doing anything else if (closestPoint == null) { return(shapeVerts); } //otherwise we can find our mutually visible vertex to split the polygon Vector2 I = rightMostHoleVertex.Position + Vector2.UnitX * closestPoint.Value; Vertex P = (closestSegment.A.Position.X > closestSegment.B.Position.X) ? closestSegment.A : closestSegment.B; //construct triangle MIP Triangle mip = new Triangle(rightMostHoleVertex, new Vertex(I, 1), P); //see if any of the reflex vertices lie inside of the MIP triangle List <Vertex> interiorReflexVertices = new List <Vertex>(); foreach (Vertex v in reflexVertices) { if (mip.ContainsPoint(v)) { interiorReflexVertices.Add(v); } } //if there are any interior reflex vertices, find the one that, when connected //to our rightMostHoleVertex, forms the line closest to Vector2.UnitX if (interiorReflexVertices.Count > 0) { float closestDot = -1f; foreach (Vertex v in interiorReflexVertices) { //compute the dot product of the vector against the UnitX Vector2 d = Vector2.Normalize(v.Position - rightMostHoleVertex.Position); float dot = Vector2.Dot(Vector2.UnitX, d); //if this line is the closest we've found if (dot > closestDot) { //save the value and save the vertex as P closestDot = dot; P = v; } } } //now we just form our output array by injecting the hole vertices into place //we know we have to inject the hole into the main array after point P going from //rightMostHoleVertex around and then back to P. int mIndex = holePolygon.IndexOf(rightMostHoleVertex); int injectPoint = polygonVertices.IndexOf(P); Log("Inserting hole at injection point {0} starting at hole vertex {1}.", P, rightMostHoleVertex); for (int i = mIndex; i <= mIndex + holePolygon.Count; i++) { Log("Inserting vertex {0} after vertex {1}.", holePolygon[i], polygonVertices[injectPoint].Value); polygonVertices.AddAfter(polygonVertices[injectPoint++], holePolygon[i]); } polygonVertices.AddAfter(polygonVertices[injectPoint], P); #if DEBUG vString = new StringBuilder(); foreach (Vertex v in polygonVertices) { vString.Append(string.Format("{0}, ", v)); } Log("New Shape Vertices: {0}\n", vString); #endif //finally we write out the new polygon vertices and return them out Vector2[] newShapeVerts = new Vector2[polygonVertices.Count]; for (int i = 0; i < polygonVertices.Count; i++) { newShapeVerts[i] = polygonVertices[i].Value.Position; } return(newShapeVerts); }
public void TestTriangleWithWrongSides() { Triangle triangle = new Triangle(5, 4, 10); }
public void TestTriangleCheckSquarenessTrue() { Triangle triangle = new Triangle(5, 4, 3); Assert.AreEqual(true, triangle.CheckSquareness()); }
public void Triangle_CalculateArea_BadSides_InvalidOperationException() { var triangle = new Triangle(2, 2, 8); Assert.Throws <InvalidOperationException>(() => triangle.CalculateArea()); }
public void TestTriangleСalculatingPerimeter() { Triangle triangle = new Triangle(5, 4, 3); Assert.AreEqual(12, triangle.GetPerimeter()); }
/* Smarter implementation, based on the assumption that only contiguous triangles can contain * the point in their circumcircle. Main differences are 1) as we find the first "bad" triangle, * we just check the contiguous ones 2) we need to keep the triangles linked together */ private void ContiguousTriangulate() { // recursive function to check contiguous if contiguous triangles contain the new point in their circumcircle void checkEdges(HashSet <Triangle> _badTriangles, Vector2 point, Triangle triangle) { for (int edge = 0; edge < 3; edge++) { if (triangle.links[edge] != null && triangle.links[edge].isPointInsideCircumcircle(point) && !_badTriangles.Contains(triangle.links[edge])) { _badTriangles.Add(triangle.links[edge]); checkEdges(_badTriangles, point, triangle.links[edge]); } } } // find if triangle1 shares one edge with triangle2, and link them bool linkTriangles(Triangle triangle1, Triangle triangle2) { if (triangle1 != triangle2 && triangle1 != null && triangle2 != null) { for (int outer = 0; outer < 3; outer++) { for (int inner = 0; inner < 3; inner++) { if (triangle1.edges[outer].Compare(triangle2.edges[inner])) { triangle1.links[outer] = triangle2; return(true); } } } } return(false); } triangulation.Clear(); trianglePool.Clear(); superTriangle = trianglePool.Get(); superTriangle.Populate(new Vector2(-halfWidth * 2.5f * scalePlayground, -halfHeight * 2 * scalePlayground), new Vector2(halfWidth * 2.5f * scalePlayground, -halfHeight * 2 * scalePlayground), new Vector2(0.0f, halfHeight * 3 * scalePlayground)); triangulation.Add(superTriangle); List <Edge> polygon = new List <Edge>(); HashSet <Triangle> badTriangles = new HashSet <Triangle>(); HashSet <Triangle> outerTriangles = new HashSet <Triangle>(); HashSet <Triangle> partialTriangulation = new HashSet <Triangle>(); for (int i = 0; i < points.Count; i++) { Vector2 point = points[i].position; polygon.Clear(); badTriangles.Clear(); outerTriangles.Clear(); partialTriangulation.Clear(); foreach (Triangle triangle in triangulation) { if (triangle.isPointInsideCircumcircle(point)) { badTriangles.Add(triangle); checkEdges(badTriangles, point, triangle); break; } } foreach (Triangle badTriangle in badTriangles) { for (int edge = 0; edge < 3; edge++) { if (!badTriangles.Contains(badTriangle.links[edge])) { polygon.Add(badTriangle.edges[edge]); // save the link with outer triangles if (badTriangle.links[edge] != null && !badTriangles.Contains(badTriangle.links[edge])) { outerTriangles.Add(badTriangle.links[edge]); } } } } foreach (Triangle badTriangle in badTriangles) { trianglePool.Remove(badTriangle); triangulation.Remove(badTriangle); } // insert new triangles into a "partial" triangulation, allowing for linking for (int j = 0; j < polygon.Count; j++) { Triangle thisTriangle = trianglePool.Get(); thisTriangle.Populate(polygon[j].A, polygon[j].B, point); partialTriangulation.Add(thisTriangle); } foreach (Triangle partialTriangle in partialTriangulation) { // link with outer triangles foreach (Triangle outerTriangle in outerTriangles) { if (linkTriangles(partialTriangle, outerTriangle)) { linkTriangles(outerTriangle, partialTriangle); break; } } // link "partial" triangles with each other int maxTwoLinked = 0; foreach (Triangle otherPartialTriangle in partialTriangulation) { if (linkTriangles(partialTriangle, otherPartialTriangle)) { maxTwoLinked++; } if (maxTwoLinked == 2) { break; } } triangulation.Add(partialTriangle); } } }
public void TestTriangleWithNegativeSide() { Triangle triangle = new Triangle(5, 4, -2); }
/// <summary> /// DoOverlapBoxTriangleTest /// </summary> /// <param name="oldBox"></param> /// <param name="newBox"></param> /// <param name="triangle"></param> /// <param name="mesh"></param> /// <param name="info"></param> /// <param name="collTolerance"></param> /// <param name="collisionFunctor"></param> /// <returns>bool</returns> private static bool DoOverlapBoxTriangleTest(Box oldBox, Box newBox, ref IndexedTriangle triangle, TriangleMesh mesh, ref CollDetectInfo info, float collTolerance, CollisionFunctor collisionFunctor) { Matrix dirs0 = newBox.Orientation; #region REFERENCE: Triangle tri = new Triangle(mesh.GetVertex(triangle.GetVertexIndex(0)),mesh.GetVertex(triangle.GetVertexIndex(1)),mesh.GetVertex(triangle.GetVertexIndex(2))); Vector3 triVec0; Vector3 triVec1; Vector3 triVec2; mesh.GetVertex(triangle.GetVertexIndex(0), out triVec0); mesh.GetVertex(triangle.GetVertexIndex(1), out triVec1); mesh.GetVertex(triangle.GetVertexIndex(2), out triVec2); // Deano move tri into world space Matrix transformMatrix = mesh.TransformMatrix; Vector3.Transform(ref triVec0, ref transformMatrix, out triVec0); Vector3.Transform(ref triVec1, ref transformMatrix, out triVec1); Vector3.Transform(ref triVec2, ref transformMatrix, out triVec2); Triangle tri = new Triangle(ref triVec0, ref triVec1, ref triVec2); #endregion #region REFERENCE Vector3 triEdge0 = (tri.GetPoint(1) - tri.GetPoint(0)); Vector3 pt0; Vector3 pt1; tri.GetPoint(0, out pt0); tri.GetPoint(1, out pt1); Vector3 triEdge0; Vector3.Subtract(ref pt1, ref pt0, out triEdge0); #endregion #region REFERENCE Vector3 triEdge1 = (tri.GetPoint(2) - tri.GetPoint(1)); Vector3 pt2; tri.GetPoint(2, out pt2); Vector3 triEdge1; Vector3.Subtract(ref pt2, ref pt1, out triEdge1); #endregion #region REFERENCE Vector3 triEdge2 = (tri.GetPoint(0) - tri.GetPoint(2)); Vector3 triEdge2; Vector3.Subtract(ref pt0, ref pt2, out triEdge2); #endregion triEdge0.Normalize(); triEdge1.Normalize(); triEdge2.Normalize(); // BEN-OPTIMISATION: Replaced loops with code that requires no looping. // The new code is faster, has less allocations and math especially // since the method returns as soon as it finds a non-overlapping axis, // i.e. Before irreleveat allocations occur. #region "Old (less efficient) code" /*Vector3 triNormal = triangle.Plane.Normal; * * // the 15 potential separating axes * const int numAxes = 13; * Vector3[] axes = new Vector3[numAxes]; * * axes[0] = triNormal; * axes[1] = dirs0.Right; * axes[2] = dirs0.Up; * axes[3] = dirs0.Backward; * Vector3.Cross(ref axes[1], ref triEdge0, out axes[4]); * Vector3.Cross(ref axes[1], ref triEdge1, out axes[5]); * Vector3.Cross(ref axes[1], ref triEdge2, out axes[6]); * Vector3.Cross(ref axes[2], ref triEdge0, out axes[7]); * Vector3.Cross(ref axes[2], ref triEdge1, out axes[8]); * Vector3.Cross(ref axes[2], ref triEdge2, out axes[9]); * Vector3.Cross(ref axes[3], ref triEdge0, out axes[10]); * Vector3.Cross(ref axes[3], ref triEdge1, out axes[11]); * Vector3.Cross(ref axes[3], ref triEdge2, out axes[12]); * * // the overlap depths along each axis * float[] overlapDepths = new float[numAxes]; * * // see if the boxes are separate along any axis, and if not keep a * // record of the depths along each axis * int i; * for (i = 0; i < numAxes; ++i) * { * overlapDepths[i] = 1.0f; * if (Disjoint(out overlapDepths[i], axes[i], newBox, tri, collTolerance)) * return false; * } * * // The box overlap, find the separation depth closest to 0. * float minDepth = float.MaxValue; * int minAxis = -1; * * for (i = 0; i < numAxes; ++i) * { * // If we can't normalise the axis, skip it * float l2 = axes[i].LengthSquared(); * if (l2 < JiggleMath.Epsilon) * continue; * * // Normalise the separation axis and the depth * float invl = 1.0f / (float)System.Math.Sqrt(l2); * axes[i] *= invl; * overlapDepths[i] *= invl; * * // If this axis is the minimum, select it * if (overlapDepths[i] < minDepth) * { * minDepth = overlapDepths[i]; * minAxis = i; * } * } * * if (minAxis == -1) * return false; * * // Make sure the axis is facing towards the 0th box. * // if not, invert it * Vector3 D = newBox.GetCentre() - tri.Centre; * Vector3 N = axes[minAxis]; * float depth = overlapDepths[minAxis];*/ #endregion #region "Optimised code" Vector3 triNormal = triangle.Plane.Normal; Vector3 right = dirs0.Right; Vector3 up = dirs0.Up; Vector3 backward = dirs0.Backward; float testDepth; if (Disjoint(out testDepth, ref triNormal, newBox, ref tri, collTolerance)) { return(false); } float depth = testDepth; Vector3 N = triNormal; if (Disjoint(out testDepth, ref right, newBox, ref tri, collTolerance)) { return(false); } if (testDepth < depth) { depth = testDepth; N = right; } if (Disjoint(out testDepth, ref up, newBox, ref tri, collTolerance)) { return(false); } if (testDepth < depth) { depth = testDepth; N = up; } if (Disjoint(out testDepth, ref backward, newBox, ref tri, collTolerance)) { return(false); } if (testDepth < depth) { depth = testDepth; N = backward; } Vector3 axis; Vector3.Cross(ref right, ref triEdge0, out axis); if (Disjoint(out testDepth, ref axis, newBox, ref tri, collTolerance)) { return(false); } testDepth *= 1.0f / (float)System.Math.Sqrt(axis.X * axis.X + axis.Y * axis.Y + axis.Z * axis.Z); if (testDepth < depth) { depth = testDepth; N = axis; } Vector3.Cross(ref right, ref triEdge1, out axis); if (Disjoint(out testDepth, ref axis, newBox, ref tri, collTolerance)) { return(false); } testDepth *= 1.0f / (float)System.Math.Sqrt(axis.X * axis.X + axis.Y * axis.Y + axis.Z * axis.Z); if (testDepth < depth) { depth = testDepth; N = axis; } Vector3.Cross(ref right, ref triEdge2, out axis); if (Disjoint(out testDepth, ref axis, newBox, ref tri, collTolerance)) { return(false); } testDepth *= 1.0f / (float)System.Math.Sqrt(axis.X * axis.X + axis.Y * axis.Y + axis.Z * axis.Z); if (testDepth < depth) { depth = testDepth; N = axis; } Vector3.Cross(ref up, ref triEdge0, out axis); if (Disjoint(out testDepth, ref axis, newBox, ref tri, collTolerance)) { return(false); } testDepth *= 1.0f / (float)System.Math.Sqrt(axis.X * axis.X + axis.Y * axis.Y + axis.Z * axis.Z); if (testDepth < depth) { depth = testDepth; N = axis; } Vector3.Cross(ref up, ref triEdge1, out axis); if (Disjoint(out testDepth, ref axis, newBox, ref tri, collTolerance)) { return(false); } testDepth *= 1.0f / (float)System.Math.Sqrt(axis.X * axis.X + axis.Y * axis.Y + axis.Z * axis.Z); if (testDepth < depth) { depth = testDepth; N = axis; } Vector3.Cross(ref up, ref triEdge2, out axis); if (Disjoint(out testDepth, ref axis, newBox, ref tri, collTolerance)) { return(false); } testDepth *= 1.0f / (float)System.Math.Sqrt(axis.X * axis.X + axis.Y * axis.Y + axis.Z * axis.Z); if (testDepth < depth) { depth = testDepth; N = axis; } Vector3.Cross(ref backward, ref triEdge0, out axis); if (Disjoint(out testDepth, ref axis, newBox, ref tri, collTolerance)) { return(false); } testDepth *= 1.0f / (float)System.Math.Sqrt(axis.X * axis.X + axis.Y * axis.Y + axis.Z * axis.Z); if (testDepth < depth) { depth = testDepth; N = axis; } Vector3.Cross(ref backward, ref triEdge1, out axis); if (Disjoint(out testDepth, ref axis, newBox, ref tri, collTolerance)) { return(false); } testDepth *= 1.0f / (float)System.Math.Sqrt(axis.X * axis.X + axis.Y * axis.Y + axis.Z * axis.Z); if (testDepth < depth) { depth = testDepth; N = axis; } Vector3.Cross(ref backward, ref triEdge2, out axis); if (Disjoint(out testDepth, ref axis, newBox, ref tri, collTolerance)) { return(false); } testDepth *= 1.0f / (float)System.Math.Sqrt(axis.X * axis.X + axis.Y * axis.Y + axis.Z * axis.Z); if (testDepth < depth) { depth = testDepth; N = axis; } /*if (N == Vector3.Zero) * return (false);*/ Vector3 D = newBox.GetCentre() - tri.Centre; N.Normalize(); int i; #endregion if (Vector3.Dot(D, N) < 0.0f) { N *= -1; } Vector3 boxOldPos = (info.Skin0.Owner != null) ? info.Skin0.Owner.OldPosition : Vector3.Zero; Vector3 boxNewPos = (info.Skin0.Owner != null) ? info.Skin0.Owner.Position : Vector3.Zero; Vector3 meshPos = (info.Skin1.Owner != null) ? info.Skin1.Owner.OldPosition : Vector3.Zero; List <Vector3> pts = new List <Vector3>(); //pts.Clear(); const float combinationDist = 0.05f; GetBoxTriangleIntersectionPoints(pts, newBox, tri, depth + combinationDist); // adjust the depth #region REFERENCE: Vector3 delta = boxNewPos - boxOldPos; Vector3 delta; Vector3.Subtract(ref boxNewPos, ref boxOldPos, out delta); #endregion #region REFERENCE: float oldDepth = depth + Vector3.Dot(delta, N); float oldDepth; Vector3.Dot(ref delta, ref N, out oldDepth); oldDepth += depth; #endregion unsafe { // report collisions int numPts = pts.Count; #if USE_STACKALLOC SmallCollPointInfo *collPts = stackalloc SmallCollPointInfo[MaxLocalStackSCPI]; #else SmallCollPointInfo[] collPtArray = SCPIStackAlloc(); fixed(SmallCollPointInfo *collPts = collPtArray) #endif { if (numPts > 0) { if (numPts >= MaxLocalStackSCPI) { numPts = MaxLocalStackSCPI - 1; } // adjust positions for (i = 0; i < numPts; ++i) { // BEN-OPTIMISATION: Reused existing SmallCollPointInfo and inlined vector substraction. collPts[i].R0.X = pts[i].X - boxNewPos.X; collPts[i].R0.Y = pts[i].Y - boxNewPos.Y; collPts[i].R0.Z = pts[i].Z - boxNewPos.Z; collPts[i].R1.X = pts[i].X - meshPos.X; collPts[i].R1.Y = pts[i].Y - meshPos.Y; collPts[i].R1.Z = pts[i].Z - meshPos.Z; collPts[i].InitialPenetration = oldDepth; } collisionFunctor.CollisionNotify(ref info, ref N, collPts, numPts); #if !USE_STACKALLOC FreeStackAlloc(collPtArray); #endif return(true); } else { #if !USE_STACKALLOC FreeStackAlloc(collPtArray); #endif return(false); } } } }
public void Triangle_CalculateArea_NegativeSide_ArgumentOutOfRangeException() { var triangle = new Triangle(-1, 4, 6); Assert.Throws <ArgumentOutOfRangeException>(() => triangle.CalculateArea()); }
public void MakeMesh() { IEnumerator <Triangle> triangleEnumerator = mesh.Triangles.GetEnumerator(); for (int chunkStart = 0; chunkStart < mesh.Triangles.Count; chunkStart += trianglesInChunk) { List <Vector3> vertices = new List <Vector3>(); List <Vector3> normals = new List <Vector3>(); List <Vector2> uvs = new List <Vector2>(); List <int> triangles = new List <int>(); int chunkEnd = chunkStart + trianglesInChunk; for (int i = chunkStart; i < chunkEnd; i++) { if (!triangleEnumerator.MoveNext()) { break; } Triangle triangle = triangleEnumerator.Current; // For the triangles to be right-side up, they need // to be wound in the opposite direction Vector3 v0 = GetPoint3D(triangle.vertices[2].id); Vector3 v1 = GetPoint3D(triangle.vertices[1].id); Vector3 v2 = GetPoint3D(triangle.vertices[0].id); triangles.Add(vertices.Count); triangles.Add(vertices.Count + 1); triangles.Add(vertices.Count + 2); vertices.Add(v0); vertices.Add(v1); vertices.Add(v2); Vector3 normal = Vector3.Cross(v1 - v0, v2 - v0); normals.Add(normal); normals.Add(normal); normals.Add(normal); uvs.Add(new Vector2(0.0f, 0.0f)); uvs.Add(new Vector2(0.0f, 0.0f)); uvs.Add(new Vector2(0.0f, 0.0f)); } Mesh chunkMesh = new Mesh(); chunkMesh.vertices = vertices.ToArray(); chunkMesh.uv = uvs.ToArray(); chunkMesh.triangles = triangles.ToArray(); chunkMesh.normals = normals.ToArray(); Transform chunk = Instantiate <Transform>(chunkPrefab, transform.position, transform.rotation); chunk.GetComponent <MeshFilter>().mesh = chunkMesh; chunk.GetComponent <MeshCollider>().sharedMesh = chunkMesh; chunk.transform.parent = transform; foreach (MatLayer l in materials) { if (l.Assign(vertices)) { chunk.GetComponent <MeshRenderer>().material = l.material; } } } }
/* loop through each point to add, brute force search through each triangle, if * the point is contained in the triangle's circumcircle remove it. Create a polygon with * each removed triangle's outer edge, and add the triangles made by linking each edge to * the new point */ private void Triangulate() { triangulation.Clear(); trianglePool.Clear(); // first triangle, containing the whole playground superTriangle = trianglePool.Get(); superTriangle.Populate(new Vector2(-halfWidth * 2.5f * scalePlayground, -halfHeight * 2 * scalePlayground), new Vector2(halfWidth * 2.5f * scalePlayground, -halfHeight * 2 * scalePlayground), new Vector2(0.0f, halfHeight * 3 * scalePlayground)); triangulation.Add(superTriangle); List <Triangle> badTriangles = new List <Triangle>(); List <Edge> polygon = new List <Edge>(); for (int i = 0; i < points.Count; i++) { Vector2 point = points[i].position; badTriangles.Clear(); polygon.Clear(); // check if the triangle contains point in its circumcircle foreach (Triangle triangle in triangulation) { if (triangle.isPointInsideCircumcircle(point)) { badTriangles.Add(triangle); } } // create the outer polygon for (int outer = 0; outer < badTriangles.Count; outer++) { for (int edge = 0; edge < 3; edge++) { bool isShared = false; for (int inner = 0; inner < badTriangles.Count; inner++) { if (inner != outer && !isShared) { for (int badEdge = 0; badEdge < 3; badEdge++) { if (badTriangles[outer].edges[edge].Compare(badTriangles[inner].edges[badEdge])) { isShared = true; } } } } if (!isShared) { polygon.Add(badTriangles[outer].edges[edge]); } } } // remove bad triangles for (int j = 0; j < badTriangles.Count; j++) { trianglePool.Remove(badTriangles[j]); triangulation.Remove(badTriangles[j]); } // create new triangles for (int j = 0; j < polygon.Count; j++) { Triangle thisTriangle = trianglePool.Get(); thisTriangle.Populate(polygon[j].A, polygon[j].B, point); triangulation.Add(thisTriangle); } } }