/*- * 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.List; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; public class HalfEdge extends BaseEntity { private static final Logger logger = LogManager.getLogger(HalfEdge.class); private static final boolean ALLOW_CIRCULAR_CHAINS = false; private Coordinate3d start; private Coordinate3d end; private HalfEdge partner; private HalfEdge next; public HalfEdge(Coordinate3d start, Coordinate3d end, EdgePolygon parent) { this.start = start; this.end = end; List halfEdgesToStart = start.getParents(HalfEdge.class); List halfEdgesToEnd = end.getParents(HalfEdge.class); HalfEdge tempPartner; if (parent == null) { tempPartner = findPartner(halfEdgesToStart, halfEdgesToEnd); } else { tempPartner = findPartner(parent, halfEdgesToStart, halfEdgesToEnd); } if (tempPartner != null) { setPartner(tempPartner); } addChild(start); addChild(end); } public HalfEdge(Coordinate3d start, Coordinate3d end) { this(start, end, null); } private HalfEdge findPartner(EdgePolygon parent, List halfEdgesToStart, List halfEdgesToEnd) { HalfEdge tempPartner = null; for (HalfEdge heStart : halfEdgesToStart) { for (HalfEdge heEnd : halfEdgesToEnd) { if (heStart == heEnd) { tempPartner = heStart; if (tempPartner.getPartner() == null) { EdgePolygon partnerParent = tempPartner.getPolygon(); if (partnerParent != null || partnerParent != parent) { return tempPartner; } } } } } return tempPartner; } private HalfEdge findPartner(List halfEdgesToStart, List halfEdgesToEnd) { HalfEdge tempPartner = null; for (HalfEdge heStart : halfEdgesToStart) { for (HalfEdge heEnd : halfEdgesToEnd) { if (heStart == heEnd) { tempPartner = heStart; if (tempPartner.getPartner() == null) { EdgePolygon partnerParent = tempPartner.getPolygon(); if (partnerParent != null) { return tempPartner; } } } } } return tempPartner; } public void setPartner(HalfEdge partner) { if (partner == this) { logger.debug("HalfEdge.setPartner() : cannot reference myself"); return; } if (null != this.partner) { if (null != partner) { if (ALLOW_CIRCULAR_CHAINS) { // check if the the partner already exists in the list of partners HalfEdge pNextPartner = this.partner; while (pNextPartner != this) { if (pNextPartner == partner) { logger.debug("(HalfEdge " + partner + " already exits in chain"); return; } pNextPartner = pNextPartner.partner; } // insert new partner in list partner.partner = this.partner; this.partner = partner; } else { logger.debug("Cannot overwrite existing partner-connection, set the connection to null first!"); } } else { // remove the existing connection this.partner.partner = null; this.partner = null; } } else { if (partner != null) { if (partner.partner != null) { if (ALLOW_CIRCULAR_CHAINS) { // this partner pointer is NULL and pPartner->mpPartner is not // NULL ==> insert this half edge in the chain of pPartner // first get the predecessor half edge of pPartner HalfEdge pNextPartner = partner.partner; HalfEdge pPreviousPartner = partner; while (pNextPartner != partner) { pPreviousPartner = pNextPartner; pNextPartner = pNextPartner.partner; } // insert new partner in list pPreviousPartner.partner = this; this.partner = partner; } else { /** * TODO : das riecht nach einer Ringverzeigerung : 3 Polygonraender treffen auf * einander */ logger.debug("Cannot overwrite existing partner-connection, set the connection to null first!"); } } else { this.partner = partner; partner.partner = this; } } } } public HalfEdge getPartner() { return partner; } public EdgePolygon getPolygon() { List polygons = getParents(EdgePolygon.class); if (!polygons.isEmpty()) { return polygons.get(0); } return null; } public GmBoundedStraight getStraight() { return GmBoundedStraight.of(start.getPoint(), end.getPoint()); } public Coordinate3d getStart() { return start; } public Coordinate3d getEnd() { return end; } public HalfEdge getNext() { return next; } public void setNext(HalfEdge next) { this.next = next; } @Override public String toString() { return "HalfEdge [start=" + start + ", end=" + end + "]"; } }