public void GetValleyFacePairBasicInfo(CMesh cm) { Mesh m = cm.mesh; List <Tuple <double, double> > face_heignt_pairs = new List <Tuple <double, double> >(); List <double> edge_length_between_face_pairs = new List <double>(); m.FaceNormals.ComputeFaceNormals(); MeshVertexList vert = m.Vertices; for (int e_ind = 0; e_ind < cm.valley_edges.Count; e_ind++) { // Register indices IndexPair edge_ind = cm.valley_edges[e_ind]; int u = edge_ind.I; int v = edge_ind.J; IndexPair face_ind = cm.valley_face_pairs[e_ind]; int P = face_ind.I; int Q = face_ind.J; MeshFace face_P = m.Faces[P]; MeshFace face_Q = m.Faces[Q]; int p = 0; int q = 0; for (int i = 0; i < 3; i++) { if (!edge_ind.Contains(face_P[i])) { p = face_P[i]; } if (!edge_ind.Contains(face_Q[i])) { q = face_Q[i]; } } /// Compute h_P & cot_Pu Vector3d vec_up = vert[p] - vert[u]; Vector3d vec_uv = vert[v] - vert[u]; double sin_Pu = (Vector3d.CrossProduct(vec_up, vec_uv) / (vec_up.Length * vec_uv.Length)).Length; double len_up = (vec_up - vec_uv).Length; double h_P = len_up * sin_Pu; /// Compute h_Q & cot_Qu Vector3d vec_uq = vert[q] - vert[u]; double sin_Qu = (Vector3d.CrossProduct(vec_uq, vec_uv) / (vec_uq.Length * vec_uv.Length)).Length; double len_uq = (vec_uq - vec_uv).Length; double h_Q = len_uq * sin_Qu; // Compute len_uv double len_uv = vec_uv.Length; // Set Tuple<h_P, h_Q> Tuple <double, double> face_height_pair = new Tuple <double, double>(h_P, h_Q); face_heignt_pairs.Add(face_height_pair); edge_length_between_face_pairs.Add(len_uv); } cm.valley_face_height_pairs = face_heignt_pairs; cm.length_of_valley_diagonal_edges = edge_length_between_face_pairs; }
public override CRS Jacobian(CMesh cm) { // 等長拘束をかける辺の数取得 int n = equal_fold_angle_edge_id.Count; List <double> var = new List <double>(); List <int> rind = new List <int>(); List <int> cind = new List <int>(); List <Point3d> verts = new List <Point3d>(cm.mesh.Vertices.ToPoint3dArray()); Mesh m = cm.mesh; m.FaceNormals.ComputeFaceNormals(); // メッシュの TopologyEdges 取得 MeshTopologyEdgeList topo_edges = m.TopologyEdges; for (int i = 0; i < n; i++) { // Register indices int edge_index = equal_fold_angle_edge_id[i]; IndexPair edge_ind = topo_edges.GetTopologyVertices(edge_index); int u = edge_ind.I; int v = edge_ind.J; IndexPair face_ind = cm.face_pairs[edge_index]; int P = face_ind[0]; int Q = face_ind[1]; MeshFace face_P = m.Faces[P]; MeshFace face_Q = m.Faces[Q]; int p = 0; int q = 0; for (int j = 0; j < 3; j++) { if (!edge_ind.Contains(face_P[j])) { p = face_P[j]; } if (!edge_ind.Contains(face_Q[j])) { q = face_Q[j]; } } /// Compute normals Vector3d normal_P = m.FaceNormals[P]; Vector3d normal_Q = m.FaceNormals[Q]; /// Compute h_P & cot_Pu Vector3d vec_up = verts[p] - verts[u]; Vector3d vec_uv = verts[v] - verts[u]; double sin_Pu = (Vector3d.CrossProduct(vec_up, vec_uv) / (vec_up.Length * vec_uv.Length)).Length; double cos_Pu = (vec_up * vec_uv) / (vec_up.Length * vec_uv.Length); double cot_Pu = cos_Pu / sin_Pu; double len_up = vec_up.Length; double h_P = len_up * sin_Pu; /// Compute cot_Pv Vector3d vec_vp = verts[p] - verts[v]; Vector3d vec_vu = verts[u] - verts[v]; double sin_Pv = (Vector3d.CrossProduct(vec_vp, vec_vu) / (vec_vp.Length * vec_vu.Length)).Length; double cos_Pv = (vec_vp * vec_vu) / (vec_vp.Length * vec_vu.Length); double cot_Pv = cos_Pv / sin_Pv; /// Compute h_Q & cot_Qu Vector3d vec_uq = verts[q] - verts[u]; double sin_Qu = (Vector3d.CrossProduct(vec_uq, vec_uv) / (vec_uq.Length * vec_uv.Length)).Length; double cos_Qu = (vec_uq * vec_uv) / (vec_uq.Length * vec_uv.Length); double cot_Qu = cos_Qu / sin_Qu; double len_uq = vec_uq.Length; double h_Q = len_uq * sin_Qu; /// Compute cot_Qv Vector3d vec_vq = verts[q] - verts[v]; double sin_Qv = (Vector3d.CrossProduct(vec_vq, vec_vu) / (vec_vq.Length * vec_vu.Length)).Length; double cos_Qv = vec_vq * vec_vu / (vec_vq.Length * vec_vu.Length); double cot_Qv = cos_Qv / sin_Qv; List <double> normal_P_list = new List <double>(); List <double> normal_Q_list = new List <double>(); normal_P_list.Add(normal_P.X); normal_P_list.Add(normal_P.Y); normal_P_list.Add(normal_P.Z); normal_Q_list.Add(normal_Q.X); normal_Q_list.Add(normal_Q.Y); normal_Q_list.Add(normal_Q.Z); /// Compute coefficients double co_pv = (-1 * cot_Pv) / (cot_Pu + cot_Pv); double co_qv = (-1 * cot_Qv) / (cot_Qu + cot_Qv); double co_pu = (-1 * cot_Pu) / (cot_Pu + cot_Pv); double co_qu = (-1 * cot_Qu) / (cot_Qu + cot_Qv); /// Compute Jacobian for (int v_ind = 0; v_ind < verts.Count; v_ind++) { if (v_ind == p) { for (int x = 0; x < 3; x++) { var.Add((normal_P_list[x] / (h_P))); cind.Add(3 * v_ind + x); rind.Add(i); } } if (v_ind == q) { for (int x = 0; x < 3; x++) { var.Add((normal_Q_list[x] / (h_Q))); cind.Add(3 * v_ind + x); rind.Add(i); } } if (v_ind == u) { for (int x = 0; x < 3; x++) { var.Add(((co_pv * (normal_P_list[x] / h_P) + co_qv * (normal_Q_list[x] / h_Q)))); cind.Add(3 * v_ind + x); rind.Add(i); } } if (v_ind == v) { for (int x = 0; x < 3; x++) { var.Add(((co_pu * (normal_P_list[x] / h_P) + co_qu * (normal_Q_list[x] / h_Q)))); cind.Add(3 * v_ind + x); rind.Add(i); } } } } CRS Jaco = new CRS(var, rind, cind, n, verts.Count * 3); return(Jaco); }
public override Vec Error(CMesh cm) { Mesh m = cm.mesh; List <Point3d> verts = new List <Point3d>(m.Vertices.ToPoint3dArray()); List <double> foldang = new List <double>(); // 等長拘束をかける辺の数取得 int n = equal_fold_angle_edge_id.Count; // メッシュの TopologyEdges 取得 MeshTopologyEdgeList topo_edges = m.TopologyEdges; // 法線方向計算 m.FaceNormals.ComputeFaceNormals(); for (int i = 0; i < n; i++) { double foldang_i = 0; /// Register indices int edge_index = equal_fold_angle_edge_id[i]; IndexPair edge_ind = topo_edges.GetTopologyVertices(edge_index); int u = edge_ind.I; int v = edge_ind.J; IndexPair face_ind = cm.face_pairs[edge_index]; int P = face_ind[0]; int Q = face_ind[1]; MeshFace face_P = m.Faces[P]; MeshFace face_Q = m.Faces[Q]; int p = 0; int q = 0; for (int j = 0; j < 3; j++) { if (!edge_ind.Contains(face_P[j])) { p = face_P[j]; } if (!edge_ind.Contains(face_Q[j])) { q = face_Q[j]; } } /// Compute normals Vector3d normal_P = m.FaceNormals[P]; Vector3d normal_Q = m.FaceNormals[Q]; /// cos(foldang_e) = n_i * n_j double cos_foldang_e = normal_P * normal_Q; /// sin(foldang_e) = n_i × n_j Vector3d vec_e = verts[u] - verts[v]; vec_e.Unitize(); double sin_foldang_e = Vector3d.CrossProduct(normal_P, normal_Q) * vec_e; if (sin_foldang_e >= 0) { if (cos_foldang_e >= 1.0) { foldang_i = 0; } else if (cos_foldang_e <= -1.0) { foldang_i = Math.PI; } else { foldang_i = Math.Acos(cos_foldang_e); } } else { if (cos_foldang_e >= 1.0) { foldang_i = 0; } else if (cos_foldang_e <= -1.0) { foldang_i = -Math.PI; } else { foldang_i = -Math.Acos(cos_foldang_e); } } if (is_set_angle) { foldang_i -= fold_angle; } foldang.Add(foldang_i); } Vec ans = new Vec(foldang); return(ans); }