package com.gisgraphy.helper; import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.GeometryFactory; import com.vividsolutions.jts.geom.LineString; import com.vividsolutions.jts.geom.Point; public class OrthogonalProjection { private final static GeometryFactory geomFact = new GeometryFactory(); public DistancePointDto getPointOnLine(LineString line,Point point){ double distance = 99999999; Point res = point; if(line!=null && point !=null){ Coordinate[] coordinates = line.getCoordinates(); for (int i=0;i< coordinates.length-1;i++){ Coordinate coordinate = coordinates[i]; if (coordinate==null){ continue; }else { Point proj = projects(coordinates[i], coordinates[i+1], point.getCoordinate()); double px = point.getX(); double py = point.getY(); double dist = Math.sqrt( Math.pow(px-proj.getX(), 2) + Math.pow(py-proj.getY(), 2) ); if (dist < distance){ distance =dist;//approx res=proj; } } } try { Point pd1 = GeolocHelper.createPoint(res.getX(), res.getY()); distance = GeolocHelper.distance(pd1, point);//more precise } catch (IllegalArgumentException e) { //ignore in case lat and long are not in range } return new DistancePointDto(res, distance); } return new DistancePointDto(res, 0D); } public Point projects(Point LinePoint1, Point LinePoint2, Point point){ if (LinePoint1==null || LinePoint2==null || point ==null){ return point; } Coordinate p1 = LinePoint1.getCoordinate(); Coordinate p2 = LinePoint2.getCoordinate(); Coordinate p = point.getCoordinate(); double bx = p1.x-p2.x; double by=p1.y-p2.y; double sq = bx*bx+by*by; double scale = 0; if (sq >0){ scale = ((p.x - p2.x)*bx + (p.y - p2.y)*by ) / sq; } if (scale <=0){ bx=p2.x; by=p2.y; } else if (scale >=1){ bx=p1.x; by=p1.y; } else { bx = bx*scale + p2.x; by = by*scale + p2.y; } System.out.println("bx="+bx+" by="+by); return geomFact.createPoint(new Coordinate(bx, by)); /*function algo( v, u, p ){ var bx = v[0] - u[0]; var by = v[1] - u[1]; var sq = bx*bx + by*by; var scale = ( sq > 0 ) ? (( (p[0] - u[0])*bx + (p[1] - u[1])*by ) / sq) : 0.0; if( scale <= 0.0 ){ bx = u[0]; by = u[1]; } else if( scale >= 1.0 ){ bx = v[0]; by = v[1]; } else { bx = bx*scale + u[0]; by = by*scale + u[1]; } return [bx, by]; }*/ } public Point projects(Coordinate p1, Coordinate p2, Coordinate p){ if (p1==null || p2==null || p ==null){ return null; } double bx = p1.x-p2.x; double by=p1.y-p2.y; double sq = bx*bx+by*by; double scale = 0; if (sq >0){ scale = ((p.x - p2.x)*bx + (p.y - p2.y)*by ) / sq; } if (scale <=0){ bx=p2.x; by=p2.y; } else if (scale >=1){ bx=p1.x; by=p1.y; } else { bx = bx*scale + p2.x; by = by*scale + p2.y; } System.out.println("bx="+bx+" by="+by); return geomFact.createPoint(new Coordinate(bx, by)); /*function algo( v, u, p ){ var bx = v[0] - u[0]; var by = v[1] - u[1]; var sq = bx*bx + by*by; var scale = ( sq > 0 ) ? (( (p[0] - u[0])*bx + (p[1] - u[1])*by ) / sq) : 0.0; if( scale <= 0.0 ){ bx = u[0]; by = u[1]; } else if( scale >= 1.0 ){ bx = v[0]; by = v[1]; } else { bx = bx*scale + u[0]; by = by*scale + u[1]; } return [bx, by]; }*/ } public static void main(String[] args) { OrthogonalProjection orth = new OrthogonalProjection(); Point p1 = geomFact.createPoint(new Coordinate(170, 150)); Point p2 = geomFact.createPoint(new Coordinate(210, 170)); Point p = geomFact.createPoint(new Coordinate(150, 250)); // orth.projects(p1, p2, p); //[50,50],[170,150],[210,170],[250,170],[290,160],[330,140],[410,100],[550,50],[750,30] Coordinate[] coordinates = new Coordinate[]{new Coordinate(50,50),new Coordinate(170,150),new Coordinate(210,170),new Coordinate(250,170),new Coordinate(290,160)}; LineString line = geomFact.createLineString(coordinates); DistancePointDto orthpoPoint = orth.getPointOnLine(line, p); System.out.println(orthpoPoint); coordinates = new Coordinate[]{new Coordinate(-0.5800364, 44.841225),new Coordinate(2.3514992, 48.8566101)}; line = geomFact.createLineString(coordinates); p= geomFact.createPoint(new Coordinate(0.340196, 46.5802596)); orthpoPoint = orth.getPointOnLine(line, p); System.out.println(orthpoPoint); Point pd1 = GeolocHelper.createPoint(0.5681100788863813, 46.413865040236196); Point pd2 = GeolocHelper.createPoint(46.5802596,0.340196 ); System.out.println(GeolocHelper.distance(pd1, p)); } }