/*
* GeoTools - The Open Source Java GIS Toolkit
* http://geotools.org
*
* (C) 2006-2008, Open Source Geospatial Foundation (OSGeo)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License.
*
* This library 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
* Lesser General Public License for more details.
*/
package org.geotools.geometry.iso.coordinate;
import java.util.ArrayList;
import java.util.List;
import org.geotools.geometry.iso.primitive.SurfaceBoundaryImpl;
import org.opengis.geometry.primitive.SurfacePatch;
/**
* @author Jackson Roehrig & Sanjay Jena
*
* A GM_Tin (Figure 21) is a GM_TriangulatedSurface that uses the Delaunay
* algorithm or a similar algorithm complemented with consideration for
* breaklines, stoplines and maximum length of triangle sides (Figure 22). These
* networks satisfy the Delaunay criterion away from the modifications: For each
* triangle in the network, the circle passing through its vertexes does not
* contain, in its interior, the vertex of any other triangle.
*
* @source $URL$
*/
public class TinImpl extends TriangulatedSurfaceImpl {
/**
* Stoplines are lines where the local continuity or regularity of the
* surface is questionable. In the area of these pathologies, triangles
* intersecting a stopline shall be removed from the TIN surface, leaving
* holes in the surface. If coincidence occurs on surface boundary
* triangles, the result shall be a change of the surface boundary. The
* attribute "stopLines" contains all these pathological segments as a set
* of line strings.
*
* GM_Tin::stopLines : Set<GM_LineString>
*/
private ArrayList<LineStringImpl> stopLines = null; /*
* ArrayList of
* GM_LineSegment
*/
/**
* Breaklines are lines of a critical nature to the shape of the surface,
* representing local ridges, or depressions (such as drainage lines) in the
* surface. As such their constituent segments must be included in the TIN
* even if doing so violates the Delaunay criterion. The attribute
* "breakLines" contains these critical segments as a set of line strings.
*
* GM_Tin::breakLines : Set<GM_LineString>
*/
private ArrayList<LineStringImpl> breakLines = null; /*
* ArrayList of
* GM_LineSegment
*/
/**
* Areas of the surface where the data is not sufficiently dense to assure
* reasonable calculations shall be removed by adding a retention criterion
* for triangles based on the length of their sides. For any triangle sides
* exceeding maximum length, the adjacent triangles to that triangle side
* shall be removed from the surface.
*
* GM_Tin::maxLength : Distance
*/
private double maxLength = Double.NaN;
@SuppressWarnings("unused")
private double minLength = Double.NaN;
/**
* The corners of the triangles in the TIN are often referred to as posts.
* The attribute "controlPoint" shall contain a set of the GM_Positions used
* as posts for this TIN. Since each TIN contains triangles, there must be
* at least 3 posts. The order in which these points are given does not
* affect the surface that is represented. Application schemas may add
* information based on the ordering of the control points to facilitate the
* reconstruction of the TIN from the controlPoints.
*
* GM_Tin::controlPoint[3..n] : GM_Position
*
* NOTE The control points of a TIN are often called "posts."
*/
private ArrayList<PositionImpl> controlPoint = null; /*
* ArrayList of
* GM_Position
*/
@SuppressWarnings("unused")
private ArrayList<LineSegmentImpl> front;
/**
* The constructor for a restricted Delaunay network requires the triangle
* corners (posts), breaklines, stoplines, and maximum length of a triangle
* side.
*
* GM_Tin::GM_Tin(post : Set<GM_Position>, stopLines : Set<GM_LineString>,
* breakLines : Set<GM_LineString>, maxLength : Number): GM_Tin
*
* @param tin
*/
// public TinImpl(TinImpl tin) {
// super(tin);
// if (tin.breakLines!=null) {
// this.breakLines = new ArrayList<LineStringImpl>(tin.breakLines);
// } else {
// this.breakLines = null;
// }
// if (tin.stopLines != null) {
// this.stopLines = new ArrayList<LineStringImpl>(tin.stopLines);
// } else {
// tin.stopLines = null;
// }
// this.maxLength = tin.maxLength;
// this.minLength = tin.minLength;
// if ( tin.mFront!=null ) {
// this.mFront = new ArrayList<LineSegmentImpl>(tin.mFront);
// } else {
// tin.mFront = null;
// }
// this.controlPoint = new ArrayList<PositionImpl>();
//
// HashMap<PositionImpl,PositionImpl> hm = new
// HashMap<PositionImpl,PositionImpl>();
// for (PositionImpl otherPos : tin.getPosts()) {
// PositionImpl thisPos = new PositionImpl(otherPos.getDirectPosition());
// this.controlPoint.add(thisPos);
// hm.put(otherPos,thisPos);
// }
// ArrayList<TriangleImpl> thisTriangles = new ArrayList<TriangleImpl>();
// for (Triangle otherTri : tin.getTriangles()) {
// Position[] otherPositions = otherTri.getCorners();
// Position[] thisPositions = new PositionImpl[3];
// thisPositions[0] = hm.get(otherPositions[0]);
// thisPositions[1] = hm.get(otherPositions[1]);
// thisPositions[2] = hm.get(otherPositions[2]);
// TriangleImpl thisTriangle =
// CoordinateFactory.getDefault().createTriangle(null,
// thisPositions[0].getPosition(),
// thisPositions[1].getPosition(),
// thisPositions[2].getPosition());
// thisTriangles.add(thisTriangle);
// }
// this.setTriangles(thisTriangles, null);
// }
/**
* This constructor delegates the mesh generation to different mesh
* generators. GM_Factory transforms the results of the mesh generation into
* input parameters
*
* @param factory
*
* @param surfBdry
* @param post
* @param stopLines
* @param breakLines
* @param maxLength
* @param triangles
*/
public TinImpl(SurfaceBoundaryImpl surfBdry,
ArrayList<PositionImpl> post, ArrayList<LineStringImpl> stopLines,
ArrayList<LineStringImpl> breakLines, double maxLength,
ArrayList<TriangleImpl> triangles) {
super(surfBdry);
this.controlPoint = post;
this.breakLines = breakLines;
this.stopLines = stopLines;
this.maxLength = maxLength;
super.setTriangles(triangles);
}
/**
* @param factory
* @param post
* @param stopLines
* @param breakLines
* @param maxLength
*/
public TinImpl(PositionImpl[] post,
LineStringImpl[] stopLines, LineStringImpl[] breakLines,
double maxLength) {
/* Call super class; Triangles will be set later */
super(null);
this.controlPoint = new ArrayList<PositionImpl>();
this.breakLines = new ArrayList<LineStringImpl>();
this.stopLines = new ArrayList<LineStringImpl>();
/* Adding posts (Control points) */
if (post.length >= 3) {
for (int i = 0; i < post.length; i++) {
this.controlPoint.add(post[i]);
}
} else {
throw new IllegalArgumentException(
"At least three control points expected."); //$NON-NLS-1$
}
/* Adding Stop Lines */
for (int i = 0; i < stopLines.length; i++) {
this.stopLines.add(stopLines[i]);
}
/* Adding Break Lines */
for (int i = 0; i < breakLines.length; i++) {
this.breakLines.add(breakLines[i]);
}
/* Setting maximum length */
this.maxLength = maxLength;
/* Create Triangles for Surface */
// temporary solution, without considering stopLines and breakLines,
// and without generating intermediate points to smooth the mesh
// TODO JR
// GeoMshDelaunayTriangulation dTr = new GeoMshDelaunayTriangulation();
// dTr.createTriangles(post);
// GM_Triangle[] triangles = dTr.getTriangles();
/* Set Triangles for Triangulated Surface (Super class) */
// JR: SJ, ich habe das übeprüft, es fast alles richtig, nur
// this.setBoundary(new GM_SurfaceBoundary(patch)) hat Fehler.
// Man muss aus allen Dreiecken die Boundary ermitteln
// GM_TriangulatedSurface:setTriangles(GM_Triangle[] triangles)
// sollte diese Arbeit erledigen
// TODO JR
// ArrayList<GM_Triangle> tris = new
// ArrayList<GM_Triangle>(triangles.length);
// for (GM_Triangle tri : tris) tris.add(tri);
// super.setTriangles(tris,null);
// JR gelöscht: erledigt in setTriangles.
// /* Set this TIN as Associated Surface for each Surface Patch
// (=Triangle) */
// for (int i=0; i<triangles.length; i++) {
// triangles[i].setAssociatedSurface(this);
// }
}
/**
* @return List<LineStringImpl>
*/
public List<LineStringImpl> getStopLines() {
return this.stopLines;
}
/**
* @return List<LineStringImpl>
*/
public List<LineStringImpl> getBreakLines() {
return this.breakLines;
}
/**
* @return max length
*/
public double getMaxLength() {
return this.maxLength;
}
/**
* Returns an Array of the surface patches as GM_Triangle´s
*
* @return ArrayList<TriangleImpl>
*/
public List<TriangleImpl> getTriangles() {
List<TriangleImpl> triangles = new ArrayList<TriangleImpl>(); //this.getFeatGeometryFactory().getListFactory().createTriangleList();
for (SurfacePatch sp : this.getPatches()) {
triangles.add((TriangleImpl) sp);
}
return triangles;
}
/**
* @return List<PositionImpl>
*/
public List<PositionImpl> getPosts() {
return this.controlPoint;
}
}