I'm trying to use JTS and postgis for backend based on spring. While I know basics of JTS I don't know how to achieve
Asked
Active
Viewed 3,546 times
3 Answers
1
I wrote the following method that is capable of what you are asking for and uses JTS LineSegment objects to calculate the splitting points:
public ArrayList<LineString> splitLineStringIntoParts(LineString ls, double length){
// result list for linestrings
ArrayList<LineString> resultList = new ArrayList();
// list for linesegments from input linestring
ArrayList<LineSegment> lineSegmentList = new ArrayList();
// create LineSegment objects from input linestring and add them to list
for(int i = 1; i < ls.getCoordinates().length; i++){
lineSegmentList.add(new LineSegment(ls.getCoordinates()[i-1], ls.getCoordinates()[i]));
}
LineString currentLineString = null;
double neededLength = length;
for(LineSegment s : lineSegmentList){
while(s.getLength() > 0){
// case: current segment is small enough to be added to the linestring
if(s.getLength() <= neededLength){
// create linestring if it does not exist
if(currentLineString == null){
currentLineString = new GeometryFactory().createLineString(new Coordinate[]{new Coordinate(s.p0), new Coordinate(s.p1)});
// just add the new endpoint otherwise
} else {
Coordinate[] coords = new Coordinate[currentLineString.getCoordinates().length + 1];
// copy old coordinates
System.arraycopy(currentLineString.getCoordinates(), 0, coords, 0, currentLineString.getCoordinates().length);
// add new coordinate at the end
coords[coords.length-1] = new Coordinate(s.p1);
// create new linestring
currentLineString = new GeometryFactory().createLineString(coords);
}
neededLength -= s.getLength();
s.setCoordinates(s.p1, s.p1);
// add linestring to result list if needed length is 0
if(neededLength == 0){
resultList.add(currentLineString);
currentLineString = null;
neededLength = length;
}
// current segment needs to be cut and added to the linestring
} else {
// get coordinate at desired distance (endpoint of linestring)
Coordinate endPoint = s.pointAlong(neededLength/s.getLength());
// create linestring if it does not exist
if(currentLineString == null){
currentLineString = new GeometryFactory().createLineString(new Coordinate[]{new Coordinate(s.p0), endPoint});
// just add the new endpoint otherwise
} else {
// add new coordinate to linestring
Coordinate[] coords = new Coordinate[currentLineString.getCoordinates().length + 1];
// copy old coordinates
System.arraycopy(currentLineString.getCoordinates(), 0, coords, 0, currentLineString.getCoordinates().length);
// add new coordinate at the end
coords[coords.length-1] = endPoint;
currentLineString = new GeometryFactory().createLineString(coords);
}
// add linestring to result list
resultList.add(currentLineString);
// reset needed length
neededLength = length;
// reset current linestring
currentLineString = null;
// adjust segment (calculated endpoint is the new startpoint)
s.setCoordinates(endPoint, s.p1);
}
}
}
// add last linestring if there is a rest
if(neededLength < length){
resultList.add(currentLineString);
}
return resultList;
}

Lars
- 2,315
- 2
- 24
- 29
0
Simply use the Java implementation of geographiclib - I believe you want GeodesicLine; then use JTS and postgis to get the linestring coordinates you generate that way into postgresql. This geodesic path example in JavaScript should get you started.

jwd630
- 4,529
- 1
- 20
- 22
-
While this is helpful I don't really understand how to use this library for what I want. Ok, I can find intermediate points beetween two points. But I actually need to equally spread this points across LineString which have a lot of sections. So to find points beetween two points is just a part of solution. Can you provide more help? If not with actual code or links to the examples, then to resources where I could learn about all this asimuts, geodesic lines and stuff. – user1685095 Nov 06 '15 at 13:17
-
Sounds like you are going to need to use other objects/methods of geographiclib. You can use Geodesic.Inverse to compute the distance between pairs of your linestring's "sections" (what Inverse returns as s12). If that distance is > X meters then use Geodesic.Direct to find the coordinate X distance from the first to the second of your pair. One guesses you want to keep all the original linestring coordinates that defined the "sections" when the distance is < X. Perhaps you need to add more detail to the question and say what you have tried, as @Cássio suggested. – jwd630 Nov 10 '15 at 02:54
-
Frankly I hoped for simpler solution. I've already implemented this in python with shapely (which uses GEOS and GEOS AFAIK is a port of subset of JST functionality to C++) and pyproj. And it's like 6 lines of code. I don't understand why it's so hard in java when it's basically the same libraries behind all this. – user1685095 Nov 10 '15 at 08:18
0
i also need to write the split function,so i find solution on stackoverflow,but not find some useful information.so i write follow method and answer your question;
public List<LineString> lineSplit(LineString lineString,double meters) {
List<LineString> results = new ArrayList<>();
List<LineSegment> segments = new ArrayList<>();
// first split linestring to segements[]
for(int i = 1; i < lineString.getCoordinates().length; i++){
segments.add(new LineSegment(lineString.getCoordinates()[i-1], lineString.getCoordinates()[i]));
}
// remainLegnth means that last segment's length dont enough to split to one segement which length is meters
// neededLength means that current segment need how many meters to create a new segment
double remainLength = 0D;
double neededLength = 0D;
// remainCoors means that if the last iteartor dont create a new segment,also mean last segment
// is too short ,even add remains length can't create a new segment;so, we should add this segment's start
// point and end point to remainCoors
List<Coordinate> remainCoors = new ArrayList<>();
// netxStartPoint to store the next segment's start point
Coordinate netxStartPoint = null;
for(int i=0;i<segments.size();i++) {
LineSegment seg = segments.get(i);
neededLength = meters-remainLength;
remainLength += seg.getLength();
netxStartPoint = seg.p0;
while(remainLength>=meters) {
remainCoors.add(netxStartPoint);
Coordinate endPoint = seg.pointAlong(neededLength/seg.getLength());
// to remove the adjacent and same vertx
for(int j=0;j<remainCoors.size()-1;j++) {
if(remainCoors.get(j).equals(remainCoors.get(j+1))) {
remainCoors.remove(j);
}
}
remainCoors.add(endPoint);
results.add(lineString.getFactory().createLineString(remainCoors.toArray(new Coordinate[remainCoors.size()])));
remainCoors = new ArrayList<>();
netxStartPoint = endPoint;
remainLength -= meters;
neededLength += meters;
}
remainCoors.add(netxStartPoint);
remainCoors.add(seg.p1);
}
for(int j=0;j<remainCoors.size()-1;j++) {
if(remainCoors.get(j).equals(remainCoors.get(j+1))) {
remainCoors.remove(j);
}
}
if(remainCoors.size()>=2) {
results.add(lineString.getFactory().createLineString(remainCoors.toArray(new Coordinate[remainCoors.size()])));
}
return results;
}

FakeYuda
- 1
- 1