private void Form1_Load(object sender, EventArgs e) { Mesh M = new Mesh(); FiniteSolverMethod Method = FiniteSolverMethod.EnergyModel; //Interop with catia to retrive exported stlPath string StlPath = CAT.SaveSurfaceAndFixedPoints(ref M.FixedPoints, ref M.oVecPlane); //Parse stlFile to Vertice and triangle matrix STLReader.STLRead(StlPath, ref M); if (M.Vertices.Count == 0 || M.TrianglesVertices.Count == 0) { MessageBox.Show("Não foi encontrada nenhuma informação na superficie exportada. Tente outra vez."); Environment.Exit(0); } //Detection of the most apropriated verticePoints M.ComputeFixedPoints(); //Calculation of Plane of flattening M.ComputePlaneofFlattening(); //Solve using the edge to edge interpretation of the article Vector<double> X = EdgeToEdgeSolver.Solve(M); //Print Result of triangles in CATIA; CAT.PrintTriangles(X, M); Vector<double> Y = Vector<double>.Build.Dense(X.Count); if (Method== FiniteSolverMethod.NewtonRaphson) { //Try to calculate de displacement vector based on finite-element analysis using NewtonRapson Method //ATENTION - IS NOT COMPLETE/WITH ERRORS! Y =NewtonRaphsonFiniteSolver.solve(X, M); } else if (Method == FiniteSolverMethod.EnergyModel) { //Try to calculate de displacement vector based on energy analysis //ATENTION - IS NOT COMPLETE/WITH ERRORS! Y = EnergyModelFiniteSolver.solve(X, M); } CAT.PrintTriangles(Y, M); Application.Exit(); }
internal void PrintTriangles(Vector<double> X2, Mesh M) { PrintTriangles(X2, M.TrianglesVertices, M.oRoot, M.vDir1, M.vDir2, M.OneIndFix, M.OnePointFix); }
public static Vector<double> solve( List<double[]> Vertices, List<int[]> TrianglesVertices, List<double[]> FacetNormals, Vector<double> X, Point3D oRoot, UnitVector3D vDir1, UnitVector3D vDir2, Mesh M) { //Method from article -Wang,Smith. Surface flattening based on energy model. Computer-Aided Design (2002) 823-833 //PseudoCode //Input: P - Set of nodes, in the initial position and N is the number of nodes //Output: the final positions of P with E(o) minimized // FOR i = 1 TO n // mi = p / 3 Sum(Ak), where Ak is the area // WHILE (Relative Area difference Es > Permissible accuracy or Relative edge length difference Ec > Permissible accuracy) // AND Variation of E(o) > Permissible percentage € // AND the number of iterations < Permissible number N // FOR i = 1 TO n // Compute Tensile force of Node Pi: Fi = Sum(C * (Dist(PiPj) - Dist(QiQj)))nij where(P - 2D - Q - 3D nij - Vector Pi to Pj) // Compute new position of Pi qi = qi + dtqi. + dt ^ 2 / 2 qi..where qi.= qi.+ dtqi..and qi..= Fi / mi // Compute Penalty force and aplly to Fpi // Compute new position of Pi qi = qi + dtqi. + dt ^ 2 / 2 qi..where qi.= qi.+ dtqi..and qi..= Fpi / mi // Compute new Es= Sum(TotalAreaNow - TotalAreaBefore) / TotalAreaNow // Compute new Ec= Sum(TotalLenghtNow - TotalLenghtBefore) / TotalLenghtNow // Compute new E(o)Sum(E(pi)) where E(pi) = 0.5 * Sum(C * (Dist(PiPj) - Dist(QiQj))) ^ 2 double[] Mass = new double [Vertices.Count]; int[] MassCounter = new int[Vertices.Count]; double Permissible = 0.00000001; Vector<double> Fi = Vector<double>.Build.Dense(2); List<Vector<double>> dqi = new List<Vector<double>>(); List<Vector<double>> qi = new List<Vector<double>>(); double LastEc = 0, Ec = 0; double LastEs = 0, Es = 0; double LastEo = 0, Eo = 0; double C = 0.5; double ro = 1; double t = 0.01; int N = 100; int Iteration = 0; double Total = 0; double LastTotal = 0; foreach (int[] tri in TrianglesVertices) { double A = getArea(Vertices[tri[0]], Vertices[tri[1]], Vertices[tri[2]]); double P = getPerimeter(Vertices[tri[0]], Vertices[tri[1]], Vertices[tri[2]]); Mass[tri[0]] += ((double)1 / (double)3) * A * ro; Mass[tri[1]] += ((double)1 / (double)3) * A * ro; Mass[tri[2]] += ((double)1 / (double)3) * A * ro; MassCounter[tri[0]] += 1; MassCounter[tri[1]] += 1; MassCounter[tri[2]] += 1; LastEc += A; LastEs += P; } for (int i = 0; i < Vertices.Count; i++) { Mass[i] = Mass[i] / MassCounter[i]; qi.Add(Vector<double>.Build.DenseOfArray(new double[] { X[i * 2], X[i * 2 + 1], 0 })); dqi.Add(Vector<double>.Build.DenseOfArray(new double[] { 0, 0, 0 })); } do { Iteration += 1; LastEo = Eo; Eo = 0; Total = 0; for (int i = 0; i < Vertices.Count; i++) { Point3D Pi = new Point3D(qi[i][0], qi[i][1], qi[i][2]); Point3D Qi = new Point3D(Vertices[i][0], Vertices[i][1], Vertices[i][2]); Fi = Vector<double>.Build.Dense(3); for (int j = i+1; j < Vertices.Count; j++) { if (i == j) continue; Point3D Pj = new Point3D(qi[j][0], qi[j][1], qi[j][2]); Point3D Qj = new Point3D(Vertices[j][0], Vertices[j][1], Vertices[j][2]); UnitVector3D nij = new UnitVector3D((Pi.ToVector()- Pj.ToVector()).ToArray()); Fi += C * ((Pi.DistanceTo(Pj) - Qi.DistanceTo(Qj)) * nij).ToVector(); Eo += Math.Pow(C * ((Pi.DistanceTo(Pj) - Qi.DistanceTo(Qj))), 2); } Vector<double> ddqi = Fi / Mass[i]; Console.WriteLine(Fi); dqi[i] += t * ddqi; qi[i] += dqi[i] * t + 0.5 * Math.Pow(t, 2) * ddqi; Total += Math.Abs(qi[i][0] - X[i * 2]); Total += Math.Abs(qi[i][1] - X[i * 2] + 1); } Console.WriteLine(Total- LastTotal); LastTotal = Total; LastEc = Ec; Ec = 0; LastEs = Es; Es = 0; foreach (int[] tri in TrianglesVertices) { double A = getArea(Vertices[tri[0]], Vertices[tri[1]], Vertices[tri[2]]); double P = getPerimeter(Vertices[tri[0]], Vertices[tri[1]], Vertices[tri[2]]); Ec += A; Es += P; } if (((Ec - LastEc) / Ec < Permissible || (Es - LastEs) / Es < Permissible) && (Eo - LastEo) / Eo < Permissible && Iteration > N) break; } while (true); Vector<double> XResult = Vector<double>.Build.DenseOfArray(X.ToArray()); for (int i = 0; i < Vertices.Count; i++) { //Console.WriteLine(qi[i][0] - X[i * 2]); Total += Math.Abs(qi[i][0] - X[i * 2]); XResult[i * 2] = qi[i][0]; //Console.WriteLine(qi[i][1] - X[i * 2+1]); Total += Math.Abs(qi[i][1] - X[i * 2]+1); XResult[i * 2+1] = qi[i][1]; } Console.WriteLine(Total); return XResult; }
internal static Vector<double> solve(Vector<double> X, Mesh M) { return solve(M.Vertices, M.TrianglesVertices, M.FacetNormals, X, M.oRoot, M.vDir1, M.vDir2,M); }
internal static void STLRead(string stlPath, ref Mesh M) { STLRead(stlPath, ref M.Vertices, ref M.TrianglesVertices, ref M.TrianglesEdges, ref M.Edges, ref M.FacetNormals); }
internal static Vector<double> Solve(Mesh M) { return Solve(M.Vertices, M.TrianglesEdges, M.Edges, M.IndiceOfFixedPoints, M.oRoot, M.vDir1, M.vDir2); }