/* Spatial Operations & Editing Tools for uDig * * Axios Engineering under a funding contract with: * Diputación Foral de Gipuzkoa, Ordenación Territorial * * http://b5m.gipuzkoa.net * http://www.axios.es * * (C) 2006, Diputación Foral de Gipuzkoa, Ordenación Territorial (DFG-OT). * DFG-OT agrees to licence under Lesser General Public License (LGPL). * * 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 es.axios.udig.ui.editingtools.precisionparallels.internal; import java.util.List; import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geomgraph.Quadrant; /** * <p> * * <pre> * Quadrant analyzer. * Based on the algorithm of the quadrant, will analyze the provided coordinate, * and determinate if they must be eliminated or not. * It will validate a coordinate or coordinates. * </pre> * * </p> * * @author Aritz Davila (www.axios.es) * @author Mauricio Pazos (www.axios.es) * */ final class QuadrantAnalyzer { private int index; private int size; private int intersectionLastPosition; private Coordinate imaginaryCoord; private Coordinate realIntersectionCoord; private final List<Coordinate> inputList; private final List<Coordinate> sourceList; /* Is valid segment1-point1 */ private boolean valids1p1; /* Is valid segment1-point2 */ private boolean valids1p2; /* Is valid segment2-point1 */ private boolean valids2p1; /* Is valid segment2-point2 */ private boolean valids2p2; public enum AnalyzerPosition { /* The coordinate 1 of the segment 1 */ SEGMENT_1_POINT_1, /* The coordinate 2 of the segment 1 */ SEGMENT_1_POINT_2, /* The coordinate 1 of the segment 2 */ SEGMENT_2_POINT_1, /* The coordinate 2 of the segment 2 */ SEGMENT_2_POINT_2, /* None of each */ RESULTANT_NONE } /** * Constructor used for analyze non-closed lines. * * @param inputList * List with the created coordinates. * @param sourceList * List with the original coordinates. * @param index * Index of the first segment. * @param intersectionLastPosition * Index of second segment. */ public QuadrantAnalyzer(final List<Coordinate> inputList, final List<Coordinate> sourceList, int index, int intersectionLastPosition) { assert inputList != null : "cannot be null"; //$NON-NLS-1$ assert sourceList != null : "cannot be null"; //$NON-NLS-1$ this.index = index; this.inputList = inputList; this.sourceList = sourceList; this.intersectionLastPosition = intersectionLastPosition; } /** * * Constructor used for analyze closed lines. * * @param inputList * List with the created coordinates. * @param sourceList * List with the original coordinates. * @param index * Index of the first segment. * @param intersectionLastPosition * Index of second segment. * @param size * Size of the input list. * @param realIntersectionCoord * The intersection of the segment off the input list. * @param imaginaryCoord * The non existent intersection of the segment off the source * list. */ public QuadrantAnalyzer(final List<Coordinate> inputList, final List<Coordinate> sourceList, int index, int intersectionLastPosition, int size, Coordinate realIntersectionCoord, Coordinate imaginaryCoord) { this(inputList, sourceList, index, intersectionLastPosition); this.size = size; this.realIntersectionCoord = realIntersectionCoord; this.imaginaryCoord = imaginaryCoord; } /** * Get the coordinates of the analyzed segment. Those coordinate will depend * on the provided 'index' and 'intersectionLastPosition'. Will get the * coordinates from the input list and from the source list and analyze * them. */ public void analyzeNonClosedLines() { Coordinate s1p1, s1p2, s2p1, s2p2, s1p1src, s1p2src, s2p1src, s2p2src; // input coordinates s1p1 = inputList.get(index); s1p2 = inputList.get(index + 1); s2p1 = inputList.get(intersectionLastPosition); s2p2 = inputList.get(intersectionLastPosition + 1); // source coordinates s1p1src = sourceList.get(index); s1p2src = sourceList.get(index + 1); s2p1src = sourceList.get(intersectionLastPosition); s2p2src = sourceList.get(intersectionLastPosition + 1); analyze(s1p1, s1p2, s2p1, s2p2, s1p1src, s1p2src, s2p1src, s2p2src); } /** * Meanwhile the analyze process, for each coordinate is stored if it was * valid or not. This function will return true if all of those analyzed * coordinates were true. * * @return True if all of the coordinates were valid. */ public boolean isValid() { return valids1p1 && valids1p2 && valids2p1 && valids2p2; } /** * Get the coordinates of the analyzed segment. Those coordinate will depend * on the provided 'index' and 'intersectionLastPosition'. Will get the * coordinates from the input list and from the source list and analyze them * using the provided intersections as referent points. * */ public void analyzeClosedLines() { // this will test if for one coordinate of each segment, the quadrant // operation with each coordinate of the other segment, both will be // false. Coordinate s1p1, s1p2, s2p1, s2p2, s1p1src, s1p2src, s2p1src, s2p2src; int secondIndex = intersectionLastPosition == 0 ? size - 1 : intersectionLastPosition - 1; // input coordinates s1p1 = inputList.get(index); s1p2 = inputList.get(index + 1); s2p1 = inputList.get(intersectionLastPosition); s2p2 = inputList.get(secondIndex); // source coordinates s1p1src = sourceList.get(index); s1p2src = sourceList.get(index + 1); s2p1src = sourceList.get(intersectionLastPosition); s2p2src = sourceList.get(secondIndex); analyzeUsingIntersection(s1p1, s1p2, s2p1, s2p2, s1p1src, s1p2src, s2p1src, s2p2src); } /** * Will analyze each coordinate respect the provided intersection * coordinate. And compare with the result of the analyzed source coordinate * with the imaginary segment. * * The parameters are the coordinates, 2 segment, 4 coordinates and its * respective coordinate off the source list. Totally 8 coordinate will be * part of that. * * @param s1p1 * @param s1p2 * @param s2p1 * @param s2p2 * @param s1p1src * @param s1p2src * @param s2p1src * @param s2p2src */ private void analyzeUsingIntersection( final Coordinate s1p1, final Coordinate s1p2, final Coordinate s2p1, final Coordinate s2p2, final Coordinate s1p1src, final Coordinate s1p2src, final Coordinate s2p1src, final Coordinate s2p2src) { // coord s1p1 (segment 1, point 1) int qs1p1s2p1 = Quadrant.quadrant(s1p1, realIntersectionCoord); int qs1p1s2p1src = Quadrant.quadrant(s1p1src, imaginaryCoord); // checking the quadrant. // a valid quadrant for segment 1 point 1, must have the same value // respect the quadrant of segment 2 point 1 and segment 2 point 2. // if any of those is false, the result will be FALSE. valids1p1 = qs1p1s2p1 == qs1p1s2p1src; // coord s1p2 (segment 1, point 2) int qs1p2s2p1 = Quadrant.quadrant(s1p2, realIntersectionCoord); int qs1p2s2p1src = Quadrant.quadrant(s1p2src, imaginaryCoord); // checking the quadrant. // a valid quadrant for segment 1 point 2, must have the same value // respect the quadrant of segment 2 point 1 and segment 2 point 2. valids1p2 = qs1p2s2p1 == qs1p2s2p1src; // coord s2p1 (segment 2, point 1) int qs2p1s1p1 = Quadrant.quadrant(s2p1, realIntersectionCoord); int qs2p1s1p1src = Quadrant.quadrant(s2p1src, imaginaryCoord); // checking the quadrant. // a valid quadrant for segment 2 point 1, must have the same value // respect the quadrant of segment 1 point 1 and segment 1 point 2. valids2p1 = qs2p1s1p1 == qs2p1s1p1src; // coord s2p2 (segment 2, point 2) int qs2p2s1p1 = Quadrant.quadrant(s2p2, realIntersectionCoord); int qs2p2s1p1src = Quadrant.quadrant(s2p2src, imaginaryCoord); // checking the quadrant. // a valid quadrant for segment 2 point 2, must have the same value // respect the quadrant of segment 1 point 1 and segment 1 point 2. valids2p2 = qs2p2s1p1 == qs2p2s1p1src; } /** * * <p> * * <pre> * Will analyze each coordinate in that way: * Coordinate 1 of the segment 1, apply quadrant operation with coordinate 1 and 2 * from the other segment. And do the same with the source coordinate. * Then, compare the result of s1p1 (segment 1-coord 1) respect s2p1, with the result * of s1p1src(segment 1-coord 1 of source) respect s2p1src. * * Do that for all the coordinates. * * The parameters are the coordinates, 2 segment, 4 coordinates and its * respective coordinate off the source list. Totally 8 coordinate will be * part of that. * </pre> * * </p> * * @param s1p1 * @param s1p2 * @param s2p1 * @param s2p2 * @param s1p1src * @param s1p2src * @param s2p1src * @param s2p2src */ private void analyze( final Coordinate s1p1, final Coordinate s1p2, final Coordinate s2p1, final Coordinate s2p2, final Coordinate s1p1src, final Coordinate s1p2src, final Coordinate s2p1src, final Coordinate s2p2src) { // coord s1p1 (segment 1, point 1) int qs1p1s2p1 = Quadrant.quadrant(s1p1, s2p1); int qs1p1s2p1src = Quadrant.quadrant(s1p1src, s2p1src); int qs1p1s2p2 = Quadrant.quadrant(s1p1, s2p2); int qs1p1s2p2src = Quadrant.quadrant(s1p1src, s2p2src); // checking the quadrant. // a valid quadrant for segment 1 point 1, must have the same value // respect the quadrant of segment 2 point 1 and segment 2 point 2. // if any of those is false, the result will be FALSE. valids1p1 = (qs1p1s2p1 == qs1p1s2p1src) && (qs1p1s2p2 == qs1p1s2p2src); // coord s1p2 (segment 1, point 2) int qs1p2s2p1 = Quadrant.quadrant(s1p2, s2p1); int qs1p2s2p1src = Quadrant.quadrant(s1p2src, s2p1src); int qs1p2s2p2 = Quadrant.quadrant(s1p2, s2p2); int qs1p2s2p2src = Quadrant.quadrant(s1p2src, s2p2src); // checking the quadrant. // a valid quadrant for segment 1 point 2, must have the same value // respect the quadrant of segment 2 point 1 and segment 2 point 2. valids1p2 = (qs1p2s2p1 == qs1p2s2p1src) && (qs1p2s2p2 == qs1p2s2p2src); // coord s2p1 (segment 2, point 1) int qs2p1s1p1 = Quadrant.quadrant(s2p1, s1p1); int qs2p1s1p1src = Quadrant.quadrant(s2p1src, s1p1src); int qs2p1s1p2 = Quadrant.quadrant(s2p1, s1p2); int qs2p1s1p2src = Quadrant.quadrant(s2p1src, s1p2src); // checking the quadrant. // a valid quadrant for segment 2 point 1, must have the same value // respect the quadrant of segment 1 point 1 and segment 1 point 2. valids2p1 = (qs2p1s1p1 == qs2p1s1p1src) && (qs2p1s1p2 == qs2p1s1p2src); // coord s2p2 (segment 2, point 2) int qs2p2s1p1 = Quadrant.quadrant(s2p2, s1p1); int qs2p2s1p1src = Quadrant.quadrant(s2p2src, s1p1src); int qs2p2s1p2 = Quadrant.quadrant(s2p2, s1p2); int qs2p2s1p2src = Quadrant.quadrant(s2p2src, s1p2src); // checking the quadrant. // a valid quadrant for segment 2 point 2, must have the same value // respect the quadrant of segment 1 point 1 and segment 1 point 2. valids2p2 = (qs2p2s1p1 == qs2p2s1p1src) && (qs2p2s1p2 == qs2p2s1p2src); } /** * Get an indicator of which coordinate is not valid. * * @return The corresponding coordinate and the segment which it belongs. */ public AnalyzerPosition getResultIndex() { if (!valids1p1) { return AnalyzerPosition.SEGMENT_1_POINT_1; } else if (!valids1p2) { return AnalyzerPosition.SEGMENT_1_POINT_2; } else if (!valids2p1) { return AnalyzerPosition.SEGMENT_2_POINT_1; } else if (!valids2p2) { return AnalyzerPosition.SEGMENT_2_POINT_2; } else { return AnalyzerPosition.RESULTANT_NONE; } } }