private void OnDrawGizmos() { Triangle2 triangle0 = CreateTriangle2(V0, V1, V2); Triangle2 triangle1 = CreateTriangle2(P0, P1, P2); bool test = Intersection.TestTriangle2Triangle2(ref triangle0, ref triangle1); Triangle2Triangle2Intr info; bool find = Intersection.FindTriangle2Triangle2(ref triangle0, ref triangle1, out info); FiguresColor(); DrawTriangle(ref triangle0); DrawTriangle(ref triangle1); if (find) { ResultsColor(); for (int i = 0; i < info.Quantity; ++i) { Vector2 p = info[i]; DrawSegment(p, info[(i + 1) % info.Quantity]); DrawPoint(p); } } LogInfo(info.IntersectionType + " " + info.Quantity); if (test != find) { LogError("test != find"); } }
private void OnDrawGizmos() { Vector2 v0 = V0.position; Vector2 v1 = V1.position; Vector2 v2 = V2.position; Triangle2 triangle = CreateTriangle2(V0, V1, V2); Circle2 circumscribed; bool b0 = Circle2.CreateCircumscribed(v0, v1, v2, out circumscribed); Circle2 inscribed; bool b1 = Circle2.CreateInscribed(v0, v1, v2, out inscribed); FiguresColor(); DrawTriangle(ref triangle); ResultsColor(); if (b0) { DrawCircle(ref circumscribed); } if (b1) { DrawCircle(ref inscribed); } LogInfo("Circumscribed: " + b0 + " Inscribed: " + b1); }
private void OnDrawGizmos() { if (triangulatedMesh != null) { //Display the triangles with a random color TestAlgorithmsHelpMethods.DisplayMeshWithRandomColors(triangulatedMesh, seed); //Display the points TestAlgorithmsHelpMethods.DisplayPoints(points, 0.1f, Color.black); //Display the points on the hull if (pointsOnHull != null && pointsOnHull.Count > 0) { HashSet <Vector3> pointsOnHull_3d = new HashSet <Vector3>(); foreach (MyVector2 p in pointsOnHull) { pointsOnHull_3d.Add(p.ToVector3()); } TestAlgorithmsHelpMethods.DisplayPoints(pointsOnHull_3d, 0.3f, Color.black); } } if (testTriangles != null) { List <Triangle2> test = new List <Triangle2>(testTriangles); testTriangleNumber = Mathf.Clamp(testTriangleNumber, 0, testTriangles.Count - 1); Triangle2 t = test[testTriangleNumber]; TestAlgorithmsHelpMethods.DisplayTriangle(t.p1.ToVector3(), t.p2.ToVector3(), t.p3.ToVector3(), Color.white); } }
//Is a triangle oriented clockwise private void IsTriangleOrientedClockwise(MyVector2 a, MyVector2 b, MyVector2 c) { Triangle2 t = new Triangle2(a, b, c); bool isOrientedClockwise = _Geometry.IsTriangleOrientedClockwise(t.p1, t.p2, t.p3); Debug.Log("Is oriented clockwise: " + isOrientedClockwise); //We can also test if changing orientation is working t.ChangeOrientation(); bool isOrientedClockwiseAfterRotation = _Geometry.IsTriangleOrientedClockwise(t.p1, t.p2, t.p3); Debug.Log("Is oriented clockwise after changing orientation: " + isOrientedClockwiseAfterRotation); //Display the triangle Gizmos.color = Color.white; Gizmos.DrawLine(a.ToVector3(), b.ToVector3()); Gizmos.DrawLine(b.ToVector3(), c.ToVector3()); Gizmos.DrawLine(c.ToVector3(), a.ToVector3()); //Arrows showing the direction of the triangle float arrowSize = 0.1f; TestAlgorithmsHelpMethods.DisplayArrow(a.ToVector3(), b.ToVector3(), arrowSize, Color.white); TestAlgorithmsHelpMethods.DisplayArrow(b.ToVector3(), c.ToVector3(), arrowSize, Color.white); TestAlgorithmsHelpMethods.DisplayArrow(c.ToVector3(), a.ToVector3(), arrowSize, Color.white); }
//Generate the mesh from the half-edge data structure, which is called when we have flipped an edge public void GenerateMesh(HalfEdgeData2 triangleData_normalized) { //From half-edge to triangle while unnormalizing HashSet <Triangle2> triangles_2d = new HashSet <Triangle2>(); foreach (HalfEdgeFace2 f in triangleData_normalized.faces) { //Each face has in this case three edges MyVector2 p1 = f.edge.v.position; MyVector2 p2 = f.edge.nextEdge.v.position; MyVector2 p3 = f.edge.nextEdge.nextEdge.v.position; //Unnormalize the point p1 = HelpMethods.UnNormalize(p1, normalizingBox, dMax); p2 = HelpMethods.UnNormalize(p2, normalizingBox, dMax); p3 = HelpMethods.UnNormalize(p3, normalizingBox, dMax); Triangle2 t = new Triangle2(p1, p2, p3); triangles_2d.Add(t); } //Make sure the triangles have the correct orientation //triangles_2d = HelpMethods.OrientTrianglesClockwise(triangles_2d); //From 2d to mesh in one step //Mesh displayMesh = _TransformBetweenDataStructures.Triangles2ToMesh(triangles_2d, useCompressedMesh: false); //Generate the triangle meshes GenerateTriangleMeshes(triangles_2d); }
//Is a point intersecting with a triangle? private void PointTriangle() { MyVector2 p = pointTrans.position.ToMyVector2(); MyVector2 t_p1 = t1_p1_trans.position.ToMyVector2(); MyVector2 t_p2 = t1_p2_trans.position.ToMyVector2(); MyVector2 t_p3 = t1_p3_trans.position.ToMyVector2(); Triangle2 t = new Triangle2(t_p1, t_p2, t_p3); bool isIntersecting = _Intersections.PointTriangle(t, p, includeBorder: true); //Display //Gizmos.color = isIntersecting ? Color.red : Color.white; //Gizmos.DrawWireSphere(p.ToVector3(), 0.1f); //Gizmos.DrawLine(t.p1.ToVector3(), t.p2.ToVector3()); //Gizmos.DrawLine(t.p2.ToVector3(), t.p3.ToVector3()); //Gizmos.DrawLine(t.p3.ToVector3(), t.p1.ToVector3()); //With mesh to better see what's going on //Triangle TestAlgorithmsHelpMethods.DisplayTriangleMesh(t_p1, t_p2, t_p3, Color.white); //Point Color pointColor = isIntersecting ? Color.red : Color.white; TestAlgorithmsHelpMethods.DisplayCircleMesh(p, 1f, 20, pointColor); }
//Is a triangle intersecting with a triangle? private void TriangleTriangle() { //3d to 2d Triangle2 t1 = new Triangle2( t1_p1_trans.transform.position.ToMyVector2(), t1_p2_trans.transform.position.ToMyVector2(), t1_p3_trans.transform.position.ToMyVector2()); Triangle2 t2 = new Triangle2( t2_p1_trans.transform.position.ToMyVector2(), t2_p2_trans.transform.position.ToMyVector2(), t2_p3_trans.transform.position.ToMyVector2()); bool isIntersecting = _Intersections.TriangleTriangle2D(t1, t2, do_AABB_test: false); //Display //Color color = isIntersecting ? Color.red : Color.white; //TestAlgorithmsHelpMethods.DisplayTriangle(t1.p1.ToVector3(), t1.p2.ToVector3(), t1.p3.ToVector3(), color); //TestAlgorithmsHelpMethods.DisplayTriangle(t2.p1.ToVector3(), t2.p2.ToVector3(), t2.p3.ToVector3(), color); //With mesh to better see what's going on TestAlgorithmsHelpMethods.DisplayTriangleMesh(t1.p1, t1.p2, t1.p3, Color.white); Color meshColor = isIntersecting ? Color.red : Color.white; TestAlgorithmsHelpMethods.DisplayTriangleMesh(t2.p1, t2.p2, t2.p3, meshColor); }
public Triangle2Ex(ref Vector2 v0, ref Vector2 v1, ref Vector2 v2) { baseTriangle = new Triangle2(ref v0, ref v1, ref v2); #if EX_GIZMO_ON InitGizmoParam(); #endif }
public Triangle2Ex(Vector2 v0, Vector2 v1, Vector2 v2) { baseTriangle = new Triangle2(v0, v1, v2); #if EX_GIZMO_ON InitGizmoParam(); #endif }
public Triangle2 Reflect(Triangle2 triangle) { if (!this.valid) { return(triangle); } return(new Triangle2(Reflect(triangle.A), Reflect(triangle.B), Reflect(triangle.C))); }
// // Arrow // public static HashSet <Triangle2> Arrow(MyVector2 p1, MyVector2 p2, float lineWidth, float arrowSize) { HashSet <Triangle2> arrowTriangles = new HashSet <Triangle2>(); //An arrow consists of two parts: the pointy part and the rectangular part //First we have to see if we can fit the parts MyVector2 lineDir = p2 - p1; float lineLength = MyVector2.Magnitude(lineDir); if (lineLength < arrowSize) { Debug.Log("Cant make arrow because line is too short"); return(null); } //Make the arrow tip MyVector2 lineDirNormalized = MyVector2.Normalize(lineDir); MyVector2 arrowBottom = p2 - lineDirNormalized * arrowSize; MyVector2 lineNormal = MyVector2.Normalize(new MyVector2(lineDirNormalized.y, -lineDirNormalized.x)); MyVector2 arrowBottom_R = arrowBottom + lineNormal * arrowSize * 0.5f; MyVector2 arrowBottom_L = arrowBottom - lineNormal * arrowSize * 0.5f; Triangle2 arrowTipTriangle = new Triangle2(p2, arrowBottom_R, arrowBottom_L); arrowTriangles.Add(arrowTipTriangle); //Make the arrow rectangle float halfWidth = lineWidth * 0.5f; MyVector2 p1_T = p1 + lineNormal * halfWidth; MyVector2 p1_B = p1 - lineNormal * halfWidth; MyVector2 p2_T = arrowBottom + lineNormal * halfWidth; MyVector2 p2_B = arrowBottom - lineNormal * halfWidth; HashSet <Triangle2> rectangle = LineSegment(p1_T, p1_B, p2_T, p2_B); foreach (Triangle2 t in rectangle) { arrowTriangles.Add(t); } return(arrowTriangles); }
//Generate two triangles if we know the corners of the rectangle public static HashSet <Triangle2> LineSegment(MyVector2 p1_T, MyVector2 p1_B, MyVector2 p2_T, MyVector2 p2_B) { HashSet <Triangle2> lineTriangles = new HashSet <Triangle2>(); //Create the triangles Triangle2 t1 = new Triangle2(p1_T, p1_B, p2_T); Triangle2 t2 = new Triangle2(p1_B, p2_B, p2_T); lineTriangles.Add(t1); lineTriangles.Add(t2); return(lineTriangles); }
//Generate list of meshes from the Triangle2 data structure public List <Mesh> GenerateTriangulationMesh(HashSet <Triangle2> triangleData, bool shouldUnNormalize) { //Unnormalize HashSet <Triangle2> triangles_2d = new HashSet <Triangle2>(); if (shouldUnNormalize) { foreach (Triangle2 t in triangleData) { //Each face has in this case three edges MyVector2 p1 = t.p1; MyVector2 p2 = t.p2; MyVector2 p3 = t.p3; //Unnormalize the point p1 = normalizer.UnNormalize(p1); p2 = normalizer.UnNormalize(p2); p3 = normalizer.UnNormalize(p3); Triangle2 t_unnormalized = new Triangle2(p1, p2, p3); triangles_2d.Add(t_unnormalized); } } else { triangles_2d = triangleData; } //Make sure the triangles have the correct orientation //triangles_2d = HelpMethods.OrientTrianglesClockwise(triangles_2d); //From 2d to mesh in one step if we want one single mesh //Mesh displayMesh = _TransformBetweenDataStructures.Triangles2ToMesh(triangles_2d, useCompressedMesh: false); //Generate the meshes from triangles List <Mesh> meshes = new List <Mesh>(); foreach (Triangle2 t in triangles_2d) { Mesh triangleMesh = Triangle2ToMesh(t); meshes.Add(triangleMesh); } return(meshes); }
private void OnDrawGizmos() { Vector2 point = Point.position; Triangle2 triangle = CreateTriangle2(V0, V1, V2); Orientations orientation = triangle.CalcOrientation(); if (orientation == Orientations.CCW) { bool cont = triangle.Contains(point); bool cont1 = triangle.ContainsCCW(point); // Use this if you know triangle orientation FiguresColor(); DrawTriangle(ref triangle); if (cont) { ResultsColor(); } DrawPoint(point); LogInfo("Orientation: " + orientation + " Contained: " + cont); if (cont != cont1) { LogError("cont != cont1"); } } else if (orientation == Orientations.CW) { bool cont = triangle.Contains(point); bool cont1 = triangle.ContainsCW(point); // Use this if you know triangle orientation FiguresColor(); DrawTriangle(ref triangle); if (cont) { ResultsColor(); } DrawPoint(point); LogInfo("Orientation: " + orientation + " Contained: " + cont); if (cont != cont1) { LogError("cont != cont1"); } } else // Degenerate { LogError("Triangle is degenerate"); } }
//Triangle public static void DisplayTriangleMesh(MyVector2 a, MyVector2 b, MyVector2 c, Color color) { Triangle2 t = new Triangle2(a, b, c); HashSet <Triangle2> triangles = new HashSet <Triangle2>(); triangles.Add(t); triangles = HelpMethods.OrientTrianglesClockwise(triangles); Mesh mesh = _TransformBetweenDataStructures.Triangles2ToMesh(triangles, false); TestAlgorithmsHelpMethods.DisplayMesh(mesh, color); }
public void SetUniforms(Material DrawTriangleMaterial, Triangle2 TriangleUvs, Triangle3 TriangleColours) { var Uvs = new List <Vector2>(); Uvs.Add(TriangleUvs.a); Uvs.Add(TriangleUvs.b); Uvs.Add(TriangleUvs.c); var Colours = new List <Color>(); Colours.Add(new Color(TriangleColours.a.x, TriangleColours.a.y, TriangleColours.a.z, 1)); Colours.Add(new Color(TriangleColours.b.x, TriangleColours.b.y, TriangleColours.b.z, 1)); Colours.Add(new Color(TriangleColours.c.x, TriangleColours.c.y, TriangleColours.c.z, 1)); SetUniforms(DrawTriangleMaterial, Uvs, Colours); }
// triangle packing! public static List <Triangle2> AllocateTriangleAtlases(List <Triangle3> MeshTriangles) { var TriangleCount = MeshTriangles.Count; var AtlasWidth = (int)Mathf.Ceil(Mathf.Sqrt((float)TriangleCount)); var AtlasHeight = AtlasWidth; var AtlasTriangles = new List <Triangle2>(); for (int ti = 0; ti < MeshTriangles.Count; ti++) { var MeshTriangle = MeshTriangles[ti]; // get atlas quad var AtlasX = ti % AtlasWidth; var AtlasY = ti / AtlasWidth; var AtlasMinu = PopMath.Range(0, AtlasWidth, AtlasX); var AtlasMaxu = PopMath.Range(0, AtlasWidth, AtlasX + 1); var AtlasMinv = PopMath.Range(0, AtlasHeight, AtlasY); var AtlasMaxv = PopMath.Range(0, AtlasHeight, AtlasY + 1); // todo: get triangle position on it's plane (ie, it's ortho) var AtlasTriangle = new Triangle2(); AtlasTriangle.a = MeshTriangle.a.xz(); AtlasTriangle.b = MeshTriangle.b.xz(); AtlasTriangle.c = MeshTriangle.c.xz(); // fit triangle to quad var AtlasTriangleBounds = new Bounds2(); AtlasTriangleBounds.Min = PopMath.Min(AtlasTriangle.a, AtlasTriangle.b, AtlasTriangle.c); AtlasTriangleBounds.Max = PopMath.Max(AtlasTriangle.a, AtlasTriangle.b, AtlasTriangle.c); AtlasTriangle.a = PopMath.Range(AtlasTriangleBounds.Min, AtlasTriangleBounds.Max, AtlasTriangle.a); AtlasTriangle.b = PopMath.Range(AtlasTriangleBounds.Min, AtlasTriangleBounds.Max, AtlasTriangle.b); AtlasTriangle.c = PopMath.Range(AtlasTriangleBounds.Min, AtlasTriangleBounds.Max, AtlasTriangle.c); // now put it in it's atlas pos AtlasTriangle.a.x = Mathf.Lerp(AtlasMinu, AtlasMaxu, AtlasTriangle.a.x); AtlasTriangle.a.y = Mathf.Lerp(AtlasMinv, AtlasMaxv, AtlasTriangle.a.y); AtlasTriangle.b.x = Mathf.Lerp(AtlasMinu, AtlasMaxu, AtlasTriangle.b.x); AtlasTriangle.b.y = Mathf.Lerp(AtlasMinv, AtlasMaxv, AtlasTriangle.b.y); AtlasTriangle.c.x = Mathf.Lerp(AtlasMinu, AtlasMaxu, AtlasTriangle.c.x); AtlasTriangle.c.y = Mathf.Lerp(AtlasMinv, AtlasMaxv, AtlasTriangle.c.y); AtlasTriangles.Add(AtlasTriangle); } return(AtlasTriangles); }
//Remove the supertriangle IEnumerator RemoveSuperTriangle(Triangle2 superTriangle, HalfEdgeData2 triangulationData) { //The super triangle doesnt exists anymore because we have split it into many new triangles //But we can use its vertices to figure out which new triangles (or faces belonging to the triangle) //we should delete HashSet <HalfEdgeFace2> triangleFacesToDelete = new HashSet <HalfEdgeFace2>(); //Loop through all vertices belongin to the triangulation foreach (HalfEdgeVertex2 v in triangulationData.vertices) { //If the face attached to this vertex already exists in the list of faces we want to delete //Then dont add it again if (triangleFacesToDelete.Contains(v.edge.face)) { continue; } MyVector2 v1 = v.position; //Is this vertex in the triangulation a vertex in the super triangle? if (v1.Equals(superTriangle.p1) || v1.Equals(superTriangle.p2) || v1.Equals(superTriangle.p3)) { triangleFacesToDelete.Add(v.edge.face); } } //Debug.Log("Triangles to delete: " + trianglesToDelete.Count); //Delete the new triangles with vertices attached to the super triangle foreach (HalfEdgeFace2 f in triangleFacesToDelete) { HalfEdgeHelpMethods.DeleteTriangleFace(f, triangulationData, shouldSetOppositeToNull: true); //VISUALZ ShowTriangles(triangulationData); yield return(new WaitForSeconds(controller.pauseTime)); } //VISUALZ - show the colored mesh when its finished controller.shouldDisplayColoredMesh = true; yield return(null); }
/// <remarks>A point on the edge of a triangle is considered to be in it.</remarks> public static bool IsPointInTriangle(Vector2 p, Triangle2 t) { // credit: https://stackoverflow.com/a/20861130/6394285 var s = (t.A.Y * t.C.X) - (t.A.X * t.C.Y) + ((t.C.Y - t.A.Y) * p.X) + ((t.A.X - t.C.X) * p.Y); var h = (t.A.X * t.B.Y) - (t.A.Y * t.B.X) + ((t.A.Y - t.B.Y) * p.X) + ((t.B.X - t.A.X) * p.Y); if ((s < 0) != (h < 0)) { return(false); } var A = (-t.B.Y * t.C.X) + (t.A.Y * (t.C.X - t.B.X)) + (t.A.X * (t.B.Y - t.C.Y)) + (t.B.X * t.C.Y); return(A < 0 ? (s <= 0 && s + h >= A) : (s >= 0 && s + h <= A)); }
private void OnDrawGizmos() { Vector2 point = Point.position; Triangle2 triangle = CreateTriangle2(V0, V1, V2); Vector2 closestPoint; float dist = Distance.Point2Triangle2(ref point, ref triangle, out closestPoint); float dist1 = Distance.SqrPoint2Triangle2(ref point, ref triangle, out closestPoint); FiguresColor(); DrawTriangle(ref triangle); ResultsColor(); DrawPoint(closestPoint); LogInfo(dist + " " + Mathf.Sqrt(dist1)); }
//From Triangle2 to mesh where height is option to avoid z-fighting //But we can also determine height on DrawMesh() private Mesh Triangle2ToMesh(Triangle2 t, float meshHeight = 0f) { //Make a single mesh triangle Vector3 p1 = t.p1.ToVector3(meshHeight); Vector3 p2 = t.p2.ToVector3(meshHeight); Vector3 p3 = t.p3.ToVector3(meshHeight); Mesh triangleMesh = new Mesh(); triangleMesh.vertices = new Vector3[] { p1, p2, p3 }; triangleMesh.triangles = new int[] { 0, 1, 2 }; triangleMesh.RecalculateNormals(); return(triangleMesh); }
//Are two AABB intersecting? private void AABB_AABB() { MyVector2 t1_p1 = t1_p1_trans.position.ToMyVector2(); MyVector2 t1_p2 = t1_p2_trans.position.ToMyVector2(); MyVector2 t1_p3 = t1_p3_trans.position.ToMyVector2(); MyVector2 t2_p1 = t2_p1_trans.position.ToMyVector2(); MyVector2 t2_p2 = t2_p2_trans.position.ToMyVector2(); MyVector2 t2_p3 = t2_p3_trans.position.ToMyVector2(); Triangle2 t1 = new Triangle2(t1_p1, t1_p2, t1_p3); Triangle2 t2 = new Triangle2(t2_p1, t2_p2, t2_p3); bool isIntersecting = Intersections.AABB_AABB_2D( t1.MinX(), t1.MaxX(), t1.MinY(), t1.MaxY(), t2.MinX(), t2.MaxX(), t2.MinY(), t2.MaxY()); Debug.Log("AABB intersecting: " + isIntersecting); //Display the rectangles and the vertices we use to make the rectangles Vector3 r1_size = new Vector3(t1.MaxX() - t1.MinX(), 0.01f, t1.MaxY() - t1.MinY()); Vector3 r2_size = new Vector3(t2.MaxX() - t2.MinX(), 0.01f, t2.MaxY() - t2.MinY()); Vector3 r1_center = new Vector3(t1.MinX() + (r1_size.x * 0.5f), 0f, t1.MinY() + (r1_size.z * 0.5f)); Vector3 r2_center = new Vector3(t2.MinX() + (r2_size.x * 0.5f), 0f, t2.MinY() + (r2_size.z * 0.5f)); Gizmos.color = Color.white; Gizmos.DrawCube(r1_center, r1_size); float r = 0.1f; //Gizmos.DrawWireSphere(t1_p1.ToVector3(), r); //Gizmos.DrawWireSphere(t1_p2.ToVector3(), r); //Gizmos.DrawWireSphere(t1_p3.ToVector3(), r); Gizmos.color = isIntersecting ? Color.red : Color.white; Gizmos.DrawCube(r2_center, r2_size); //Gizmos.DrawWireSphere(t2_p1.ToVector3(), r); //Gizmos.DrawWireSphere(t2_p2.ToVector3(), r); //Gizmos.DrawWireSphere(t2_p3.ToVector3(), r); }
public Triangle2[] GetTris(){ Triangle2[] tris = new Triangle2[2]; Triangle2 t1 = new Triangle2(); Triangle2 t2 = new Triangle2(); t1.a = a; t1.b = b; t1.c = c; t1.Tag = this.Tag; t2.a = a; t2.b = b; t2.c = d; t2.Tag = this.Tag; tris[0] = t1; tris[1] = t2; return tris; }
static void Main() { Triangle1 t1 = new Triangle1(); t1.Width = 6; t1.Height = 8; Console.WriteLine("밑변은 {0} ", t1.Width); Console.WriteLine("높이는 {0} ", t1.Height); Console.WriteLine("면적은 {0} ", t1.Area); Triangle2 t2 = new Triangle2(); t2.Width = 6; t2.Height = 8; Console.WriteLine("밑변은 {0} ", t2.Width); Console.WriteLine("높이는 {0} ", t2.Height); Console.WriteLine("면적은 {0} ", t2.Area); }
//Generate the mesh from the half-edge data structure, which is called when we have flipped an edge public void GenerateTriangulationMesh(HalfEdgeData2 triangleData_normalized) { //From half-edge to triangle HashSet <Triangle2> triangles_2d = new HashSet <Triangle2>(); foreach (HalfEdgeFace2 f in triangleData_normalized.faces) { //Each face has in this case three edges MyVector2 p1 = f.edge.v.position; MyVector2 p2 = f.edge.nextEdge.v.position; MyVector2 p3 = f.edge.nextEdge.nextEdge.v.position; Triangle2 t = new Triangle2(p1, p2, p3); triangles_2d.Add(t); } GenerateTriangulationMesh(triangles_2d); }
public Triangle2[] GetTris() { Triangle2[] tris = new Triangle2[2]; Triangle2 t1 = new Triangle2(); Triangle2 t2 = new Triangle2(); t1.a = a; t1.b = b; t1.c = c; t1.Tag = this.Tag; t2.a = a; t2.b = b; t2.c = d; t2.Tag = this.Tag; tris[0] = t1; tris[1] = t2; return(tris); }
//이전 C# 버전에서 구조체(struct) 전체를 readonly로 만들 수 있었는데, //C# 8.0부터는 구조체의 각 멤버에 대해 개별적으로 readonly로 정의할 수 있게 되었다. //만약 구조체의 메서드나 속성이 구조체의 상태를 변경하지 않는다면 readonly로 적용할 수 있고, //readonly 멤버가 다른 non-readonly 멤버를 엑세스하면 컴파일러가 Warning을 표시한다. //C# 7.2에서 도입된 in 파라미터는 Value 타입의 파라미터를 Pass by reference로 전달할 수 있게 하는 기능을 제공한다. //만약 파라미터로 전달하는 구조체가(Value 타입) 큰 사이즈라면, Pass by value로 복사해서 전달하는 //것보다 위치 정보만을 전달하는 Pass by reference를 사용하는 것이 성능면에서 효율적이다. //이러한 목적으로 in 파라미터는 구조체를 Pass by value로 전달할 수 있는 기능을 제공한다. //만약 구조체 전체가 readonly라면, 즉 구조체 내부의 모든 멤버가 readonly라면, //in 파라미터를 사용하여 Pass by reference로 전달할 지라도 호출된 메서드(Callee)에서 구조체의 //내부 상태를 변경하는 행위를 할 수 없으므로, 호출자(Caller)의 구조체는 변경되지 않을 것이 확실하다. //이러한 측면에 큰 사이즈의 구조체를 in 파라미터로 전달하기 위해, //(가능하다면) 구조체를 readonly로 만들 것이 좋을 것이다. //하지만, 경우에 따라 구조체가 상태를 변경하는 멤버를 가질 수도 있다.이러한 경우에는 //일부 멤버들에 대해 readonly 멤버를 사용하는 것을 고려해 볼 수 있다. //Non-readonly 구조체인 경우 in 파라미터로 전달되면, //컴파일러는 호출된 메서드(Callee)에서 전달된 구조체의 멤버(메서드나 속성 등)을 //호출할 때마다 구조체 파라미터를 복사하게 된다. //이는 컴파일러가 구조체의 멤버가 상태를 변경하는지 미리 알 수 없기 때문에, //방어적으로 구조체를 다시 복사(defensive copy or hidden copy)하여 사용하는 것이다. //구조체의 크기가 큰 경우 Callee 에서 그 구조체에 대해 10개의 메서드/속성을 호출한다면, //10번의 복사가 읽어나는데 이는 성능을 저하시키는 원인이 될 수 있다. //예를 들어, 아래 예제를 보면, Triangle 구조체가 정의되어 있고, //이 Triangle 인스턴스를 Check(in Triangle) 메서드에 in 파라미터로 전달하고 있다. public StructReadOnly() { Triangle t = new Triangle(3, 4, 5); Check(t); Console.WriteLine($"t.IsEquilatrea : {t.IsEquilateral}"); t.a = 4; t.b = 4; t.c = 4; Console.WriteLine($"t.IsEquilatrea : {t.IsEquilateral}"); Check(t); t = new Triangle(5, 5, 5); Check(ref t, 1); Console.WriteLine($"t.IsEquilatrea : {t.IsEquilateral}"); Triangle2 t2 = new Triangle2(3, 3, 3); Check2(ref t2); Console.WriteLine($"t2.IsEquilatrea : {t2.IsEquilateral}"); }
// // Generate meshes // //Generate list of meshes from the Half-edge data structure public List <Mesh> GenerateTriangulationMesh(HalfEdgeData2 triangleData, bool shouldUnNormalize) { //From half-edge to triangle HashSet <Triangle2> triangles_2d = new HashSet <Triangle2>(); foreach (HalfEdgeFace2 f in triangleData.faces) { //Each face has in this case three edges MyVector2 p1 = f.edge.v.position; MyVector2 p2 = f.edge.nextEdge.v.position; MyVector2 p3 = f.edge.nextEdge.nextEdge.v.position; Triangle2 t = new Triangle2(p1, p2, p3); triangles_2d.Add(t); } List <Mesh> meshes = GenerateTriangulationMesh(triangles_2d, shouldUnNormalize); return(meshes); }
private void OnDrawGizmos() { Triangle2 triangle = new Triangle2(V0.position, V1.position, V2.position); Gizmos.color = Color.gray; Gizmos.DrawLine(triangle.V0, triangle.V1); Gizmos.DrawLine(triangle.V1, triangle.V2); Gizmos.DrawLine(triangle.V2, triangle.V0); var ori = triangle.CalcOrientation(); Vector3 angles = triangle.CalcAnglesDeg(); Gizmos.color = Color.blue; float radius = .25f; Vector2 baryPoint = triangle.EvalBarycentric(c0, c1); Vector3 baryCoords = triangle.CalcBarycentricCoords(ref baryPoint); Gizmos.DrawSphere(baryPoint, radius); Logger.LogInfo("orientation: " + ori + " Angles: " + angles.ToStringEx() + " Bary: " + baryCoords.ToStringEx()); }
private void OnDrawGizmos() { Line2 line = CreateLine2(Line); Triangle2 triangle = CreateTriangle2(V0, V1, V2); IntersectionTypes intersectionType; bool test = Intersection.TestLine2Triangle2(ref line, ref triangle, out intersectionType); Line2Triangle2Intr info; bool find = Intersection.FindLine2Triangle2(ref line, ref triangle, out info); FiguresColor(); DrawLine(ref line); DrawTriangle(ref triangle); if (find) { ResultsColor(); if (info.IntersectionType == IntersectionTypes.Point) { DrawPoint(info.Point0); } else if (info.IntersectionType == IntersectionTypes.Segment) { DrawSegment(info.Point0, info.Point1); DrawPoint(info.Point0); DrawPoint(info.Point1); } } LogInfo(intersectionType); if (test != find) { LogError("test != find"); } if (intersectionType != info.IntersectionType) { LogError("intersectionType != info.IntersectionType"); } }
private void OnDrawGizmos() { Triangle2 triangle = CreateTriangle2(V0, V1, V2); Vector2 point = Point.position; Orientations orientation = triangle.CalcOrientation(); int ccwSide = triangle.QuerySideCCW(point); int cwSide = triangle.QuerySideCW(point); FiguresColor(); DrawTriangle(ref triangle); if (orientation == Orientations.CCW) { SetColor(ccwSide); } else if (orientation == Orientations.CW) { SetColor(cwSide); } DrawPoint(point); LogInfo("Orientation: " + orientation + " CCWSide: " + ccwSide + " CWSide: " + cwSide); }