1 /* =============================================================================
5 * =============================================================================
7 * Copyright (C) Stanford University, 2006. All Rights Reserved.
10 * =============================================================================
12 * For the license of bayes/sort.h and bayes/sort.c, please see the header
15 * ------------------------------------------------------------------------
17 * For the license of kmeans, please see kmeans/LICENSE.kmeans
19 * ------------------------------------------------------------------------
21 * For the license of ssca2, please see ssca2/COPYRIGHT
23 * ------------------------------------------------------------------------
25 * For the license of lib/mt19937ar.c and lib/mt19937ar.h, please see the
26 * header of the files.
28 * ------------------------------------------------------------------------
30 * For the license of lib/rbtree.h and lib/rbtree.c, please see
31 * lib/LEGALNOTICE.rbtree and lib/LICENSE.rbtree
33 * ------------------------------------------------------------------------
35 * Unless otherwise noted, the following license applies to STAMP files:
37 * Copyright (c) 2007, Stanford University
38 * All rights reserved.
40 * Redistribution and use in source and binary forms, with or without
41 * modification, are permitted provided that the following conditions are
44 * * Redistributions of source code must retain the above copyright
45 * notice, this list of conditions and the following disclaimer.
47 * * Redistributions in binary form must reproduce the above copyright
48 * notice, this list of conditions and the following disclaimer in
49 * the documentation and/or other materials provided with the
52 * * Neither the name of Stanford University nor the names of its
53 * contributors may be used to endorse or promote products derived
54 * from this software without specific prior written permission.
56 * THIS SOFTWARE IS PROVIDED BY STANFORD UNIVERSITY ``AS IS'' AND ANY
57 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
58 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
59 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL STANFORD UNIVERSITY BE LIABLE
60 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
61 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
62 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
63 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
64 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
65 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
66 * THE POSSIBILITY OF SUCH DAMAGE.
68 * =============================================================================
72 element rootElementPtr;
73 Queue_t initBadQueuePtr;
75 RBTree boundarySetPtr;
77 /* =============================================================================
79 * =============================================================================
82 rootElementPtr = null;
83 initBadQueuePtr = new Queue_t(-1);
85 boundarySetPtr = new RBTree(null, element_listCompareEdge);
89 /* =============================================================================
91 * =============================================================================
93 void TMmesh_insert (element elementPtr, avltree edgeMapPtr) {
95 * Assuming fully connected graph, we just need to record one element.
96 * The root element is not needed for the actual refining, but rather
97 * for checking the validity of the final mesh.
99 if (rootElementPtr==null) {
100 rootElementPtr=elementPtr;
104 * Record existence of each of this element's edges
106 int numEdge = elementPtr.element_getNumEdge();
107 for (int i = 0; i < numEdge; i++) {
108 edge edgePtr = elementPtr.element_getEdge(i);
109 if (!MAP_CONTAINS(edgeMapPtr, edgePtr)) {
110 /* Record existance of this edge */
112 PMAP_INSERT(edgeMapPtr, edgePtr, elementPtr);
113 yada.Assert(isSuccess);
116 * Shared edge; update each element's neighborList
119 element sharerPtr = (element)MAP_FIND(edgeMapPtr, edgePtr);
120 yada.Assert(sharerPtr!=null); /* cannot be shared by >2 elements */
121 elementPtr.element_addNeighbor(sharerPtr);
122 sharerPtr.element_addNeighbor(elementPtr);
123 isSuccess = PMAP_REMOVE(edgeMapPtr, edgePtr);
124 yada.Assert(isSuccess);
125 isSuccess = PMAP_INSERT(edgeMapPtr,
127 null); /* marker to check >2 sharers */
128 yada.Assert(isSuccess);
133 * Check if really encroached
136 edge encroachedPtr = elementPtr.element_getEncroachedPtr();
137 if (encroachedPtr!=null) {
138 if (!boundarySetPtr.contains(encroachedPtr)) {
139 element_clearEncroached(elementPtr);
145 /* =============================================================================
147 * =============================================================================
149 public void TMmesh_remove(element elementPtr) {
150 yada.Assert(!elementPtr.element_isGarbage());
153 * If removing root, a new root is selected on the next mesh_insert, which
154 * always follows a call a mesh_remove.
156 if (rootElementPtr == elementPtr) {
161 * Remove from neighbors
164 List_t neighborListPtr = elementPtr.element_getNeighborListPtr();
165 TMLIST_ITER_RESET(it, neighborListPtr);
166 while (TMLIST_ITER_HASNEXT(it, neighborListPtr)) {
167 element neighborPtr = (element)TMLIST_ITER_NEXT(it, neighborListPtr);
168 List_t neighborNeighborListPtr = neighborPtr.element_getNeighborListPtr();
169 boolean status = neighborNeighborListPtr.remove(elementPtr);
173 elementPtr.element_isGarbage(true);
177 /* =============================================================================
178 * TMmesh_insertBoundary
179 * =============================================================================
181 boolean TMmesh_insertBoundary(edge boundaryPtr) {
182 return boundarySetPtr.insert(boundaryPtr,null);
186 /* =============================================================================
187 * TMmesh_removeBoundary
188 * =============================================================================
190 boolean TMmesh_removeBoundary(edge boundaryPtr) {
191 return boundarySetPtr.remove(boundaryPtr);
195 /* =============================================================================
197 * =============================================================================
199 static void createElement (coordinate coordinates,
201 avltree edgeMapPtr) {
202 element elementPtr = new element(coordinates, numCoordinate);
203 yada.Assert(elementPtr!=null);
205 if (numCoordinate == 2) {
206 edge boundaryPtr = elementPtr.element_getEdge(0);
207 boolean status = boundarySetPtr.insert(boundaryPtr, null);
211 mesh_insert(elementPtr, edgeMapPtr);
213 if (elementPtr.element_isBad()) {
214 boolean status = initBadQueuePtr.queue_push(elementPtr);
220 /* =============================================================================
223 * Returns number of elements read from file
225 * Refer to http://www.cs.cmu.edu/~quake/triangle.html for file formats.
226 * =============================================================================
228 int mesh_read(String fileNamePrefix) {
230 coordinate coordinates;
231 char fileName[]=new char[256];
232 int fileNameSize = sizeof(fileName) / sizeof(fileName[0]);
233 char inputBuff[]=new char[256];
234 int inputBuffSize = sizeof(inputBuff) / sizeof(inputBuff[0]);
241 avltree edgeMapPtr = new avltree(0);
246 snprintf(fileName, fileNameSize, "%s.node", fileNamePrefix);
247 inputFile = fopen(fileName, "r");
248 yada.Assert(inputFile);
249 fgets(inputBuff, inputBuffSize, inputFile);
250 sscanf(inputBuff, "%li %li", numEntry, numDimension);
251 yada.Assert(numDimension == 2); /* must be 2-D */
252 numCoordinate = numEntry + 1; /* numbering can start from 1 */
253 coordinates = new coordinate[numCoordinate];
254 for (i = 0; i < numEntry; i++) {
258 if (!fgets(inputBuff, inputBuffSize, inputFile)) {
261 if (inputBuff[0] == '#') {
262 continue; /* TODO: handle comments correctly */
264 sscanf(inputBuff, "%li %lf %lf", id, x, y);
265 coordinates[id].x = x;
266 coordinates[id].y = y;
268 yada.Assert(i == numEntry);
272 * Read .poly file, which contains boundary segments
274 snprintf(fileName, fileNameSize, "%s.poly", fileNamePrefix);
275 inputFile = fopen(fileName, "r");
276 yada.Assert(inputFile);
277 fgets(inputBuff, inputBuffSize, inputFile);
278 sscanf(inputBuff, "%li %li", numEntry, numDimension);
279 yada.Assert(numEntry == 0); /* .node file used for vertices */
280 yada.Assert(numDimension == 2); /* must be edge */
281 fgets(inputBuff, inputBuffSize, inputFile);
282 sscanf(inputBuff, "%li", numEntry);
283 for (i = 0; i < numEntry; i++) {
287 coordinate insertCoordinates=new coordinate[2];
288 if (!fgets(inputBuff, inputBuffSize, inputFile)) {
291 if (inputBuff[0] == '#') {
292 continue; /* TODO: handle comments correctly */
294 sscanf(inputBuff, "%li %li %li", id, a, b);
295 yada.Assert(a >= 0 && a < numCoordinate);
296 yada.Assert(b >= 0 && b < numCoordinate);
297 insertCoordinates[0] = coordinates[a];
298 insertCoordinates[1] = coordinates[b];
299 createElement(meshPtr, insertCoordinates, 2, edgeMapPtr);
301 yada.Assert(i == numEntry);
302 numElement += numEntry;
306 * Read .ele file, which contains triangles
308 snprintf(fileName, fileNameSize, "%s.ele", fileNamePrefix);
309 inputFile = fopen(fileName, "r");
310 yada.Assert(inputFile);
311 fgets(inputBuff, inputBuffSize, inputFile);
312 sscanf(inputBuff, "%li %li", numEntry, numDimension);
313 yada.Assert(numDimension == 3); /* must be triangle */
314 for (i = 0; i < numEntry; i++) {
319 coordinate insertCoordinates[]=new coordinate[3];
320 if (!fgets(inputBuff, inputBuffSize, inputFile)) {
323 if (inputBuff[0] == '#') {
324 continue; /* TODO: handle comments correctly */
326 sscanf(inputBuff, "%li %li %li %li", id, a, b, c);
327 yada.Assert(a >= 0 && a < numCoordinate);
328 yada.Assert(b >= 0 && b < numCoordinate);
329 yada.Assert(c >= 0 && c < numCoordinate);
330 insertCoordinates[0] = coordinates[a];
331 insertCoordinates[1] = coordinates[b];
332 insertCoordinates[2] = coordinates[c];
333 createElement(meshPtr, insertCoordinates, 3, edgeMapPtr);
335 yada.Assert(i == numEntry);
336 numElement += numEntry;
340 MAP_FREE(edgeMapPtr);
346 /* =============================================================================
348 * -- Returns NULL if none
349 * =============================================================================
351 element mesh_getBad() {
352 return (element)queue_pop(initBadQueuePtr);
356 /* =============================================================================
358 * =============================================================================
360 void mesh_shuffleBad (Random randomPtr) {
361 queue_shuffle(initBadQueuePtr, randomPtr);
365 /* =============================================================================
367 * =============================================================================
369 boolean mesh_check(int expectedNumElement) {
370 int numBadTriangle = 0;
371 int numFalseNeighbor = 0;
374 System.out.println("Checking final mesh:");
376 Queue_t searchQueuePtr = new Queue_t(-1);
377 avltree visitedMapPtr = new avltree(1);
380 * Do breadth-first search starting from rootElementPtr
382 yada.Assert(rootElementPtr!=null);
383 searchQueuePtr.queue_push(rootElementPtr);
384 while (!searchQueuePtr.queue_isEmpty()) {
386 List_t neighborListPtr;
388 element currentElementPtr = (element)queue_pop(searchQueuePtr);
389 if (visitedMapPtr.contains(currentElementPtr)) {
392 boolean isSuccess = visitedMapPtr.insert(currentElementPtr, null);
393 yada.Assert(isSuccess);
394 if (!currentElementPtr.checkAngles()) {
397 neighborListPtr = currentElementPtr.element_getNeighborListPtr();
399 list_iter_reset(it, neighborListPtr);
400 while (list_iter_hasNext(it, neighborListPtr)) {
401 element neighborElementPtr =
402 (element)list_iter_next(it, neighborListPtr);
404 * Continue breadth-first search
406 if (!visitedMapPtr.contains(neighborElementPtr)) {
407 boolean isSuccess = searchQueuePtr.queue_push(neighborElementPtr);
408 yada.Assert(isSuccess);
410 } /* for each neighbor */
414 } /* breadth-first search */
416 System.out.println("Number of elements = "+ numElement);
417 System.out.println("Number of bad triangles = "+ numBadTriangle);
419 return (!(numBadTriangle > 0 ||
420 numFalseNeighbor > 0 ||
421 numElement != expectedNumElement));