📄 earclip.java
字号:
/* * $RCSfile: EarClip.java,v $ * * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed, licensed or * intended for use in the design, construction, operation or * maintenance of any nuclear facility. * * $Revision: 1.4 $ * $Date: 2007/02/09 17:20:18 $ * $State: Exp $ */// ----------------------------------------------------------------------//// The reference to Fast Industrial Strength Triangulation (FIST) code// in this release by Sun Microsystems is related to Sun's rewrite of// an early version of FIST. FIST was originally created by Martin// Held and Joseph Mitchell at Stony Brook University and is// incorporated by Sun under an agreement with The Research Foundation// of SUNY (RFSUNY). The current version of FIST is available for// commercial use under a license agreement with RFSUNY on behalf of// the authors and Stony Brook University. Please contact the Office// of Technology Licensing at Stony Brook, phone 631-632-9009, for// licensing information.//// ----------------------------------------------------------------------package com.sun.j3d.utils.geometry;import java.io.*;import java.util.*;import javax.vecmath.*;class EarClip { /** * Classifies all the internal angles of the loop referenced by ind. * the following classification is used: * 0 ... if angle is 180 degrees * 1 ... if angle between 0 and 180 degrees * 2 ... if angle is 0 degrees * -1 ... if angle between 180 and 360 degrees * -2 ... if angle is 360 degrees */ static void classifyAngles(Triangulator triRef, int ind) { int ind0, ind1, ind2; int i0, i1, i2; int angle; ind1 = ind; i1 = triRef.fetchData(ind1); ind0 = triRef.fetchPrevData(ind1); i0 = triRef.fetchData(ind0); do { ind2 = triRef.fetchNextData(ind1); i2 = triRef.fetchData(ind2); angle = Numerics.isConvexAngle(triRef, i0, i1, i2, ind1); triRef.setAngle(ind1, angle); i0 = i1; i1 = i2; ind1 = ind2; } while (ind1 != ind); } static void classifyEars(Triangulator triRef, int ind) { int ind1; int i1; int[] ind0, ind2; double[] ratio; ind0 = new int[1]; ind2 = new int[1]; ratio = new double[1]; Heap.initHeap(triRef); ind1 = ind; i1 = triRef.fetchData(ind1); do { if ((triRef.getAngle(ind1) > 0) && isEar(triRef, ind1, ind0, ind2, ratio)) { Heap.dumpOnHeap(triRef, ratio[0], ind1, ind0[0], ind2[0]); } ind1 = triRef.fetchNextData(ind1); i1 = triRef.fetchData(ind1); } while (ind1 != ind); // Not using sorted_ear so don't have to do MakeHeap(); // MakeHeap(); // Heap.printHeapData(triRef); } /** * This function checks whether a diagonal is valid, that is, whether it is * locally within the polygon, and whether it does not intersect any other * segment of the polygon. also, some degenerate cases get a special * handling. */ static boolean isEar(Triangulator triRef, int ind2, int[] ind1, int[] ind3, double[] ratio) { int i0, i1, i2, i3, i4; int ind0, ind4; BBox bb; boolean convex, coneOk; i2 = triRef.fetchData(ind2); ind3[0] = triRef.fetchNextData(ind2); i3 = triRef.fetchData(ind3[0]); ind4 = triRef.fetchNextData(ind3[0]); i4 = triRef.fetchData(ind4); ind1[0] = triRef.fetchPrevData(ind2); i1 = triRef.fetchData(ind1[0]); ind0 = triRef.fetchPrevData(ind1[0]); i0 = triRef.fetchData(ind0); /* System.out.println("isEar : i0 " + i0 + " i1 " + i1 + " i2 " + i2 + " i3 " + i3 + " i4 " + i4); */ if ((i1 == i3) || (i1 == i2) || (i2 == i3) || (triRef.getAngle(ind2) == 2)) { // oops, this is not a simple polygon! ratio[0] = 0.0; return true; } if (i0 == i3) { // again, this is not a simple polygon! if ((triRef.getAngle(ind0) < 0) || (triRef.getAngle(ind3[0]) < 0)) { ratio[0] = 0.0; return true; } else return false; } if (i1 == i4) { // again, this is not a simple polygon! if ((triRef.getAngle(ind1[0]) < 0) || (triRef.getAngle(ind4) < 0)) { ratio[0] = 0.0; return true; } else return false; } // check whether the new diagonal i1, i3 locally is within the polygon convex = triRef.getAngle(ind1[0]) > 0; coneOk = Numerics.isInCone(triRef, i0, i1, i2, i3, convex); // System.out.println("isEar :(1) convex " + convex + " coneOk " + coneOk ); if (!coneOk) return false; convex = triRef.getAngle(ind3[0]) > 0; coneOk = Numerics.isInCone(triRef, i2, i3, i4, i1, convex); // System.out.println("isEar :(2) convex " + convex + " coneOk " + coneOk ); if (coneOk) { // check whether this diagonal is a valid diagonal. this translates to // checking either condition CE1 or CE2 (see my paper). If CE1 is to // to be checked, then we use a BV-tree or a grid. Otherwise, we use // "buckets" (i.e., a grid) or no hashing at all. bb = new BBox(triRef, i1, i3); // use CE2 + no_hashing if(!NoHash.noHashIntersectionExists(triRef, i2, ind2, i3, i1, bb)) { if (triRef.earsSorted) { // determine the quality of the triangle ratio[0] = Numerics.getRatio(triRef, i1, i3, i2); } else { ratio[0] = 1.0; } return true; } } // System.out.println("isEar : false"); return false; } /** * This is the main function that drives the ear-clipping. it obtains an ear * from set of ears maintained in a priority queue, clips this ear, and * updates all data structures appropriately. (ears are arranged in the * priority queue (i.e., heap) according to a quality criterion that tries * to avoid skinny triangles.) */ static boolean clipEar(Triangulator triRef, boolean[] done) { int ind0, ind1, ind3, ind4; int i0, i1, i2, i3, i4; int angle1, angle3; double ratio[] = new double[1]; int index0[] = new int[1]; int index1[] = new int[1]; int index2[] = new int[1]; int index3[] = new int[1]; int index4[] = new int[1]; int ind2[] = new int[1]; int testCnt = 0; // Heap.printHeapData(triRef); do { // System.out.println("In clipEarloop " + testCnt++); if (!Heap.deleteFromHeap(triRef, ind2, index1, index3)) // no ear exists?! return false; // get the successors and predecessors in the list of nodes and check // whether the ear still is part of the boundary ind1 = triRef.fetchPrevData(ind2[0]); i1 = triRef.fetchData(ind1); ind3 = triRef.fetchNextData(ind2[0]); i3 = triRef.fetchData(ind3); } while ((index1[0] != ind1) || (index3[0] != ind3)); //System.out.println("Out of clipEarloop "); i2 = triRef.fetchData(ind2[0]); // delete the clipped ear from the list of nodes, and update the bv-tree triRef.deleteLinks(ind2[0]); // store the ear in a list of ears which have already been clipped // StoreTriangle(GetOriginal(ind1), GetOriginal(ind2), GetOriginal(ind3)); triRef.storeTriangle(ind1, ind2[0], ind3); /* */ /* update the angle classification at ind1 and ind3 */ /* */ ind0 = triRef.fetchPrevData(ind1); i0 = triRef.fetchData(ind0); if (ind0 == ind3) { // nothing left done[0] = true; return true; } angle1 = Numerics.isConvexAngle(triRef, i0, i1, i3, ind1); ind4 = triRef.fetchNextData(ind3); i4 = triRef.fetchData(ind4); angle3 = Numerics.isConvexAngle(triRef, i1, i3, i4, ind3); if (i1 != i3) { if ((angle1 >= 0) && (triRef.getAngle(ind1) < 0)) NoHash.deleteReflexVertex(triRef, ind1); if ((angle3 >= 0) && (triRef.getAngle(ind3) < 0)) NoHash.deleteReflexVertex(triRef, ind3); } else { if ((angle1 >= 0) && (triRef.getAngle(ind1) < 0)) NoHash.deleteReflexVertex(triRef, ind1); else if ((angle3 >= 0) && (triRef.getAngle(ind3) < 0)) NoHash.deleteReflexVertex(triRef, ind3); } triRef.setAngle(ind1, angle1); triRef.setAngle(ind3, angle3); // check whether either of ind1 and ind3 is an ear. (the "ratio" is // the length of the triangle's longest side divided by the length of the // height normal onto this side; it is used as a quality criterion.) if (angle1 > 0) { if (isEar(triRef, ind1, index0, index2, ratio)) { // insert the new ear into the priority queue of ears Heap.insertIntoHeap(triRef, ratio[0], ind1, index0[0], index2[0]); } } if (angle3 > 0) { if(isEar(triRef, ind3, index2, index4, ratio)) { Heap.insertIntoHeap(triRef, ratio[0], ind3, index2[0], index4[0]); } } // check whether the triangulation is finished. ind0 = triRef.fetchPrevData(ind1); i0 = triRef.fetchData(ind0); ind4 = triRef.fetchNextData(ind3); i4 = triRef.fetchData(ind4); if (ind0 == ind4) { // only one triangle left -- clip it! triRef.storeTriangle(ind1, ind3, ind4); done[0] = true; } else { done[0] = false; } return true; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -