1
1
package micycle .pgs .commons ;
2
2
3
- import java .util .Collection ;
4
3
import java .util .HashMap ;
5
- import java .util .HashSet ;
4
+ import java .util .List ;
6
5
import java .util .Map ;
7
6
import java .util .Map .Entry ;
8
7
import java .util .Objects ;
9
- import java .util .Set ;
10
8
import java .util .TreeSet ;
11
9
import java .util .stream .Collectors ;
12
10
import org .jgrapht .Graph ;
13
11
import org .jgrapht .Graphs ;
14
- import org .jgrapht .alg .util .NeighborCache ;
15
12
import org .jgrapht .alg .util .Pair ;
16
13
import org .jgrapht .graph .DefaultEdge ;
17
14
import org .jgrapht .graph .SimpleGraph ;
@@ -44,14 +41,13 @@ private AreaMerge() {
44
41
*/
45
42
public static PShape areaMerge (PShape mesh , double areaThreshold ) {
46
43
SimpleGraph <PShape , DefaultEdge > graph = PGS_Conversion .toDualGraph (mesh );
47
- NeighborCache <PShape , DefaultEdge > neighborCache = new NeighborCache <>(graph );
48
44
49
45
Map <PShape , FaceGroup > initialFaceMap = new HashMap <>(graph .vertexSet ().size ());
50
46
SimpleGraph <FaceGroup , DefaultEdge > groupsGraph = new SimpleGraph <>(DefaultEdge .class );
51
47
TreeSet <FaceGroup > smallGroups = new TreeSet <>(); // groups having area < areaThreshold
52
48
for (PShape face : graph .vertexSet ()) {
53
49
double area = PGS_ShapePredicates .area (face );
54
- FaceGroup f = new FaceGroup (face , area , neighborCache );
50
+ FaceGroup f = new FaceGroup (face , area );
55
51
initialFaceMap .put (face , f );
56
52
groupsGraph .addVertex (f );
57
53
@@ -72,11 +68,13 @@ public static PShape areaMerge(PShape mesh, double areaThreshold) {
72
68
73
69
while (!smallGroups .isEmpty ()) {
74
70
final FaceGroup toMerge = smallGroups .pollFirst ();
75
- Collection <FaceGroup > neighbors = Graphs .neighborSetOf (groupsGraph , toMerge );
76
71
77
72
// find smallest neighbor of the toMerge face
78
- // FaceGroup smallestNeighbor = neighbors.stream().min((a, b) -> Double.compare(a.area, b.area)).orElse(null);
79
- FaceGroup smallestNeighbor = Graphs .neighborListOf (groupsGraph , toMerge ).get (0 );
73
+ List <FaceGroup > neighboringGroups = Graphs .neighborListOf (groupsGraph , toMerge );
74
+ // sort neighbors by area, pick the smallest. ensures algorithm is stable on the
75
+ // same input
76
+ FaceGroup smallestNeighbor = neighboringGroups .stream ().min ((a , b ) -> Double .compare (a .area , b .area )).orElse (null );
77
+ // FaceGroup smallestNeighbor = neighbors.get(0);
80
78
if (smallestNeighbor == null ) {
81
79
break ; // exit merging
82
80
}
@@ -86,10 +84,6 @@ public static PShape areaMerge(PShape mesh, double areaThreshold) {
86
84
87
85
if (smallestNeighbor .area > areaThreshold ) {
88
86
smallGroups .remove (smallestNeighbor );
89
- } else {
90
- // re-insert and order the new group
91
- // smallGroups.remove(smallestNeighbor);
92
- // smallGroups.add(smallestNeighbor);
93
87
}
94
88
}
95
89
@@ -141,13 +135,9 @@ static class FaceGroup implements Comparable<FaceGroup> {
141
135
private double area ;
142
136
/** A map of faces comprising this group and their respective areas. */
143
137
private Map <PShape , Double > faces ;
144
- private Set <PShape > neighborFaces ; // union of neighbors of each face - faces themselves
145
- private final NeighborCache <PShape , DefaultEdge > neighborCache ;
146
138
147
- FaceGroup (PShape initial , double area , NeighborCache < PShape , DefaultEdge > meshNeighborCache ) {
139
+ FaceGroup (PShape initial , double area ) {
148
140
this .faces = new HashMap <>();
149
- this .neighborFaces = new HashSet <>();
150
- this .neighborCache = meshNeighborCache ;
151
141
addFace (initial , area );
152
142
}
153
143
@@ -156,45 +146,20 @@ static class FaceGroup implements Comparable<FaceGroup> {
156
146
*/
157
147
public boolean addFace (PShape face , double area ) {
158
148
if (face == null ) {
159
- // System.err.println("Tried to add null face.");
160
149
return false ;
161
150
}
162
- // if (!faces.isEmpty() && !neighborFaces.contains(face)) {
163
- // System.err.println("Tried to add a face that is not a neighboring face of the group.");
164
- // return false;
165
- // }
166
151
if (!faces .containsKey (face )) {
167
152
faces .put (face , area );
168
153
this .area += area ;
169
- // recomputeNeighbors(face);
170
154
return true ;
171
155
}
172
156
return false ;
173
157
}
174
158
175
- private void recomputeNeighbors (PShape face ) {
176
- neighborFaces .addAll (neighborCache .neighborsOf (face ));
177
- /*
178
- * Now remove any of the group's own faces from the neighbours.
179
- */
180
- neighborFaces .removeAll (faces .keySet ());
181
- }
182
-
183
- private void recomputeNeighbors () {
184
- neighborFaces .clear ();
185
- for (PShape face : faces .keySet ()) {
186
- neighborFaces .addAll (neighborCache .neighborsOf (face ));
187
- }
188
- neighborFaces .removeAll (faces .keySet ());
189
- }
190
-
191
159
/**
192
160
* Merges another facegroup into this one.
193
161
*/
194
162
public boolean mergeWith (FaceGroup other ) {
195
- // if (!neighbors(other)) {
196
- // return false;
197
- // }
198
163
boolean changed = false ;
199
164
for (Entry <PShape , Double > faceEntry : other .faces .entrySet ()) {
200
165
changed = changed | addFace (faceEntry .getKey (), faceEntry .getValue ());
@@ -203,35 +168,6 @@ public boolean mergeWith(FaceGroup other) {
203
168
return changed ;
204
169
}
205
170
206
- /**
207
- * @return true if this and the other facegroup have no faces in common
208
- */
209
- public boolean disjoint (FaceGroup other ) {
210
- Set <PShape > myFaces = new HashSet <>(faces .keySet ());
211
- myFaces .retainAll (other .faces .keySet ());
212
- return myFaces .isEmpty ();
213
- }
214
-
215
- public boolean neighbors (PShape face ) {
216
- return neighborFaces .contains (face );
217
- }
218
-
219
- /**
220
- * @param facegroup
221
- * @return true if the groups are disjoint and neighborFaces each other
222
- */
223
- public boolean neighbors (FaceGroup facegroup ) {
224
- if (!disjoint (facegroup )) {
225
- return false ;
226
- }
227
- for (PShape face : facegroup .faces .keySet ()) {
228
- if (neighborFaces .contains (face )) {
229
- return true ;
230
- }
231
- }
232
- return false ;
233
- }
234
-
235
171
public boolean hasFace (PShape face ) {
236
172
return faces .keySet ().contains (face );
237
173
}
0 commit comments