public Vector3d RotateVector(Vector3d v, Vector3d axis, double angle) { axis = axis.UnitVector(); double t = CadMath.Deg2Rad(angle); CadQuaternion q = CadQuaternion.RotateQuaternion(axis, t); CadQuaternion r = q.Conjugate();; CadQuaternion qp; qp = CadQuaternion.FromPoint(v); qp = r * qp; qp = qp * q; Vector3d rv = v; rv = qp.ToPoint(); return(rv); }
// 回転体の作成 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); }