public void LaplaceRelaxation(TopoModel model) { double n = 2; RHVector3 newPos = new RHVector3(pos); newPos.AddInternal(pos); foreach (TopoTriangle t in connectedFacesList) { int idx = t.VertexIndexFor(this); n += 2; newPos.AddInternal(t.vertices[(idx + 1) % 3].pos); newPos.AddInternal(t.vertices[(idx + 2) % 3].pos); } newPos.Scale(1.0 / n); // validate newPos does not create intersecting triangles or bad shapes foreach (TopoTriangle t in connectedFacesList) { int idx = t.VertexIndexFor(this); RHVector3 d1 = t.vertices[(idx+1)%3].pos.Subtract(newPos); RHVector3 d2 = t.vertices[(idx+2)%3].pos.Subtract(t.vertices[(idx+1)%3].pos); RHVector3 normal = d1.CrossProduct(d2); if (normal.ScalarProduct(t.normal) < 0) return; double angle = t.AngleEdgePoint((idx + 1) % 3, newPos); if(angle < 0.088 || angle > 2.96) return; // Angle gets to small } model.vertices.ChangeCoordinates(this, newPos); }
public TopoModel Copy() { TopoModel newModel = new TopoModel(); int nOld = vertices.Count; int i = 0; List<TopoVertex> vcopy = new List<TopoVertex>(vertices.Count); foreach (TopoVertex v in vertices) { v.id = i++; TopoVertex newVert = new TopoVertex(v.id, v.pos); newModel.addVertex(newVert); vcopy.Add(newVert); } foreach (TopoTriangle t in triangles) { TopoTriangle triangle = new TopoTriangle(newModel, vcopy[t.vertices[0].id], vcopy[t.vertices[1].id], vcopy[t.vertices[2].id], t.normal.x, t.normal.y, t.normal.z); newModel.triangles.Add(triangle); } UpdateVertexNumbers(); newModel.UpdateVertexNumbers(); newModel.badEdges = 0; newModel.badTriangles = badTriangles; newModel.shells = shells; newModel.updatedNormals = updatedNormals; newModel.loopEdges = loopEdges; newModel.manyShardEdges = 0; newModel.manifold = manifold; newModel.normalsOriented = normalsOriented; return newModel; }
public void FixNormals() { if (repairedModel == null) repairedModel = originalModel.Copy(); repairedModel.UpdateNormals(); repairedModel.AnalyseFast(); //repairedModel.updateBad(); ShowRepaired(true); }
void TestInplaneOutside() { TopoModel model = new TopoModel(); TopoVertex v1 = model.addVertex(new RHVector3(0, 0, 0)); TopoVertex v2 = model.addVertex(new RHVector3(10, 0, 0)); TopoVertex v3 = model.addVertex(new RHVector3(10, 10, 0)); TopoVertex v4 = model.addVertex(new RHVector3(11, 1, 0)); TopoVertex v5 = model.addVertex(new RHVector3(17, 1, 0)); TopoVertex v6 = model.addVertex(new RHVector3(11, 7, 0)); TopoTriangle t1 = model.AddTriangle(new TopoTriangle(model, v1, v2, v3)); TopoTriangle t2 = model.AddTriangle(new TopoTriangle(model, v4, v5, v6)); if (t1.Intersects(t2)) { faildTests++; Console.WriteLine("Failed test:TestInplaneOutside"); } }
void TestSharedPointIntersect() { TopoModel model = new TopoModel(); TopoVertex v1 = model.addVertex(new RHVector3(0, 0, 0)); TopoVertex v2 = model.addVertex(new RHVector3(10, 0, 0)); TopoVertex v3 = model.addVertex(new RHVector3(5, 5, 0)); TopoVertex v4 = model.addVertex(new RHVector3(0, 0, -5)); TopoVertex v5 = model.addVertex(new RHVector3(10, 0, -5)); TopoVertex v6 = model.addVertex(new RHVector3(5, 0, 5)); TopoTriangle t1 = model.AddTriangle(new TopoTriangle(model, v1, v2, v3)); TopoTriangle t2 = model.AddTriangle(new TopoTriangle(model, v1, v5, v6)); if (!t1.Intersects(t2)) { faildTests++; Console.WriteLine("Failed test:TestSharedPointIntersect"); } }
public void Analyse(PrintModel pm) { TopoModel m = new TopoModel(); m.Merge(pm.Model, pm.trans); infoVolume.Text = (0.001*m.Volume()).ToString("0.0000") + " cm³"; infoSurface.Text = (0.01 * m.Surface()).ToString("0.0000") + " cm²"; infoShells.Text = pm.Model.shells.ToString(); infoPoints.Text = pm.Model.vertices.Count.ToString(); infoEdges.Text = pm.Model.edges.Count.ToString(); infoFaces.Text = pm.Model.triangles.Count.ToString(); infoMinX.Text = m.boundingBox.minPoint.x.ToString("0.00")+" mm"; infoMaxX.Text = m.boundingBox.maxPoint.x.ToString("0.00") + " mm"; infoSizeX.Text = m.boundingBox.Size.x.ToString("0.00") + " mm"; infoMinY.Text = m.boundingBox.minPoint.y.ToString("0.00") + " mm"; infoMaxY.Text = m.boundingBox.maxPoint.y.ToString("0.00") + " mm"; infoSizeY.Text = m.boundingBox.Size.y.ToString("0.00") + " mm"; infoMinZ.Text = m.boundingBox.minPoint.z.ToString("0.00") + " mm"; infoMaxZ.Text = m.boundingBox.maxPoint.z.ToString("0.00") + " mm"; infoSizeZ.Text = m.boundingBox.Size.z.ToString("0.00") + " mm"; groupBox1.Text = pm.name; }
//QFont font; //float arrow_length; internal Coordinate() { submesh = new Submesh[3]; model = new TopoModel[3]; //arrow_length = Convert.ToSingle(Math.Abs(model.boundingBox.zMax - model.boundingBox.zMin)); // override mesh color for (int i = 0; i < 3; i++) { // import mesh from STL. model[i] = new TopoModel(); model[i].importSTL(Application.StartupPath + Path.DirectorySeparatorChar + names[i],1); submesh[i] = new Submesh(); model[i].FillMeshTrianglesOnly(submesh[i], 0); submesh[i].Compress(true, coordinate_colors[i]); submesh[i].vertices.Clear(); } model = null; // release memory // config font /*font = new QFont("data/HappySans.ttf", label_font_size, new QFontBuilderConfiguration(true)); font.Options.DropShadowActive = false;*/ }
public void RunTest() { if (repairedModel == null) { repairedModel = originalModel.Copy(); repairedModel.RepairUnobtrusive(); } repairedModel.RetestIntersectingTriangles(); //repairedModel.JoinTouchedOpenEdges(0.1); //repairedModel.UpdateNormals(); repairedModel.Analyse(); repairedModel.updateBad(); ShowRepaired(true); }
public void Reset() { repairedModel = originalModel.Copy(); repairedModel.Analyse(); ShowRepaired(true); }
public void DeepAnalysis(InfoProgressPanel ipp) { originalModel.ipp = ipp; originalModel.Analyse(); if (ipp.IsKilled) { return; } originalModel.updateBad(); if (originalModel.intersectingTriangles.Count > 0 || originalModel.badTriangles > 0 || originalModel.manifold == false || originalModel.manyShardEdges != 0 || originalModel.loopEdges != 0 || originalModel.normalsOriented == false) { if (repairedModel == null) repairedModel = originalModel.Copy(); repairedModel.ipp = ipp; repairedModel.RepairUnobtrusive(); repairedModel.Analyse(); originalModel.Analyse(); if (ipp.IsKilled) { originalModel.clear(); repairedModel.clear(); return; } repairedModel.updateBad(); ShowRepaired(true); repairedModel.ipp = null; } originalModel.ipp = null; }
public PrintModel cloneWithModel(TopoModel m,int idx) { PrintModel stl = new PrintModel(); stl.filename = ""; stl.name = name+" ("+idx+")"; stl.lastModified = lastModified; stl.Position.x = Position.x; stl.Position.y = Position.y; stl.Position.z = Position.z; stl.Scale.x = Scale.x; stl.Scale.y = Scale.y; stl.Scale.z = Scale.z; stl.Rotation.x = Rotation.x; stl.Rotation.y = Rotation.y; stl.Rotation.z = Rotation.z; stl.Selected = false; stl.activeModel = 0; stl.originalModel = m; stl.repairedModel = null; stl.UpdateBoundingBox(); return stl; }
void TestInplane3D_1() { TopoModel model = new TopoModel(); TopoVertex v1 = model.addVertex(new RHVector3(3.67848944664001,-2.6547646522522,1.38814495312454E-14)); TopoVertex v2 = model.addVertex(new RHVector3(1.62981510162354,-1.05116808414459,1.83297828141877E-14)); TopoVertex v3 = model.addVertex(new RHVector3(2.29873323440552,-0.79055267572403,2.11497486191092E-14)); TopoVertex v4 = model.addVertex(new RHVector3(1.63205575942993,-1.05116808414459,2.78849697113037)); TopoVertex v5 = model.addVertex(new RHVector3(0.916237592697144,-1.1297744512558,1.83297828141877E-14)); TopoVertex v6 = model.addVertex(new RHVector3(1.38571500778198,-1.07829427719116,2.67316389083862)); TopoTriangle t1 = model.AddTriangle(new TopoTriangle(model, v1, v2, v3)); TopoTriangle t2 = model.AddTriangle(new TopoTriangle(model, v4, v5, v6)); if (t1.Intersects(t2)) { faildTests++; Console.WriteLine("Failed test:TestInplane3D_1"); } }
void TestInplaneInsideSameEdgeIntersects() { TopoModel model = new TopoModel(); TopoVertex v1 = model.addVertex(new RHVector3(0, 0, 0)); TopoVertex v2 = model.addVertex(new RHVector3(10, 0, 0)); TopoVertex v3 = model.addVertex(new RHVector3(10, 10, 0)); TopoVertex v4 = model.addVertex(new RHVector3(1, 1, 0)); TopoVertex v5 = model.addVertex(new RHVector3(7, 1, 0)); TopoVertex v6 = model.addVertex(new RHVector3(5, 3, 0)); TopoTriangle t1 = model.AddTriangle(new TopoTriangle(model, v1, v2, v3)); TopoTriangle t2 = model.AddTriangle(new TopoTriangle(model, v1, v2, v6)); if (!t1.Intersects(t2)) { faildTests++; Console.WriteLine("Failed test:TestInplaneInsideSameEdgeIntersects"); } }
public List<TopoModel> SplitIntoSurfaces() { CountShells(); foreach (TopoTriangle tri in triangles) tri.algHelper = tri.shell; List<TopoModel> models = new List<TopoModel>(); Dictionary<int, TopoModel> modelMap = new Dictionary<int, TopoModel>(); foreach (TopoTriangle tri in triangles) { int shell = tri.algHelper; if (modelMap.ContainsKey(shell)) { RHVector3 v1 = tri.vertices[0].pos; RHVector3 v2 = tri.vertices[1].pos; RHVector3 v3 = tri.vertices[2].pos; RHVector3 n = tri.normal; modelMap[shell].addTriangle(v1.x, v1.y, v1.z, v2.x, v2.y, v2.z, v3.x, v3.y, v3.z, n.x, n.y, n.z); } else { List<TopoTriangleDistance> intersections = new List<TopoTriangleDistance>(); RHVector3 lineStart = tri.Center; RHVector3 lineDirection = tri.normal; double delta; foreach (TopoTriangle test in triangles) { if(test.IntersectsLine(lineStart, lineDirection, out delta)) { intersections.Add(new TopoTriangleDistance(delta,test)); } } intersections.Sort(); Stack<TopoTriangleDistance> tdStack = new Stack<TopoTriangleDistance>(); foreach (TopoTriangleDistance td in intersections) { if (td.triangle == tri) { TopoModel m = null; if ((tdStack.Count & 2) == 0) { m = new TopoModel(); models.Add(m); modelMap.Add(shell, m); } else { int trueShell = tdStack.ElementAt(tdStack.Count-1).triangle.algHelper; foreach (TopoTriangle t in triangles) { if (t.algHelper == shell) t.algHelper = trueShell; } if (modelMap.ContainsKey(trueShell)) m = modelMap[trueShell]; else { m = new TopoModel(); models.Add(m); modelMap.Add(shell, m); } } RHVector3 v1 = tri.vertices[0].pos; RHVector3 v2 = tri.vertices[1].pos; RHVector3 v3 = tri.vertices[2].pos; RHVector3 n = tri.normal; m.addTriangle(v1.x, v1.y, v1.z, v2.x, v2.y, v2.z, v3.x, v3.y, v3.z, n.x, n.y, n.z); break; } else if (tdStack.Count > 0 && tdStack.Peek().triangle.algHelper == td.triangle.algHelper) { tdStack.Pop(); } else { tdStack.Push(td); } } } } foreach (TopoModel m in models) { m.Analyse(); } return models; }
public void Merge(TopoModel model, Matrix4 trans) { int nOld = vertices.Count; int i = 0; List<TopoVertex> vcopy = new List<TopoVertex>(model.vertices.Count); foreach (TopoVertex v in model.vertices) { v.id = i++; TopoVertex newVert = new TopoVertex(v.id, v.pos, trans); addVertex(newVert); vcopy.Add(newVert); } foreach (TopoTriangle t in model.triangles) { TopoTriangle triangle = new TopoTriangle(this, vcopy[t.vertices[0].id], vcopy[t.vertices[1].id], vcopy[t.vertices[2].id]); triangle.RecomputeNormal(); triangles.Add(triangle); } RemoveUnusedDatastructures(); intersectionsUpToDate = false; }
private void saveComposition(string filename) { TopoModel model = new TopoModel(); foreach (PrintModel stl in ListObjects(false)) { stl.UpdateMatrix(); model.Merge(stl.ActiveModel, stl.trans); } if (filename.EndsWith(".obj") || filename.EndsWith(".OBJ")) model.exportObj(filename,true); else model.exportSTL(filename, writeSTLBinary); Slicer.lastBox.Clear(); Slicer.lastBox.Add(model.boundingBox); }