public static bool IsPointInTriangle(Vector3d p, CadFace triangle, CadMesh mesh) { if (triangle.VList.Count < 3) { return(false); } Vector3d p0 = mesh.VertexStore[triangle.VList[0]].vector; Vector3d p1 = mesh.VertexStore[triangle.VList[1]].vector; Vector3d p2 = mesh.VertexStore[triangle.VList[2]].vector; Vector3d c1 = CadMath.CrossProduct(p, p0, p1); Vector3d c2 = CadMath.CrossProduct(p, p1, p2); Vector3d c3 = CadMath.CrossProduct(p, p2, p0); double ip12 = CadMath.InnerProduct(c1, c2); double ip13 = CadMath.InnerProduct(c1, c3); // When all corossProduct result's sign are same, Point is in triangle if (ip12 > 0 && ip13 > 0) { return(true); } return(false); }
// Faceを三角形に分割する public static List <CadFace> Split(CadFace face, CadMesh mesh) { CadVertex p0 = default(CadVertex); // Deep copy CadFace src = new CadFace(face); var triangles = new List <CadFace>(); int i1 = -1; int state = 0; CadFace triangle; i1 = FindMaxDistantPointIndex(p0, src, mesh); if (i1 == -1) { return(triangles); } triangle = GetTriangleWithCenterPoint(src, i1); Vector3d tp0 = mesh.VertexStore[triangle.VList[0]].vector; Vector3d tp1 = mesh.VertexStore[triangle.VList[1]].vector; Vector3d tp2 = mesh.VertexStore[triangle.VList[2]].vector; Vector3d dir = CadMath.Normal(tp1, tp0, tp2); Vector3d currentDir = Vector3d.Zero; while (src.VList.Count > 3) { if (state == 0) { i1 = FindMaxDistantPointIndex(p0, src, mesh); if (i1 == -1) { return(triangles); } } triangle = GetTriangleWithCenterPoint(src, i1); tp0 = mesh.VertexStore[triangle.VList[0]].vector; tp1 = mesh.VertexStore[triangle.VList[1]].vector; tp2 = mesh.VertexStore[triangle.VList[2]].vector; currentDir = CadMath.Normal(tp1, tp0, tp2); bool hasIn = ListContainsPointInTriangle(triangle, src, mesh); double scala = CadMath.InnerProduct(dir, currentDir); if (!hasIn && (scala > 0)) { triangles.Add(triangle); src.VList.RemoveAt(i1); state = 0; continue; } if (state == 0) { state = 1; i1 = 0; } else if (state == 1) { i1++; if (i1 >= src.VList.Count) { break; } } } if (src.VList.Count == 3) { triangle = new CadFace(); triangle.VList.Add(src.VList[0]); triangle.VList.Add(src.VList[1]); triangle.VList.Add(src.VList[2]); triangles.Add(triangle); } return(triangles); }
public static CadMesh CreateExtruded(VertexList src, Vector3d dv, int div = 0) { if (src.Count < 3) { return(null); } div += 1; VertexList vl; Vector3d n = CadUtil.TypicalNormal(src); if (CadMath.InnerProduct(n, dv) <= 0) { vl = new VertexList(src); vl.Reverse(); } else { vl = src; } int vlCnt = vl.Count; CadMesh mesh = new CadMesh(vl.Count * 2, vl.Count); CadFace f; Vector3d dt = dv / div; Vector3d sv = Vector3d.Zero; // 頂点リスト作成 for (int i = 0; i < div + 1; i++) { for (int j = 0; j < vlCnt; j++) { mesh.VertexStore.Add(vl[j] + sv); } sv += dt; } // 表面 f = new CadFace(); for (int i = 0; i < vlCnt; i++) { f.VList.Add(i); } mesh.FaceStore.Add(f); // 裏面 f = new CadFace(); int si = (div + 1) * vlCnt - 1; int ei = si - (vlCnt - 1); for (int i = si; i >= ei; i--) { f.VList.Add(i); } mesh.FaceStore.Add(f); // 側面 for (int k = 0; k < div; k++) { int ti = vlCnt * k; for (int i = 0; i < vlCnt; i++) { int j = (i + 1) % vlCnt; f = new CadFace(); f.VList.Add(i + ti); f.VList.Add(i + ti + vlCnt); f.VList.Add(j + ti + vlCnt); f.VList.Add(j + ti); mesh.FaceStore.Add(f); } } MeshUtil.SplitAllFace(mesh); return(mesh); }
// 回転体の作成 public static CadMesh CreateRotatingBody(int circleDiv, Vector3d org, Vector3d axis, VertexList vl, bool topCap, bool btmCap, FaceType facetype = FaceType.TRIANGLE) { if (vl.Count < 2) { return(null); } #region 面の向きが外から中心に向かってみた場合に左回りになるように回転軸の向きを調整 // vlの全体的な向きを求めるためvl[0]から一番遠い点を求める int fi = CadUtil.FindMaxDistantPointIndex(vl[0], vl); Vector3d vldir = (Vector3d)(vl[fi] - vl[0]); // vlの全体的な向きと回転軸の向きが同じ場合、回転軸の向きを反転 double dot = CadMath.InnerProduct(axis, vldir); if (dot > 0) { axis *= -1; } #endregion CadMesh mesh = new CadMesh(vl.Count * circleDiv, vl.Count * circleDiv); CrossInfo crossS = CadMath.PerpCrossLine(org, org + axis, (Vector3d)vl[0]); CrossInfo crossE = CadMath.PerpCrossLine(org, org + axis, (Vector3d)vl.End()); crossS.Distance = (crossS.CrossPoint - (Vector3d)vl[0]).Length; crossE.Distance = (crossE.CrossPoint - (Vector3d)vl.End()).Length; int s = 0; int e = vl.Count; int vc = vl.Count; int ps = 0; // VertexStoreの並びは以下の様になる。vlの個数をnとする。 // topCap中心点, btmCap中心点, 側面点0, 側面点1 ..... 側面点n-1 // 変数ps: 側面の点0の位置 // 変数s: vlから取り出す先頭位置 // 最初の点をtopCapの中心とする場合、側面点0ではなくなるので、+1する // 変数e: vlから取り出す終端 // 最後の点をbtmCapの中心とする場合、側面点n-1ではなくなるので、-1する // 変数vc: 側面1列の点の数 if (crossS.Distance < CadMath.Epsilon) { mesh.VertexStore.Add(vl[0]); s += 1; topCap = true; vc--; ps++; } else if (topCap) { mesh.VertexStore.Add((CadVertex)crossS.CrossPoint); ps++; } if (crossE.Distance < CadMath.Epsilon) { mesh.VertexStore.Add(vl.End()); e -= 1; btmCap = true; vc--; ps++; } else if (btmCap) { mesh.VertexStore.Add((CadVertex)crossE.CrossPoint); ps++; } double d = Math.PI * 2.0 / circleDiv; CadQuaternion qp; for (int i = 0; i < circleDiv; i++) { double a = i * d; CadQuaternion q = CadQuaternion.RotateQuaternion(axis, a); CadQuaternion con = q.Conjugate(); for (int vi = s; vi < e; vi++) { CadVertex p = vl[vi]; p.vector -= org; qp = CadQuaternion.FromPoint(p.vector); qp = con * qp; qp = qp * q; p.vector = qp.ToPoint(); p += org; mesh.VertexStore.Add(p); } } CadFace f; if (topCap) { for (int i = 0; i < circleDiv; i++) { f = new CadFace(0, ((i + 1) % circleDiv) * vc + ps, i * vc + ps); mesh.FaceStore.Add(f); } } if (btmCap) { for (int i = 0; i < circleDiv; i++) { int bi = (vc - 1); f = new CadFace(1, (i * vc) + bi + ps, ((i + 1) % circleDiv) * vc + bi + ps); mesh.FaceStore.Add(f); } } // 四角形で作成 if (facetype == FaceType.QUADRANGLE) { for (int i = 0; i < circleDiv; i++) { int nextSlice = ((i + 1) % circleDiv) * vc + ps; for (int vi = 0; vi < vc - 1; vi++) { f = new CadFace( (i * vc) + ps + vi, nextSlice + vi, nextSlice + vi + 1, (i * vc) + ps + vi + 1 ); mesh.FaceStore.Add(f); } } } else { // 三角形で作成 for (int i = 0; i < circleDiv; i++) { int nextSlice = ((i + 1) % circleDiv) * vc + ps; for (int vi = 0; vi < vc - 1; vi++) { f = new CadFace( (i * vc) + ps + vi, nextSlice + vi, (i * vc) + ps + vi + 1 ); mesh.FaceStore.Add(f); f = new CadFace( nextSlice + vi, nextSlice + vi + 1, (i * vc) + ps + vi + 1 ); mesh.FaceStore.Add(f); } } } return(mesh); }