/*- * 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; } }