001: /*
002: * This file is part of the GeOxygene project source files.
003: *
004: * GeOxygene aims at providing an open framework which implements OGC/ISO specifications for
005: * the development and deployment of geographic (GIS) applications. It is a open source
006: * contribution of the COGIT laboratory at the Institut Géographique National (the French
007: * National Mapping Agency).
008: *
009: * See: http://oxygene-project.sourceforge.net
010: *
011: * Copyright (C) 2005 Institut Géographique National
012: *
013: * This library is free software; you can redistribute it and/or modify it under the terms
014: * of the GNU Lesser General Public License as published by the Free Software Foundation;
015: * either version 2.1 of the License, or any later version.
016: *
017: * This library is distributed in the hope that it will be useful, but WITHOUT ANY
018: * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
019: * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
020: *
021: * You should have received a copy of the GNU Lesser General Public License along with
022: * this library (see file LICENSE if present); if not, write to the Free Software
023: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
024: *
025: */
026:
027: package fr.ign.cogit.geoxygene.contrib.geometrie;
028:
029: import java.util.Iterator;
030:
031: import fr.ign.cogit.geoxygene.spatial.coordgeom.DirectPosition;
032: import fr.ign.cogit.geoxygene.spatial.coordgeom.DirectPositionList;
033: import fr.ign.cogit.geoxygene.spatial.coordgeom.GM_LineString;
034: import fr.ign.cogit.geoxygene.spatial.coordgeom.GM_Polygon;
035: import fr.ign.cogit.geoxygene.spatial.geomroot.GM_Object;
036:
037: /**
038: * Méthodes statiques de calcul d'indices de forme (de lignes et de surfaces).
039: *
040: * English : Measures of shapes
041: *
042: * @author Mustière/Sheeren/Grosso
043: */
044:
045: public abstract class IndicesForme {
046:
047: //////////////////////////////////////////
048: // INDICES SUR DES SURFACES
049: //////////////////////////////////////////
050:
051: /** Indice de circularité de Miller (pour des surfaces)
052: * Valeur entre 0 et 1.
053: * Vaut 1 si le polygone est un cercle, 0 si il est de surface nulle.
054: * Définition = 4*pi*surface/perimetre^2
055: * Conseil : le seuil de 0.95 est adapté pour des ronds points dans un réseau routier.
056: */
057: public static double indiceCompacite(GM_Polygon poly) {
058: if (Operateurs.surface(poly) == 0)
059: return 0;
060: if (poly.coord().size() < 4)
061: return 0;
062: double perimetre = poly.perimeter();
063: if (perimetre == 0)
064: return 0;
065: double surface = poly.area();
066: return 4 * (Math.PI) * surface / Math.pow(perimetre, 2);
067: }
068:
069: /** Coefficient de compacité de Gravelius (pour des surfaces)
070: * Non borné : supérieur ou égal à 1 (cercle) .
071: * Définition = perimetre/2*Racine(Pi*surface)
072: */
073: public static double indiceCompaciteGravelius(GM_Polygon poly) {
074: double perimetre = poly.length();
075: double surface = poly.area();
076: return perimetre / 2 * (Math.sqrt(Math.PI * surface));
077: }
078:
079: /** Diamètre d'une surface: plus grande distance entre 2 points de la
080: * frontière de la surface considérée.
081: *
082: * English: diameter of a surface
083: *
084: * @param GM_Object A
085: * @return -1 si A n'est pas une surface, le diamètre sinon
086: */
087: public static double diametreSurface(GM_Object A) {
088: if (A.area() == 0)
089: return -1;
090:
091: DirectPositionList pts = A.coord();
092: double dist, diametre = 0;
093:
094: Iterator itPts = pts.getList().iterator();
095: while (itPts.hasNext()) {
096: DirectPosition dp = (DirectPosition) itPts.next();
097: Iterator itPts2 = pts.getList().iterator();
098: while (itPts2.hasNext()) {
099: DirectPosition dp2 = (DirectPosition) itPts2.next();
100: dist = Distances.distance2D(dp, dp2);
101: if (dist > diametre)
102: diametre = dist;
103: }
104: }
105: return diametre;
106: }
107:
108: //////////////////////////////////////////
109: // INDICES SUR DES LIGNES
110: //////////////////////////////////////////
111: /** Méthode qui détermine si la liste de points passée en entrée est rectiligne.
112: * Une ligne est considérée rectiligne si les angles entre les segments qui
113: * la constitue ne sont pas trop forts (inférieur au seuil en paramètre en radians).
114: * Défaut : dépend de l'échantillonage des courbes, des critères de courbure
115: * seraient plus stables.
116: *
117: * English: is the line straight?
118: */
119: public static boolean rectiligne(GM_LineString ligne,
120: double toleranceAngulaire) {
121: int i;
122: Angle ecartTrigo;
123: double angle;
124: double angleMin = Math.PI - toleranceAngulaire;
125: double angleMax = Math.PI + toleranceAngulaire;
126: DirectPositionList listePts = ligne.getControlPoint();
127: for (i = 0; i < listePts.size() - 2; i++) {
128: ecartTrigo = Angle.angleTroisPoints(listePts.get(i),
129: listePts.get(i + 1), listePts.get(i + 2));
130: angle = ecartTrigo.getAngle();
131: if ((angle > angleMax) || (angle < angleMin))
132: return false;
133: }
134: return true;
135: }
136:
137: }
|