PageRenderTime 37ms CodeModel.GetById 20ms app.highlight 13ms RepoModel.GetById 2ms app.codeStats 0ms

/src/org/mt4j/util/math/ConvexityUtil.java

http://mt4j.googlecode.com/
Java | 297 lines | 105 code | 56 blank | 136 comment | 32 complexity | cb7d138f5b7fd245a94bd8e903178d55 MD5 | raw file
  1/***********************************************************************
  2 * mt4j Copyright (c) 2008 - 2009 C.Ruff, Fraunhofer-Gesellschaft All rights reserved.
  3 *  
  4 *   This program is free software: you can redistribute it and/or modify
  5 *   it under the terms of the GNU General Public License as published by
  6 *   the Free Software Foundation, either version 3 of the License, or
  7 *   (at your option) any later version.
  8 *
  9 *   This program is distributed in the hope that it will be useful,
 10 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 11 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 12 *   GNU General Public License for more details.
 13 *
 14 *   You should have received a copy of the GNU General Public License
 15 *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 16 *
 17 ***********************************************************************/
 18package org.mt4j.util.math;
 19
 20/**
 21 * Class to check whether a series of vectors which belong to
 22 * a polygon are convex or concave.
 23 * <p>C code from the article
 24 * "Testing the Convexity of a Polygon"
 25 * by Peter Schorn and Frederick Fisher,
 26 *	(schorn@inf.ethz.ch, fred@kpc.com)
 27 * in "Graphics Gems IV", Academic Press, 1994
 28 * @author C.Ruff
 29 */
 30public class ConvexityUtil {
 31
 32	/** The Constant NotConvex. */
 33	public static final int NotConvex = 0;
 34	
 35	/** The Constant NotConvexDegenerate. */
 36	public static final int NotConvexDegenerate = 1;
 37	
 38	/** The Constant ConvexDegenerate. */
 39	public static final int ConvexDegenerate = 2;
 40	
 41	/** The Constant ConvexCCW. */
 42	public static final int ConvexCCW = 3;
 43	
 44	/** The Constant ConvexCW. */
 45	public static final int ConvexCW = 4;
 46
 47	/*
 48	 * C code from the article
 49	 * "Testing the Convexity of a Polygon"
 50	 * by Peter Schorn and Frederick Fisher,
 51	 *	(schorn@inf.ethz.ch, fred@kpc.com)
 52	 * in "Graphics Gems IV", Academic Press, 1994
 53	 */
 54
 55	/* Reasonably Optimized Routine to Classify a Polygon's Shape */
 56
 57	/*
 58
 59	.. code omitted which reads polygon, stores in an array, and calls
 60		classifyPolygon2()
 61	*/
 62
 63//	typedef enum { NotConvex, NotConvexDegenerate,
 64//		       ConvexDegenerate, ConvexCCW, ConvexCW } PolygonClass;
 65//
 66//	typedef double	Number;		/* float or double */
 67//
 68//	#define ConvexCompare(delta)						\
 69//    ( (delta[0] > 0) ? -1 :	/* x coord diff, second pt > first pt */\
 70//      (delta[0] < 0) ?	1 :	/* x coord diff, second pt < first pt */\
 71//      (delta[1] > 0) ? -1 :	/* x coord same, second pt > first pt */\
 72//      (delta[1] < 0) ?	1 :	/* x coord same, second pt > first pt */\
 73//      0 )			/* second pt equals first point */
 74
 75	      
 76  	/**
 77	 * Convex compare.
 78	 * 
 79	 * @param delta the delta
 80	 * 
 81	 * @return the int
 82	 */
 83	private static int ConvexCompare(Vector3D delta){
 84  		int returnval = ( 
 85  				  (delta.x > 0) ? -1 :	/* x coord diff, second pt > first pt */
 86			      (delta.x < 0) ?  1 :	/* x coord diff, second pt < first pt */
 87			      (delta.y > 0) ? -1 :	/* x coord same, second pt > first pt */
 88			      (delta.y < 0) ?  1 :	/* x coord same, second pt > first pt */
 89			       0 );
 90  		
 91  		return returnval;
 92  	}
 93  	
 94	/**
 95	 * Convex get point delta.
 96	 * 
 97	 * @param delta the delta
 98	 * @param pprev the pprev
 99	 * @param pcur the pcur
100	 */
101	private static void ConvexGetPointDelta(Vector3D delta, Vector3D pprev, Vector3D pcur) {
102	    pcur = pVert[iread++];						
103	    delta.x = pcur.x - pprev.x;					
104	    delta.y = pcur.y - pprev.y;	
105	}
106	
107	
108	/**
109	 * Convex cross.
110	 * 
111	 * @param p the p
112	 * @param q the q
113	 * 
114	 * @return the float
115	 */
116	private static float ConvexCross(Vector3D p, Vector3D q){
117		return 	(p.x * q.y - p.y * q.x);
118	}
119//
120	
121//	#define ConvexCheckTriple						
122//	    if ( (thisDir = ConvexCompare(dcur)) == -curDir ) {			
123//		  ++dirChanges;							
124//		  /* The following line will optimize for polygons that are  */
125//		  /* not convex because of classification condition 4,	     */ 
126//		  /* otherwise, this will only slow down the classification. */ 
127//		  /* if ( dirChanges > 2 ) return NotConvex;		     */ 
128//	    }									
129//	    curDir = thisDir;							
130//	    cross = ConvexCross(dprev, dcur);					
131//	    if ( cross > 0 ) { if ( angleSign == -1 ) return NotConvex;		
132//			       angleSign = 1;					
133//			     }							
134//	    else if (cross < 0) { if (angleSign == 1) return NotConvex;		
135//				    angleSign = -1;				
136//				  }						
137//	    pSecond = pThird;		/* Remember ptr to current point. */	
138//	    dprev[0] = dcur[0];		/* Remember current delta.	  */	
139//	    dprev[1] = dcur[1];							
140
141	    /**
142 * Convex check triple.
143 * 
144 * @return the int
145 */
146private static int ConvexCheckTriple(){
147		    if ( (thisDir = ConvexCompare(dcur)) == -curDir ) {			
148				  ++dirChanges;		
149
150//				  System.out.println("Dirchange! " + dirChanges);
151				  /* The following line will optimize for polygons that are  */
152				  /* not convex because of classification condition 4,	     */ 
153				  /* otherwise, this will only slow down the classification. */ 
154				  /* if ( dirChanges > 2 ) return NotConvex;		     */ 
155			    }				
156		    
157			    curDir = thisDir;							
158			    cross = ConvexCross(dprev, dcur);	
159			    
160			    if ( cross > 0 ) { 
161			    	if ( angleSign == -1 ){ 
162			    		return NotConvex;	
163			    	}
164					      angleSign = 1;					
165			    } else if (cross < 0) { 
166			    	if (angleSign == 1){ 
167			    		return NotConvex; //TODO ander smachen
168//			    		return NotConvexDegenerate;
169			    	}
170					    angleSign = -1;				
171				}						
172			    pSecond = pThird;		/* Remember ptr to current point. */	
173			    dprev.x = dcur.x;		/* Remember current delta.	  */	
174			    dprev.y = dcur.y;	
175			    
176			    return -1;
177	    }
178	    
179	/** The nvert. */
180	private static int nvert;
181	
182	/** The p vert. */
183	private static Vector3D[] pVert;
184	
185	/** The iread. */
186	private static int 
187		curDir, 
188		thisDir, 
189		dirChanges = 0,
190	    angleSign = 0, 
191	    iread ;
192	
193	/** The cross. */
194	private static float cross;
195	
196	/** The dprev. */
197	private static Vector3D dprev = new Vector3D(0,0,0); 
198	
199	/** The dcur. */
200	private static Vector3D dcur = new Vector3D(0,0,0); 
201	
202	/** The p second. */
203	private static Vector3D pSecond = new Vector3D(0,0,0); 
204	
205	/** The p third. */
206	private static Vector3D pThird = new Vector3D(0,0,0); 
207	
208	/** The p save second. */
209	private static Vector3D pSaveSecond = new Vector3D(0,0,0); 
210
211	
212	/**
213	 * Classify polygon2.
214	 * 
215	 * @param vertCount the vert count
216	 * @param pVerts the verts
217	 * 
218	 * @return the int
219	 */
220	public static int classifyPolygon2(int vertCount, Vector3D[] pVerts){
221	 nvert = vertCount;
222	 pVert = Vector3D.getDeepVertexArrayCopy(pVerts);
223//	 pVert = pVerts;
224	 
225	    /* if ( nvert <= 0 ) return error;	     if you care */
226
227	    /* Get different point, return if less than 3 diff points. */
228	    if ( nvert < 3 ) 
229	    	return ConvexDegenerate;
230	    
231	    iread = 1;
232	    while ( true ) {
233			ConvexGetPointDelta(dprev, pVert[0], pSecond);
234			
235			if ( dprev.x != 0 || dprev.y != 0) 
236				break;
237			
238			/* Check if out of points. Check here to avoid slowing down cases
239			 * without repeated points.
240			 */
241			if ( iread >= nvert ) 
242				return ConvexDegenerate;
243	    }
244
245	    pSaveSecond = pSecond;
246
247	    curDir = ConvexCompare(dprev);	/* Find initial direction */
248
249	    while ( iread < nvert ) {
250			/* Get different point, break if no more points */
251			ConvexGetPointDelta(dcur, pSecond, pThird );
252			if ( dcur.x == 0.0  &&	 dcur.y == 0.0 ) 
253				continue;
254	
255			if (ConvexCheckTriple() == NotConvex ){		/* Check current three points */
256				return NotConvex;
257			}
258	    }
259
260	    /* Must check for direction changes from last vertex back to first */
261	    pThird = pVert[0];			/* Prepare for 'ConvexCheckTriple' */
262	    dcur.x = pThird.x - pSecond.x;
263	    dcur.y = pThird.y - pSecond.y;
264	   
265	    if ( ConvexCompare(dcur) != 0) {
266	    	if (ConvexCheckTriple() == NotConvex ){		/* Check current three points */
267				return NotConvex;
268	    	}
269	    }
270
271	    /* and check for direction changes back to second vertex */
272	    dcur.x = pSaveSecond.x - pSecond.x;
273	    dcur.y = pSaveSecond.y - pSecond.y;
274	    
275	    if (ConvexCheckTriple() == NotConvex ){		/* Don't care about 'pThird' now */
276			return NotConvex;			
277	    }
278
279	    /* Decide on polygon type given accumulated status */
280	    if ( dirChanges > 2 )
281	    	return (angleSign != 0 ) ? NotConvex : NotConvexDegenerate;
282
283	    if ( angleSign > 0 ) 
284	    	return ConvexCCW;
285	    
286	    if ( angleSign < 0 ) 
287	    	return ConvexCW;
288	    
289	    return ConvexDegenerate;
290	}
291
292
293
294	
295	
296	
297}