/*
* This is part of Geomajas, a GIS framework, http://www.geomajas.org/.
*
* Copyright 2008-2015 Geosparc nv, http://www.geosparc.com/, Belgium.
*
* The program is available in open source according to the GNU Affero
* General Public License. All contributions in this program are covered
* by the Geomajas Contributors License Agreement. For full licensing
* details, see LICENSE.txt in the project root.
*/
package org.geomajas.plugin.editing.client.snap.algorithm;
import org.geomajas.annotation.Api;
import org.geomajas.geometry.Coordinate;
import org.geomajas.geometry.Geometry;
import org.geomajas.geometry.service.MathService;
import org.geomajas.plugin.editing.client.snap.SnapAlgorithm;
/**
* <p> Snapping algorithm that snaps to both end-points and any point on an edge of intersecting geometries. Only
* geometries with closed rings that actually intersect the given coordinate are considered for snapping. All other
* geometries are discarded. </p>
*
* @author Pieter De Graef
* @since 2.0.0
*/
@Api(allMethods = true)
public class NearestEdgeOfIntersection implements SnapAlgorithm {
private Geometry[] geometries;
private double calculatedDistance;
private boolean hasSnapped;
// ------------------------------------------------------------------------
// SnappingAlgorithm implementation:
// ------------------------------------------------------------------------
/**
* Execute the snap operation.
*
* @param coordinate The original location.
* @param distance The maximum distance allowed for snapping.
* @return The new location. If no snapping target was found, this may return the original location.
*/
public Coordinate snap(Coordinate coordinate, double distance) {
// Some initialization:
calculatedDistance = distance;
hasSnapped = false;
Coordinate snappingPoint = coordinate;
// Go over all rings and consider only the intersecting ones:
for (Geometry geometry : geometries) {
if (MathService.isWithin(geometry, coordinate)) {
NearestEdgeSnapAlgorithm nearestEdge = new NearestEdgeSnapAlgorithm();
nearestEdge.setGeometries(new Geometry[] { geometry });
Coordinate temp = nearestEdge.snap(coordinate, calculatedDistance);
if (nearestEdge.hasSnapped()) {
hasSnapped = true;
calculatedDistance = nearestEdge.getCalculatedDistance();
snappingPoint = temp;
}
}
}
return snappingPoint;
}
/**
* Set the full list of target geometries. These are the geometries where to this snapping algorithm can snap.
*
* @param geometries The list of target geometries.
*/
public void setGeometries(Geometry[] geometries) {
this.geometries = geometries;
}
/**
* Get the effective distance that was bridged during the snap operation. In case snapping occurred, this distance
* will be smaller than the given "distance" value during the last call to snap.
*
* @return The effective snapping distance. Only valid if snapping actually occurred.
*/
public double getCalculatedDistance() {
return calculatedDistance;
}
/**
* Has snapping actually occurred during the last call to the <code>snap</code> method? If so the returned snap
* location was different from the original location.
*
* @return Returns if the returned location from the snap method differs from the original location.
*/
public boolean hasSnapped() {
return hasSnapped;
}
}