/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
- /***********************************************************************
- * mt4j Copyright (c) 2008 - 2009 C.Ruff, Fraunhofer-Gesellschaft All rights reserved.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- ***********************************************************************/
- package org.mt4j.util.math;
-
- /**
- * Class to check whether a series of vectors which belong to
- * a polygon are convex or concave.
- * <p>C code from the article
- * "Testing the Convexity of a Polygon"
- * by Peter Schorn and Frederick Fisher,
- * (schorn@inf.ethz.ch, fred@kpc.com)
- * in "Graphics Gems IV", Academic Press, 1994
- * @author C.Ruff
- */
- public class ConvexityUtil {
-
- /** The Constant NotConvex. */
- public static final int NotConvex = 0;
-
- /** The Constant NotConvexDegenerate. */
- public static final int NotConvexDegenerate = 1;
-
- /** The Constant ConvexDegenerate. */
- public static final int ConvexDegenerate = 2;
-
- /** The Constant ConvexCCW. */
- public static final int ConvexCCW = 3;
-
- /** The Constant ConvexCW. */
- public static final int ConvexCW = 4;
-
- /*
- * C code from the article
- * "Testing the Convexity of a Polygon"
- * by Peter Schorn and Frederick Fisher,
- * (schorn@inf.ethz.ch, fred@kpc.com)
- * in "Graphics Gems IV", Academic Press, 1994
- */
-
- /* Reasonably Optimized Routine to Classify a Polygon's Shape */
-
- /*
-
- .. code omitted which reads polygon, stores in an array, and calls
- classifyPolygon2()
- */
-
- // typedef enum { NotConvex, NotConvexDegenerate,
- // ConvexDegenerate, ConvexCCW, ConvexCW } PolygonClass;
- //
- // typedef double Number; /* float or double */
- //
- // #define ConvexCompare(delta) \
- // ( (delta[0] > 0) ? -1 : /* x coord diff, second pt > first pt */\
- // (delta[0] < 0) ? 1 : /* x coord diff, second pt < first pt */\
- // (delta[1] > 0) ? -1 : /* x coord same, second pt > first pt */\
- // (delta[1] < 0) ? 1 : /* x coord same, second pt > first pt */\
- // 0 ) /* second pt equals first point */
-
-
- /**
- * Convex compare.
- *
- * @param delta the delta
- *
- * @return the int
- */
- private static int ConvexCompare(Vector3D delta){
- int returnval = (
- (delta.x > 0) ? -1 : /* x coord diff, second pt > first pt */
- (delta.x < 0) ? 1 : /* x coord diff, second pt < first pt */
- (delta.y > 0) ? -1 : /* x coord same, second pt > first pt */
- (delta.y < 0) ? 1 : /* x coord same, second pt > first pt */
- 0 );
-
- return returnval;
- }
-
- /**
- * Convex get point delta.
- *
- * @param delta the delta
- * @param pprev the pprev
- * @param pcur the pcur
- */
- private static void ConvexGetPointDelta(Vector3D delta, Vector3D pprev, Vector3D pcur) {
- pcur = pVert[iread++];
- delta.x = pcur.x - pprev.x;
- delta.y = pcur.y - pprev.y;
- }
-
-
- /**
- * Convex cross.
- *
- * @param p the p
- * @param q the q
- *
- * @return the float
- */
- private static float ConvexCross(Vector3D p, Vector3D q){
- return (p.x * q.y - p.y * q.x);
- }
- //
-
- // #define ConvexCheckTriple
- // if ( (thisDir = ConvexCompare(dcur)) == -curDir ) {
- // ++dirChanges;
- // /* The following line will optimize for polygons that are */
- // /* not convex because of classification condition 4, */
- // /* otherwise, this will only slow down the classification. */
- // /* if ( dirChanges > 2 ) return NotConvex; */
- // }
- // curDir = thisDir;
- // cross = ConvexCross(dprev, dcur);
- // if ( cross > 0 ) { if ( angleSign == -1 ) return NotConvex;
- // angleSign = 1;
- // }
- // else if (cross < 0) { if (angleSign == 1) return NotConvex;
- // angleSign = -1;
- // }
- // pSecond = pThird; /* Remember ptr to current point. */
- // dprev[0] = dcur[0]; /* Remember current delta. */
- // dprev[1] = dcur[1];
-
- /**
- * Convex check triple.
- *
- * @return the int
- */
- private static int ConvexCheckTriple(){
- if ( (thisDir = ConvexCompare(dcur)) == -curDir ) {
- ++dirChanges;
-
- // System.out.println("Dirchange! " + dirChanges);
- /* The following line will optimize for polygons that are */
- /* not convex because of classification condition 4, */
- /* otherwise, this will only slow down the classification. */
- /* if ( dirChanges > 2 ) return NotConvex; */
- }
-
- curDir = thisDir;
- cross = ConvexCross(dprev, dcur);
-
- if ( cross > 0 ) {
- if ( angleSign == -1 ){
- return NotConvex;
- }
- angleSign = 1;
- } else if (cross < 0) {
- if (angleSign == 1){
- return NotConvex; //TODO ander smachen
- // return NotConvexDegenerate;
- }
- angleSign = -1;
- }
- pSecond = pThird; /* Remember ptr to current point. */
- dprev.x = dcur.x; /* Remember current delta. */
- dprev.y = dcur.y;
-
- return -1;
- }
-
- /** The nvert. */
- private static int nvert;
-
- /** The p vert. */
- private static Vector3D[] pVert;
-
- /** The iread. */
- private static int
- curDir,
- thisDir,
- dirChanges = 0,
- angleSign = 0,
- iread ;
-
- /** The cross. */
- private static float cross;
-
- /** The dprev. */
- private static Vector3D dprev = new Vector3D(0,0,0);
-
- /** The dcur. */
- private static Vector3D dcur = new Vector3D(0,0,0);
-
- /** The p second. */
- private static Vector3D pSecond = new Vector3D(0,0,0);
-
- /** The p third. */
- private static Vector3D pThird = new Vector3D(0,0,0);
-
- /** The p save second. */
- private static Vector3D pSaveSecond = new Vector3D(0,0,0);
-
-
- /**
- * Classify polygon2.
- *
- * @param vertCount the vert count
- * @param pVerts the verts
- *
- * @return the int
- */
- public static int classifyPolygon2(int vertCount, Vector3D[] pVerts){
- nvert = vertCount;
- pVert = Vector3D.getDeepVertexArrayCopy(pVerts);
- // pVert = pVerts;
-
- /* if ( nvert <= 0 ) return error; if you care */
-
- /* Get different point, return if less than 3 diff points. */
- if ( nvert < 3 )
- return ConvexDegenerate;
-
- iread = 1;
- while ( true ) {
- ConvexGetPointDelta(dprev, pVert[0], pSecond);
-
- if ( dprev.x != 0 || dprev.y != 0)
- break;
-
- /* Check if out of points. Check here to avoid slowing down cases
- * without repeated points.
- */
- if ( iread >= nvert )
- return ConvexDegenerate;
- }
-
- pSaveSecond = pSecond;
-
- curDir = ConvexCompare(dprev); /* Find initial direction */
-
- while ( iread < nvert ) {
- /* Get different point, break if no more points */
- ConvexGetPointDelta(dcur, pSecond, pThird );
- if ( dcur.x == 0.0 && dcur.y == 0.0 )
- continue;
-
- if (ConvexCheckTriple() == NotConvex ){ /* Check current three points */
- return NotConvex;
- }
- }
-
- /* Must check for direction changes from last vertex back to first */
- pThird = pVert[0]; /* Prepare for 'ConvexCheckTriple' */
- dcur.x = pThird.x - pSecond.x;
- dcur.y = pThird.y - pSecond.y;
-
- if ( ConvexCompare(dcur) != 0) {
- if (ConvexCheckTriple() == NotConvex ){ /* Check current three points */
- return NotConvex;
- }
- }
-
- /* and check for direction changes back to second vertex */
- dcur.x = pSaveSecond.x - pSecond.x;
- dcur.y = pSaveSecond.y - pSecond.y;
-
- if (ConvexCheckTriple() == NotConvex ){ /* Don't care about 'pThird' now */
- return NotConvex;
- }
-
- /* Decide on polygon type given accumulated status */
- if ( dirChanges > 2 )
- return (angleSign != 0 ) ? NotConvex : NotConvexDegenerate;
-
- if ( angleSign > 0 )
- return ConvexCCW;
-
- if ( angleSign < 0 )
- return ConvexCW;
-
- return ConvexDegenerate;
- }
-
-
-
-
-
-
- }