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 * =============================================================================
71 public class element {
72 coordinate coordinates[];
74 coordinate circumCenter;
79 coordinate midpoints[]; /* midpoint of each edge */
80 double radii[]; /* half of edge length */
81 edge encroachedEdgePtr; /* opposite obtuse angle */
83 List_t neighborListPtr;
89 /* =============================================================================
91 * -- put smallest coordinate in position 0
92 * =============================================================================
94 void minimizeCoordinates() {
97 for (int i = 1; i < numCoordinate; i++) {
98 if (coordinate.coordinate_compare(coordinates[i], coordinates[minPosition]) < 0) {
103 while(minPosition != 0) {
104 coordinate tmp = coordinates[0];
105 for (int j = 0; j < (numCoordinate - 1); j++) {
106 coordinates[j] = coordinates[j+1];
108 coordinates[numCoordinate-1] = tmp;
114 /* =============================================================================
116 * -- Sets isSkinny to TRUE if the angle constraint is not met
117 * =============================================================================
119 void checkAngles (double angleConstraint) {
120 //double angleConstraint = global_angleConstraint;
123 yada.Assert(numCoordinate == 2 || numCoordinate == 3);
124 isReferenced = false;
126 encroachedEdgePtr = null;
128 if (numCoordinate == 3) {
130 for (i = 0; i < 3; i++) {
131 double angle = coordinate.coordinate_angle(coordinates[i],
132 coordinates[(i + 1) % 3],
133 coordinates[(i + 2) % 3]);
134 yada.Assert(angle > 0.0);
135 yada.Assert(angle < 180.0);
137 encroachedEdgePtr = edges[(i + 1) % 3];
139 if (angle < angleConstraint) {
142 if (angle < minAngle) {
146 yada.Assert(minAngle < 180.0);
151 /* =============================================================================
152 * calculateCircumCenter
154 * Given three points A(ax,ay), B(bx,by), C(cx,cy), circumcenter R(rx,ry):
157 * | by - ay (||b - a||)^2 |
159 * | cy - ay (||c - a||)^2 |
161 * rx = ax - -----------------------------
163 * | bx - ax by - ay |
165 * | cx - ax cy - ay |
169 * | bx - ax (||b - a||)^2 |
171 * | cx - ax (||c - a||)^2 |
173 * ry = ay + -----------------------------
175 * | bx - ax by - ay |
177 * | cx - ax cy - ay |
180 * =============================================================================
182 void calculateCircumCircle() {
183 coordinate circumCenterPtr = this.circumCenter;
185 yada.Assert(numCoordinate == 2 || numCoordinate == 3);
187 if (numCoordinate == 2) {
188 circumCenterPtr.x = (coordinates[0].x + coordinates[1].x) / 2.0;
189 circumCenterPtr.y = (coordinates[0].y + coordinates[1].y) / 2.0;
191 double ax = coordinates[0].x;
192 double ay = coordinates[0].y;
193 double bx = coordinates[1].x;
194 double by = coordinates[1].y;
195 double cx = coordinates[2].x;
196 double cy = coordinates[2].y;
197 double bxDelta = bx - ax;
198 double byDelta = by - ay;
199 double cxDelta = cx - ax;
200 double cyDelta = cy - ay;
201 double bDistance2 = (bxDelta * bxDelta) + (byDelta * byDelta);
202 double cDistance2 = (cxDelta * cxDelta) + (cyDelta * cyDelta);
203 double xNumerator = (byDelta * cDistance2) - (cyDelta * bDistance2);
204 double yNumerator = (bxDelta * cDistance2) - (cxDelta * bDistance2);
205 double denominator = 2 * ((bxDelta * cyDelta) - (cxDelta * byDelta));
206 double rx = ax - (xNumerator / denominator);
207 double ry = ay + (yNumerator / denominator);
208 yada.Assert(Math.fabs(denominator) > 2.2250738585072014e-308); /* make sure not colinear */
209 circumCenterPtr.x = rx;
210 circumCenterPtr.y = ry;
213 circumRadius = coordinate.coordinate_distance(circumCenterPtr,
218 /* =============================================================================
221 * Note: Makes pairPtr sorted; i.e., coordinate_compare(first, second) < 0
222 * =============================================================================
224 public void setEdge(int i) {
225 coordinate firstPtr = coordinates[i];
226 coordinate secondPtr = coordinates[(i + 1) % numCoordinate];
228 edge edgePtr = edges[i];
229 int cmp = coordinate.coordinate_compare(firstPtr, secondPtr);
230 yada.Assert(cmp != 0);
232 edgePtr.firstPtr = firstPtr;
233 edgePtr.secondPtr = secondPtr;
235 edgePtr.firstPtr = secondPtr;
236 edgePtr.secondPtr = firstPtr;
239 coordinate midpointPtr = midpoints[i];
240 midpointPtr.x = (firstPtr.x + secondPtr.x) / 2.0;
241 midpointPtr.y = (firstPtr.y + secondPtr.y) / 2.0;
243 radii[i] = coordinate.coordinate_distance(firstPtr, midpointPtr);
247 /* =============================================================================
249 * =============================================================================
251 void initEdges(coordinate[] coordinates, int numCoordinate) {
252 numEdge = ((numCoordinate * (numCoordinate - 1)) / 2);
254 for (int e = 0; e < numEdge; e++) {
260 /* =============================================================================
262 * =============================================================================
264 int element_compare (element aElementPtr, element bElementPtr) {
265 int aNumCoordinate = aElementPtr.numCoordinate;
266 int bNumCoordinate = bElementPtr.numCoordinate;
267 coordinate aCoordinates[] = aElementPtr.coordinates;
268 coordinate bCoordinates[] = bElementPtr.coordinates;
270 if (aNumCoordinate < bNumCoordinate) {
272 } else if (aNumCoordinate > bNumCoordinate) {
276 for (int i = 0; i < aNumCoordinate; i++) {
277 int compareCoordinate =
278 coordinate.coordinate_compare(aCoordinates[i], bCoordinates[i]);
279 if (compareCoordinate != 0) {
280 return compareCoordinate;
288 /* =============================================================================
289 * element_listCompare
292 * =============================================================================
294 int element_listCompare (Object aPtr, Object bPtr) {
295 element aElementPtr = (element)aPtr;
296 element bElementPtr = (element)bPtr;
298 return element_compare(aElementPtr, bElementPtr);
302 /* =============================================================================
306 * =============================================================================
308 int element_mapCompare(Object aPtr, Object bPtr) {
309 element aElementPtr = (element)(((edge)aPtr).firstPtr);
310 element bElementPtr = (element)(((edge)bPtr).firstPtr);
312 return element_compare(aElementPtr, bElementPtr);
316 /* =============================================================================
319 * Contains a copy of input arg 'coordinates'
320 * =============================================================================
323 double angleConstraint;
324 public element(coordinate[] coordinates, int numCoordinate, double angle) {
325 this.coordinates=new coordinate[3];
326 this.midpoints=new coordinate[3]; /* midpoint of each edge */
327 this.radii=new double[3]; /* half of edge length */
329 this.edges=new edge[3];
330 for (int i = 0; i < numCoordinate; i++) {
331 this.coordinates[i] = coordinates[i];
333 this.numCoordinate = numCoordinate;
334 minimizeCoordinates();
335 this.angleConstraint=angle;
337 calculateCircumCircle();
338 initEdges(coordinates, numCoordinate);
339 neighborListPtr = new List_t(0);//TMLIST_ALLOC(element_listCompare);
341 isReferenced = false;
345 /* =============================================================================
347 * =============================================================================
349 int element_getNumEdge() {
354 /* =============================================================================
357 * Returned edgePtr is sorted; i.e., coordinate_compare(first, second) < 0
358 * =============================================================================
360 edge element_getEdge(int i) {
361 if (i < 0 || i > numEdge)
367 /* =============================================================================
368 * element_compareEdge
369 * =============================================================================
371 static int compareEdge(edge aEdgePtr, edge bEdgePtr) {
372 int diffFirst = coordinate.coordinate_compare((coordinate)aEdgePtr.firstPtr,
373 (coordinate)bEdgePtr.firstPtr);
375 return ((diffFirst != 0) ?
377 (coordinate.coordinate_compare((coordinate)aEdgePtr.secondPtr,
378 (coordinate)bEdgePtr.secondPtr)));
382 /* ============================================================================
383 * element_listCompareEdge
386 * ============================================================================
388 int element_listCompareEdge (Object aPtr, Object bPtr) {
389 edge aEdgePtr = (edge)(aPtr);
390 edge bEdgePtr = (edge)(bPtr);
392 return compareEdge(aEdgePtr, bEdgePtr);
396 /* =============================================================================
397 * element_mapCompareEdge
400 * =============================================================================
402 int element_mapCompareEdge (edge aPtr, edge bPtr) {
403 edge aEdgePtr = (edge)(aPtr.firstPtr);
404 edge bEdgePtr = (edge)(bPtr.firstPtr);
406 return compareEdge(aEdgePtr, bEdgePtr);
410 /* =============================================================================
411 * element_heapCompare
413 * For use in heap_t. Consider using minAngle instead of "do not care".
414 * =============================================================================
416 int element_heapCompare (Object aPtr, Object bPtr) {
417 element aElementPtr = (element)aPtr;
418 element bElementPtr = (element)bPtr;
420 if (aElementPtr.encroachedEdgePtr!=null) {
421 if (bElementPtr.encroachedEdgePtr!=null) {
422 return 0; /* do not care */
428 if (bElementPtr.encroachedEdgePtr!=null) {
432 return 0; /* do not care */
436 /* =============================================================================
437 * element_isInCircumCircle
438 * =============================================================================
440 boolean element_isInCircumCircle(coordinate coordinatePtr) {
441 double distance = coordinate.coordinate_distance(coordinatePtr, circumCenter);
442 return distance <= circumRadius;
446 /* =============================================================================
448 * =============================================================================
450 boolean isEncroached() {
451 return encroachedEdgePtr!=null;
455 /* =============================================================================
456 * element_setEncroached
457 * =============================================================================
459 void element_clearEncroached() {
460 encroachedEdgePtr = null;
464 /* =============================================================================
465 * element_getEncroachedPtr
466 * =============================================================================
468 edge element_getEncroachedPtr() {
469 return encroachedEdgePtr;
473 /* =============================================================================
475 * =============================================================================
477 boolean element_isSkinny() {
482 /* =============================================================================
484 * -- Does it need to be refined?
485 * =============================================================================
487 boolean element_isBad() {
488 return (isEncroached() || element_isSkinny());
492 /* =============================================================================
493 * TMelement_isReferenced
494 * -- Held by another data structure?
495 * =============================================================================
497 boolean element_isReferenced () {
502 /* =============================================================================
503 * TMelement_setIsReferenced
504 * =============================================================================
506 void element_setIsReferenced(boolean status) {
507 isReferenced= status;
511 /* =============================================================================
513 * -- Can we deallocate?
514 * =============================================================================
517 /* =============================================================================
518 * TMelement_isGarbage
519 * -- Can we deallocate?
520 * =============================================================================
522 public boolean element_isGarbage() {
528 /* =============================================================================
529 * TMelement_setIsGarbage
530 * =============================================================================
532 void element_setIsGarbage(boolean status) {
537 /* =============================================================================
538 * TMelement_addNeighbor
539 * =============================================================================
541 void element_addNeighbor(element neighborPtr) {
542 neighborListPtr.insert(neighborPtr);
546 /* =============================================================================
547 * element_getNeighborListPtr
548 * =============================================================================
550 List_t element_getNeighborListPtr () {
551 return neighborListPtr;
555 /* =============================================================================
556 * element_getCommonEdge
558 * Returns pointer to aElementPtr's shared edge
559 * =============================================================================
561 static edge element_getCommonEdge (element aElementPtr, element bElementPtr) {
562 edge aEdges[] = aElementPtr.edges;
563 edge bEdges[] = bElementPtr.edges;
564 int aNumEdge = aElementPtr.numEdge;
565 int bNumEdge = bElementPtr.numEdge;
567 for (int a = 0; a < aNumEdge; a++) {
568 edge aEdgePtr = aEdges[a];
569 for (int b = 0; b < bNumEdge; b++) {
570 edge bEdgePtr = bEdges[b];
571 if (compareEdge(aEdgePtr, bEdgePtr) == 0) {
581 /* =============================================================================
582 * element_getNewPoint
583 * -- Either the element is encroached or is skinny, so get the new point to add
584 * =============================================================================
586 coordinate element_getNewPoint() {
587 if (encroachedEdgePtr!=null) {
588 for (int e = 0; e < numEdge; e++) {
589 if (compareEdge(encroachedEdgePtr, edges[e]) == 0) {
599 /* =============================================================================
600 * element_checkAngles
602 * Return FALSE if minimum angle constraint not met
603 * =============================================================================
605 boolean checkAngles() {
606 // double angleConstraint = global_angleConstraint;
607 if (numCoordinate == 3) {
608 for (int i = 0; i < 3; i++) {
609 double angle = coordinate.coordinate_angle(coordinates[i],
610 coordinates[(i + 1) % 3],
611 coordinates[(i + 2) % 3]);
612 if (angle < angleConstraint) {
621 /* =============================================================================
623 * =============================================================================
625 void element_print() {
626 for (int c = 0; c < numCoordinate; c++) {
627 coordinates[c].coordinate_print();
628 System.out.println(" ");
633 /* =============================================================================
635 * =============================================================================
637 void element_printEdge (edge edgePtr) {
638 ((coordinate)edgePtr.firstPtr).coordinate_print();
639 System.out.println(" -> ");
640 ((coordinate)edgePtr.secondPtr).coordinate_print();
644 /* =============================================================================
645 * element_printAngles
646 * =============================================================================
648 void element_printAngles() {
649 if (numCoordinate == 3) {
650 for (int i = 0; i < 3; i++) {
651 double angle = coordinate.coordinate_angle(coordinates[i],
652 coordinates[(i + 1) % 3],
653 coordinates[(i + 2) % 3]);
654 System.out.println(angle);