private void FaceToDirection(CadFigure fig, Vector3d org, Vector3d dir) { if (fig.Type != CadFigure.Types.POLY_LINES) { return; } Vector3d faceNormal = CadUtil.TypicalNormal(fig.PointList); if (faceNormal.EqualsThreshold(dir) || (-faceNormal).EqualsThreshold(dir)) { // Face is already target direction return; } // | 回転軸 rv // | // | // | --------->向けたい方向 dir // / // / // 面の法線 faceNormal Vector3d rv = CadMath.Normal(faceNormal, dir); double t = CadMath.AngleOfVector(faceNormal, dir); CadUtil.RotateFigure(fig, org, rv, t); }
public async void FlipWithInteractive(List <CadFigure> rootFigList) { await Task.Run(() => { Controller.StartEdit(); var res = InputLine(); if (res.state != InteractCtrl.States.END) { Controller.AbendEdit(); return; } if ((res.p1 - res.p0).IsZero()) { Controller.AbendEdit(); ItConsole.println("Error: Same point"); return; } Vector3d normal = CadMath.Normal( res.p1 - res.p0, (Controller.DC.ViewDir)); FlipWithPlane(rootFigList, res.p0, normal); RunOnMainThread(() => { Controller.EndEdit(); Controller.Redraw(); }); }); }
public static CadMesh CreateUnitCube(Vector3d wv, Vector3d hv, FaceType faceType = FaceType.TRIANGLE) { Vector3d tv = CadMath.Normal(wv, hv); Vector3d wv2 = wv / 2; Vector3d hv2 = hv / 2; Vector3d tv2 = tv / 2; CadMesh cm = new CadMesh(8, 12); cm.VertexStore.Add(CadVertex.Create(wv2 + hv2 + tv2)); cm.VertexStore.Add(CadVertex.Create(-wv2 + hv2 + tv2)); cm.VertexStore.Add(CadVertex.Create(-wv2 - hv2 + tv2)); cm.VertexStore.Add(CadVertex.Create(wv2 - hv2 + tv2)); cm.VertexStore.Add(CadVertex.Create(wv2 + hv2 - tv2)); cm.VertexStore.Add(CadVertex.Create(-wv2 + hv2 - tv2)); cm.VertexStore.Add(CadVertex.Create(-wv2 - hv2 - tv2)); cm.VertexStore.Add(CadVertex.Create(wv2 - hv2 - tv2)); if (faceType == FaceType.QUADRANGLE) { cm.FaceStore.Add(new CadFace(0, 1, 2, 3)); cm.FaceStore.Add(new CadFace(7, 6, 5, 4)); cm.FaceStore.Add(new CadFace(0, 4, 5, 1)); cm.FaceStore.Add(new CadFace(1, 5, 6, 2)); cm.FaceStore.Add(new CadFace(2, 6, 7, 3)); cm.FaceStore.Add(new CadFace(3, 7, 4, 0)); } else { cm.FaceStore.Add(new CadFace(0, 1, 2)); cm.FaceStore.Add(new CadFace(2, 3, 0)); cm.FaceStore.Add(new CadFace(7, 6, 5)); cm.FaceStore.Add(new CadFace(5, 4, 7)); cm.FaceStore.Add(new CadFace(0, 4, 5)); cm.FaceStore.Add(new CadFace(5, 1, 0)); cm.FaceStore.Add(new CadFace(1, 5, 6)); cm.FaceStore.Add(new CadFace(6, 2, 1)); cm.FaceStore.Add(new CadFace(2, 6, 7)); cm.FaceStore.Add(new CadFace(7, 3, 2)); cm.FaceStore.Add(new CadFace(3, 7, 4)); cm.FaceStore.Add(new CadFace(4, 0, 3)); } return(cm); }
public CadFigure AddRectRectChamferAt(Vector3d p, double w, double h, double c) { Vector3d viewDir = Controller.DC.ViewDir; Vector3d upDir = Controller.DC.UpVector; Vector3d wdir = CadMath.Normal(viewDir, upDir); Vector3d hdir = upDir.UnitVector(); Vector3d wd = wdir * w; Vector3d hd = hdir * h; CadVertex sp = (CadVertex)p; CadVertex tp = sp; Vector3d wc = wdir * c; Vector3d hc = hdir * c; CadFigure fig = Controller.DB.NewFigure(CadFigure.Types.RECT); fig.AddPoint(tp + wc); tp += wd; fig.AddPoint(tp - wc); fig.AddPoint(tp + hc); tp += hd; fig.AddPoint(tp - hc); fig.AddPoint(tp - wc); tp = sp + hd; fig.AddPoint(tp + wc); fig.AddPoint(tp - hc); tp = sp; fig.AddPoint(tp + hc); fig.IsLoop = true; fig.EndCreate(Controller.DC); CadOpe ope = new CadOpeAddFigure(Controller.CurrentLayer.ID, fig.ID); Session.AddOpe(ope); Controller.CurrentLayer.AddFigure(fig); Session.PostRemakeObjectTree(); return(fig); }
public void CutMesh(uint id) { CadFigureMesh tfig = GetCadFigureMesh(id); if (tfig == null) { ItConsole.println("invalid ID"); return; } (Vector3d p0, Vector3d p1) = InputLine(); if (p0.IsInvalid() || p1.IsInvalid()) { return; } HeModel he = tfig.mHeModel; CadMesh src = HeModelConverter.ToCadMesh(he); Vector3d normal = CadMath.Normal( p1 - p0, (Controller.DC.ViewDir)); (CadMesh m1, CadMesh m2) = MeshUtil.CutMeshWithVector(src, p0, p1, normal); CadFigureMesh fig1 = (CadFigureMesh)Controller.DB.NewFigure(CadFigure.Types.MESH); fig1.SetMesh(HeModelConverter.ToHeModel(m1)); CadFigureMesh fig2 = (CadFigureMesh)Controller.DB.NewFigure(CadFigure.Types.MESH); fig2.SetMesh(HeModelConverter.ToHeModel(m2)); CadOpe ope; ope = new CadOpeAddFigure(Controller.CurrentLayer.ID, fig1.ID); Session.AddOpe(ope); Controller.CurrentLayer.AddFigure(fig1); ope = new CadOpeAddFigure(Controller.CurrentLayer.ID, fig2.ID); Session.AddOpe(ope); Controller.CurrentLayer.AddFigure(fig2); ope = new CadOpeRemoveFigure(Controller.CurrentLayer, tfig.ID); Session.AddOpe(ope); Controller.CurrentLayer.RemoveFigureByID(tfig.ID); Controller.ClearSelection(); Session.PostRemakeObjectTree(); }
// 三角形の追加 // 左右回り方を統一して追加するようにする public void AddTriangle(int v0, int v1, int v2) { HalfEdge he0 = mHeModel.CreateHalfEdge(v0); HalfEdge he1 = mHeModel.CreateHalfEdge(v1); HalfEdge he2 = mHeModel.CreateHalfEdge(v2); he0.Next = he1; he0.Prev = he2; he1.Next = he2; he1.Prev = he0; he2.Next = he0; he2.Prev = he1; // 法線の設定 Vector3d normal = CadMath.Normal( mHeModel.VertexStore[v0].vector, mHeModel.VertexStore[v1].vector, mHeModel.VertexStore[v2].vector); // Faceの設定 HeFace face = mHeModel.CreateFace(he0); if (!normal.IsInvalid()) { face.Normal = mHeModel.NormalStore.Add(normal); he0.Normal = mHeModel.NormalStore.Add(normal); he1.Normal = mHeModel.NormalStore.Add(normal); he2.Normal = mHeModel.NormalStore.Add(normal); } int faceIndex = mHeModel.FaceStore.Add(face); he0.Face = faceIndex; he1.Face = faceIndex; he2.Face = faceIndex; // Pairの設定 HeConnector.SetHalfEdgePair(he0, HeMap); HeMap[HeConnector.GetHeKey(he0)] = he0; HeConnector.SetHalfEdgePair(he1, HeMap); HeMap[HeConnector.GetHeKey(he1)] = he1; HeConnector.SetHalfEdgePair(he2, HeMap); HeMap[HeConnector.GetHeKey(he2)] = he2; }
public async void CutMeshWithInteractive(CadFigure fig) { await Task.Run(() => { var res = InputLine(); if (res.state != InteractCtrl.States.END) { Controller.AbendEdit(); return; } if ((res.p1 - res.p0).IsZero()) { Controller.AbendEdit(); ItConsole.println("Error: Same point"); return; } CadFigureMesh mesh = fig as CadFigureMesh; if (mesh == null) { Controller.AbendEdit(); ItConsole.println("Error: Target is not mesh"); return; } Vector3d normal = CadMath.Normal( res.p1 - res.p0, (Controller.DC.ViewDir)); CutMeshWithVector(mesh, res.p0, res.p1, normal); RunOnMainThread(() => { Controller.ClearSelection(); Controller.Redraw(); }); }); }
public async void FlipAndCopyWithInteractive(List <CadFigure> rootFigList) { await Task.Run(() => { var res = InputLine(); if (res.state != InteractCtrl.States.END) { return; } if ((res.p1 - res.p0).IsZero()) { ItConsole.println("Error: Same point"); return; } Vector3d normal = CadMath.Normal( res.p1 - res.p0, Controller.DC.ViewDir); FlipAndCopyWithPlane(rootFigList, res.p0, normal); }); }
public CadFigure AddCircleAt(Vector3d p, double r) { Vector3d viewDir = Controller.DC.ViewDir; Vector3d upDir = Controller.DC.UpVector; CadFigure fig = Controller.DB.NewFigure(CadFigure.Types.CIRCLE); Vector3d p0 = p; Vector3d p1 = p0 + CadMath.Normal(viewDir, upDir) * r; fig.AddPoint((CadVertex)p0); fig.AddPoint((CadVertex)p1); fig.EndCreate(Controller.DC); CadOpe ope = new CadOpeAddFigure(Controller.CurrentLayer.ID, fig.ID); Session.AddOpe(ope); Controller.CurrentLayer.AddFigure(fig); Session.PostRemakeObjectTree(); return(fig); }
public CadFigure AddRectAt(Vector3d p, double w, double h) { Vector3d viewDir = Controller.DC.ViewDir; Vector3d upDir = Controller.DC.UpVector; Vector3d wd = CadMath.Normal(viewDir, upDir) * w; Vector3d hd = upDir.UnitVector() * h; CadVertex p0 = (CadVertex)p; CadVertex p1 = (CadVertex)p; CadFigure fig = Controller.DB.NewFigure(CadFigure.Types.RECT); fig.AddPoint(p0); p1 = p0 + wd; fig.AddPoint(p1); p1 = p0 + wd + hd; fig.AddPoint(p1); p1 = p0 + hd; fig.AddPoint(p1); fig.IsLoop = true; fig.EndCreate(Controller.DC); CadOpe ope = new CadOpeAddFigure(Controller.CurrentLayer.ID, fig.ID); Session.AddOpe(ope); Controller.CurrentLayer.AddFigure(fig); Session.PostRemakeObjectTree(); return(fig); }
public void RecreateNormals() { Vector3dList newNormalStore = new Vector3dList(VertexStore.Count); int i; for (i = 0; i < FaceStore.Count; i++) { HeFace face = FaceStore[i]; HalfEdge head = FaceStore[i].Head; HalfEdge c = head; Vector3d n = CadMath.Normal( VertexStore[c.Vertex].vector, VertexStore[c.Next.Vertex].vector, VertexStore[c.Next.Next.Vertex].vector ); face.Normal = newNormalStore.Add(n); for (; ;) { c.Normal = newNormalStore.Add(n); c = c.Next; if (c == head) { break; } } } NormalStore = newNormalStore; }
// 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); }
// option: // e.g. // a100q30 max area = 100, min degree = 30 // a100q max area = 100, min degree = default (20) // min degree < 34 // Other options see // https://www.cs.cmu.edu/~quake/triangle.switch.html // public void Triangulate(uint figID, string option) { CadFigure tfig = Controller.DB.GetFigure(figID); if (tfig == null || tfig.Type != Types.POLY_LINES) { return; } if (tfig.PointCount < 3) { return; } CadFigure cfig = FigUtil.Clone(tfig); Vector3d org = cfig.PointList[0].vector; Vector3d dir = Vector3d.UnitZ; Vector3d faceNormal = CadUtil.TypicalNormal(cfig.PointList); Vector3d rotateV = default; double t = 0; if (!faceNormal.EqualsThreshold(dir) && !(-faceNormal).EqualsThreshold(dir)) { rotateV = CadMath.Normal(faceNormal, dir); t = -CadMath.AngleOfVector(faceNormal, dir); CadUtil.RotateFigure(cfig, org, rotateV, t); } //Controller.CurrentLayer.AddFigure(cfig); VertexList vl = cfig.GetPoints(12); CadMesh m = IglW.Triangulate(vl, option); HeModel hem = HeModelConverter.ToHeModel(m); CadFigureMesh fig = (CadFigureMesh)Controller.DB.NewFigure(CadFigure.Types.MESH); fig.SetMesh(hem); for (int i = 0; i < fig.PointCount; i++) { CadVertex v = fig.PointList[i]; v.Z = org.Z; fig.PointList[i] = v; } if (t != 0) { CadUtil.RotateFigure(fig, org, rotateV, -t); } CadOpeList root = new CadOpeList(); CadOpe ope; ope = new CadOpeAddFigure(Controller.CurrentLayer.ID, fig.ID); Session.AddOpe(ope); Controller.CurrentLayer.AddFigure(fig); ope = new CadOpeRemoveFigure(Controller.CurrentLayer, figID); Session.AddOpe(ope); Controller.CurrentLayer.RemoveFigureByID(figID); Controller.CurrentFigure = null; Session.PostRemakeObjectTree(); }