IsOrientableManifoldWithBoundaries method
bool
IsOrientableManifoldWithBoundaries(
)
Implementation
bool IsOrientableManifoldWithBoundaries() {
final LinkedHashMap<Edge3, Object> incidenceE =
LinkedHashMap<Edge3, Object>();
bool addEdge(VM.Vector3 v1, VM.Vector3 v2, Object face) {
final Edge3 edge = Edge3(v1, v2);
final Object f = incidenceE.putIfAbsent(edge, () => face);
if (f != face) {
LogWarn("unexpected duplicate edge: ${edge}");
return true;
} else {
return false;
}
}
for (Face3 f3 in faces3) {
VM.Vector3 va = vertices[f3.a];
VM.Vector3 vb = vertices[f3.b];
VM.Vector3 vc = vertices[f3.c];
if (addEdge(va, vb, f3) | addEdge(vb, vc, f3) | addEdge(vc, va, f3)) {
return false;
}
}
for (Face4 f4 in faces4) {
VM.Vector3 va = vertices[f4.a];
VM.Vector3 vb = vertices[f4.b];
VM.Vector3 vc = vertices[f4.c];
VM.Vector3 vd = vertices[f4.d];
if (addEdge(va, vb, f4) |
addEdge(vb, vc, f4) |
addEdge(vc, va, f4) |
// same split as in GenerateFaceIndices()
addEdge(va, vc, f4) |
addEdge(vc, vd, f4) |
addEdge(vd, va, f4)) {
return false;
}
}
// check that each edge is incident to two faces with compatible orientation
for (Edge3 e in incidenceE.keys) {
Edge3 f = Edge3(e.v2, e.v1);
if (!incidenceE.containsKey(f)) {
LogWarn("unpaired edge ${e.v1}->${e.v2}");
return false;
}
}
// fan property
// print("build incidenceV from ${incidenceE.length} edges");
final LinkedHashMap<VM.Vector3, List<VM.Vector3>> incidenceV =
LinkedHashMap<VM.Vector3, List<VM.Vector3>>(hashCode: hashVector3);
for (Edge3 e in incidenceE.keys) {
incidenceV.putIfAbsent(e.v1, () => <VM.Vector3>[]).add(e.v2);
}
bool formsLoop(List<VM.Vector3> lst) {
for (int i = 0; i < lst.length; ++i) {
VM.Vector3 v1 = i == 0 ? lst.last : lst[i - 1];
// print("fan ${v1} ${lst}");
bool found = false;
for (int j = i; j < lst.length; ++j) {
VM.Vector3 v2 = lst[j];
if (incidenceE.containsKey(Edge3(v1, v2))) {
lst[j] = lst[i];
lst[i] = v2;
found = true;
break;
}
}
if (!found) {
return false;
}
}
return true;
}
//print ("check loops");
for (List<VM.Vector3> lst in incidenceV.values) {
if (!formsLoop(lst)) {
LogWarn("fan issues for ${lst}");
return false;
}
}
return true;
}