package oripa.paint.geometry;
import java.awt.geom.Point2D;
import java.util.Collection;
import javax.vecmath.Vector2d;
import oripa.ORIPA;
import oripa.paint.core.PaintConfig;
import oripa.paint.core.PaintContext;
import oripa.value.OriLine;
public class NearestVertexFinder {
/**
*
* Note that {@code nearest} will be affected.
* @param p target point
* @param nearest current nearest point to p
* @param other new point to be tested
*
* @return nearest point to p
*/
private static void findNearestOf(
Point2D.Double p, NearestPoint nearest, Vector2d other){
double dist = p.distance(other.x, other.y);
if (dist < nearest.distance) {
nearest.point = other;
nearest.distance = dist;
}
}
public static Vector2d findNearestOf(
Point2D.Double p, Vector2d nearest, Vector2d other){
NearestPoint nearestPoint = new NearestPoint();
nearestPoint.point = nearest;
nearestPoint.distance = p.distance(nearest.x, nearest.y);
NearestVertexFinder.findNearestOf(
p, nearestPoint, other);
return nearest;
}
private static NearestPoint findNearestVertexFromLines(
Point2D.Double p, Collection<OriLine> lines){
NearestPoint minPosition = new NearestPoint();
for (OriLine line : lines) {
findNearestOf(p, minPosition, line.p0);
findNearestOf(p, minPosition, line.p1);
}
return minPosition;
}
/**
* Find the nearest of p among vertices
* @param p
* @param vertices
* @return nearest point
*/
private static NearestPoint findNearestVertex(Point2D.Double p, Collection<Vector2d> vertices){
NearestPoint minPosition = new NearestPoint();
for(Vector2d vertex : vertices){
findNearestOf(p, minPosition, vertex);
}
return minPosition;
}
/**
* find the nearest of current mouse point in the circle whose radius = {@code distance}.
* @param context
* @param distance
* @return nearestPoint in the limit. null if there are no such vertex.
*/
public static NearestPoint findAround(PaintContext context, double distance){
NearestPoint nearestPosition = new NearestPoint();
Point2D.Double currentPoint = context.getLogicalMousePoint();
Collection<Collection<Vector2d>> vertices = ORIPA.doc.getVerticesArea(
currentPoint.x, currentPoint.y, distance);
for(Collection<Vector2d> locals : vertices){
NearestPoint nearest;
nearest = findNearestVertex(currentPoint, locals);
if(nearest.distance < nearestPosition.distance){
nearestPosition = nearest;
}
}
if (context.dispGrid) {
NearestPoint nearestGrid = findNearestVertex(
currentPoint, context.updateGrids(PaintConfig.gridDivNum));
if(nearestGrid.distance < nearestPosition.distance){
nearestPosition = nearestGrid;
}
}
if (nearestPosition.distance >= distance) {
return null;
}
else {
// System.out.println("#area " + vertices.size() +
// ", #v(area1) " + vertices.iterator().next().size() +
// ", scaled limit = " + distance);
}
return nearestPosition;
}
public static NearestPoint findFromPickedLine(PaintContext context){
NearestPoint nearestPosition;
Point2D.Double currentPoint = context.getLogicalMousePoint();
nearestPosition = findNearestVertexFromLines(
currentPoint, context.getLines());
return nearestPosition;
}
}