public override Vec Error(CMesh cm) { Mesh m = cm.mesh; List <double> err = new List <double>(); m.Normals.ComputeNormals(); var topo = m.TopologyVertices; topo.SortEdges(); List <bool> isNaked = new List <bool>(m.GetNakedEdgePointStatus()); List <int> internalVertices = new List <int>(); for (int i = 0; i < topo.Count; i++) { if (!isNaked[i]) { internalVertices.Add(i); } } //各内部頂点について for (int r = 0; r < internalVertices.Count; r++) { //内部頂点のインデックス、位置ベクトル int index_center = internalVertices[r]; Vector3d center = new Vector3d(topo[index_center]); //接続点のインデックス、位置ベクトル List <int> index_neighbors = new List <int>(); List <Vector3d> neighbors = new List <Vector3d>(); index_neighbors.AddRange(topo.ConnectedTopologyVertices(index_center)); //エッジベクトル List <Vector3d> vecs = new List <Vector3d>(); double sum = 0; int n = index_neighbors.Count; //三角形分割の区別 List <int> connected_edges = new List <int>(topo.ConnectedEdges(index_center)); List <bool> is_corrects = new List <bool>(); for (int i = 0; i < n; i++) { bool is_correct = m.TopologyEdges.GetTopologyVertices(connected_edges[i]).Contains(index_neighbors[i]); is_corrects.Add(is_correct); } List <double> signs = new List <double>(); for (int i = -1; i < n - 1; i++) { if (i == -1) { signs.Add(1); } else if (cm.edgeInfo[connected_edges[i]] != 'T') { signs.Add(-signs[i]); } else { signs.Add(signs[i]); } } //位置ベクトル取得 foreach (int index_neighbor in index_neighbors) { neighbors.Add(new Vector3d(topo[index_neighbor])); } //方向ベクトル取得 foreach (Vector3d neighbor in neighbors) { Vector3d temp = neighbor - center; vecs.Add(temp); } for (int i = 0; i < n; i++) { if (i == 0) { sum += signs[i] * Vector3d.VectorAngle(vecs[n - 1], vecs[0]); } else { sum += signs[i] * Vector3d.VectorAngle(vecs[i - 1], vecs[i]); } } err.Add((double)sum); } Vec ans = new Vec(err); return(ans); }
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); }