/*-
* Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart
*
* This file is part of CityDoctor2.
*
* CityDoctor2 is free software: 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, either version 3 of the License, or
* (at your option) any later version.
*
* CityDoctor2 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.
*
* You should have received a copy of the GNU Lesser General Public License
* along with CityDoctor2. If not, see .
*/
package de.hft.stuttgart.citydoctor2.edge;
import java.util.ArrayList;
import java.util.List;
public class PolyLine2d extends BaseEntity {
private PolyLineSegment2d mpFirst;
private PolyLineSegment2d mpLast;
public PolyLine2d(PolyLineSegment2d pStart) {
mpFirst = mpLast = pStart;
addChild(mpFirst);
while (mpLast.getNext() != null) {
addChild(mpLast.getNext());
mpLast = mpLast.getNext();
}
}
public PolyLine2d(Coordinate2d pVertex1, Coordinate2d pVertex2) {
PolyLineSegment2d pSegment = new PolyLineSegment2d(pVertex1, pVertex2);
mpFirst = mpLast = pSegment;
addChild(pSegment);
}
public List getCoordinates() {
List coordinates = new ArrayList<>();
if (mpFirst != null) {
PolyLineSegment2d pSegment = mpFirst;
coordinates.add(pSegment.getStart());
while (pSegment != null) {
coordinates.add(pSegment.getEnd());
pSegment = pSegment.getNext();
}
}
return coordinates;
}
public PolyLineSegment2d getFirstSegment() {
return mpFirst;
}
public PolyLineSegment2d getLastSegment() {
return mpLast;
}
public Coordinate2d getStart() {
return mpFirst.getStart();
}
public Coordinate2d getEnd() {
return mpLast.getEnd();
}
public List getSegments() {
List segments = new ArrayList<>();
PolyLineSegment2d pSegment = mpFirst;
while (pSegment != null) {
segments.add(pSegment);
pSegment = pSegment.getNext();
}
return segments;
}
public PolyLine2d append(PolyLine2d pSecondLine) {
// append the end-vertices to the current line
PolyLineSegment2d pSecondStart = pSecondLine.getFirstSegment();
while (pSecondStart != null) {
append(pSecondStart.getEnd());
pSecondStart = pSecondStart.getNext();
}
return pSecondLine;
}
private Coordinate2d append(Coordinate2d pVertex) {
// check if the polyline already contains segments
// -----------------------------------------------
PolyLineSegment2d pNewSegment = new PolyLineSegment2d(getEnd(), pVertex);
addChild(pNewSegment);
mpLast.setNext(pNewSegment);
mpLast = pNewSegment;
return pVertex;
}
/**
* Split a polyline at a vertex that is already part of the polyline. The
* original PolyLine will be split, and the right fragment will be returned. The
* original PolyLine will hold the left fragment
*
* @param pVertex
* @return
*/
public PolyLine2d split(Coordinate2d pVertex) {
PolyLineSegment2d seg = mpFirst;
PolyLineSegment2d leftLast = null;
PolyLineSegment2d rightFirst = null;
for (; seg != null; seg = seg.getNext()) {
if (seg.getEnd() == pVertex) {
leftLast = seg;
rightFirst = seg.getNext();
break;
}
}
if (leftLast == null) {
throw new IllegalArgumentException("vertex is not part of polyline");
}
List segmentsToRemove = new ArrayList<>();
PolyLineSegment2d pToRemove = rightFirst;
while (pToRemove != null) {
segmentsToRemove.add(pToRemove);
pToRemove = pToRemove.getNext();
}
// terminate this polyline
// -----------------------
leftLast.setNext(null);
mpLast = leftLast;
PolyLine2d pRightLine = new PolyLine2d(rightFirst);
// De-refernence all unused segments from this line
// ------------------------------------------------
for (PolyLineSegment2d itTR : segmentsToRemove) {
removeChild(itTR);
}
return pRightLine;
}
}