/* * Project: MoleCuilder * Description: creates and alters molecular systems * Copyright (C) 2010 University of Bonn. All rights reserved. * Please see the LICENSE file or "Copyright notice" in builder.cpp for details. */ /* * BoundaryPolygonSet.cpp * * Created on: Jul 29, 2010 * Author: heber */ // include config.h #ifdef HAVE_CONFIG_H #include #endif #include "CodePatterns/MemDebug.hpp" #include "BoundaryPolygonSet.hpp" #include #include "BoundaryLineSet.hpp" #include "BoundaryPointSet.hpp" #include "BoundaryTriangleSet.hpp" #include "TesselPoint.hpp" #include "CodePatterns/Assert.hpp" #include "CodePatterns/Info.hpp" #include "CodePatterns/Log.hpp" #include "CodePatterns/Verbose.hpp" #include "Helpers/helpers.hpp" #include "LinearAlgebra/Plane.hpp" #include "LinearAlgebra/Vector.hpp" using namespace std; /** Constructor for BoundaryPolygonSet. */ BoundaryPolygonSet::BoundaryPolygonSet() : Nr(-1) { Info FunctionInfo(__func__); } ; /** Destructor of BoundaryPolygonSet. * Just clears endpoints. * \note When removing triangles from a class Tesselation, use RemoveTesselationTriangle() */ BoundaryPolygonSet::~BoundaryPolygonSet() { Info FunctionInfo(__func__); endpoints.clear(); LOG(1, "Erasing polygon Nr." << Nr << " itself."); } ; /** Calculates the normal vector for this triangle. * Is made unique by comparison with \a OtherVector to point in the other direction. * \param &OtherVector direction vector to make normal vector unique. * \return allocated vector in normal direction */ Vector * BoundaryPolygonSet::GetNormalVector(const Vector &OtherVector) const { Info FunctionInfo(__func__); // get normal vector Vector TemporaryNormal; Vector *TotalNormal = new Vector; PointSet::const_iterator Runner[3]; for (int i = 0; i < 3; i++) { Runner[i] = endpoints.begin(); for (int j = 0; j < i; j++) { // go as much further Runner[i]++; if (Runner[i] == endpoints.end()) { ELOG(0, "There are less than three endpoints in the polygon!"); performCriticalExit(); } } } TotalNormal->Zero(); int counter = 0; for (; Runner[2] != endpoints.end();) { TemporaryNormal = Plane(((*Runner[0])->node->getPosition()), ((*Runner[1])->node->getPosition()), ((*Runner[2])->node->getPosition())).getNormal(); for (int i = 0; i < 3; i++) // increase each of them Runner[i]++; (*TotalNormal) += TemporaryNormal; } TotalNormal->Scale(1. / (double) counter); // make it always point inward (any offset vector onto plane projected onto normal vector suffices) if (TotalNormal->ScalarProduct(OtherVector) > 0.) TotalNormal->Scale(-1.); LOG(1, "Normal Vector is " << *TotalNormal << "."); return TotalNormal; } ; /** Calculates the center point of the triangle. * Is third of the sum of all endpoints. * \param *center central point on return. */ void BoundaryPolygonSet::GetCenter(Vector * const center) const { Info FunctionInfo(__func__); center->Zero(); int counter = 0; for(PointSet::const_iterator Runner = endpoints.begin(); Runner != endpoints.end(); Runner++) { (*center) += ((*Runner)->node->getPosition()); counter++; } center->Scale(1. / (double) counter); LOG(1, "Center is at " << *center << "."); } /** Checks whether the polygons contains all three endpoints of the triangle. * \param *triangle triangle to test * \return true - triangle is contained polygon, false - is not */ bool BoundaryPolygonSet::ContainsBoundaryTriangle(const BoundaryTriangleSet * const triangle) const { Info FunctionInfo(__func__); return ContainsPresentTupel(triangle->endpoints, 3); } ; /** Checks whether the polygons contains both endpoints of the line. * \param *line line to test * \return true - line is of the triangle, false - is not */ bool BoundaryPolygonSet::ContainsBoundaryLine(const BoundaryLineSet * const line) const { Info FunctionInfo(__func__); return ContainsPresentTupel(line->endpoints, 2); } ; /** Checks whether point is any of the three endpoints this triangle contains. * \param *point point to test * \return true - point is of the triangle, false - is not */ bool BoundaryPolygonSet::ContainsBoundaryPoint(const BoundaryPointSet * const point) const { Info FunctionInfo(__func__); for (PointSet::const_iterator Runner = endpoints.begin(); Runner != endpoints.end(); Runner++) { LOG(0, "Checking against " << **Runner); if (point == (*Runner)) { LOG(0, " Contained."); return true; } } LOG(0, " Not contained."); return false; } ; /** Checks whether point is any of the three endpoints this triangle contains. * \param *point TesselPoint to test * \return true - point is of the triangle, false - is not */ bool BoundaryPolygonSet::ContainsBoundaryPoint(const TesselPoint * const point) const { Info FunctionInfo(__func__); for (PointSet::const_iterator Runner = endpoints.begin(); Runner != endpoints.end(); Runner++) if (point == (*Runner)->node) { LOG(0, " Contained."); return true; } LOG(0, " Not contained."); return false; } ; /** Checks whether given array of \a *Points coincide with polygons's endpoints. * \param **Points pointer to an array of BoundaryPointSet * \param dim dimension of array * \return true - set of points is contained in polygon, false - is not */ bool BoundaryPolygonSet::ContainsPresentTupel(const BoundaryPointSet * const * Points, const int dim) const { Info FunctionInfo(__func__); int counter = 0; LOG(1, "Polygon is " << *this); for (int i = 0; i < dim; i++) { LOG(1, " Testing endpoint " << *Points[i]); if (ContainsBoundaryPoint(Points[i])) { counter++; } } if (counter == dim) return true; else return false; } ; /** Checks whether given PointList coincide with polygons's endpoints. * \param &endpoints PointList * \return true - set of points is contained in polygon, false - is not */ bool BoundaryPolygonSet::ContainsPresentTupel(const PointSet &endpoints) const { Info FunctionInfo(__func__); size_t counter = 0; LOG(1, "Polygon is " << *this); for (PointSet::const_iterator Runner = endpoints.begin(); Runner != endpoints.end(); Runner++) { LOG(1, " Testing endpoint " << **Runner); if (ContainsBoundaryPoint(*Runner)) counter++; } if (counter == endpoints.size()) return true; else return false; } ; /** Checks whether given set of \a *Points coincide with polygons's endpoints. * \param *P pointer to BoundaryPolygonSet * \return true - is the very triangle, false - is not */ bool BoundaryPolygonSet::ContainsPresentTupel(const BoundaryPolygonSet * const P) const { return ContainsPresentTupel((const PointSet) P->endpoints); } ; /** Gathers all the endpoints' triangles in a unique set. * \return set of all triangles */ TriangleSet * BoundaryPolygonSet::GetAllContainedTrianglesFromEndpoints() const { Info FunctionInfo(__func__); pair Tester; TriangleSet *triangles = new TriangleSet; for (PointSet::const_iterator Runner = endpoints.begin(); Runner != endpoints.end(); Runner++) for (LineMap::const_iterator Walker = (*Runner)->lines.begin(); Walker != (*Runner)->lines.end(); Walker++) for (TriangleMap::const_iterator Sprinter = (Walker->second)->triangles.begin(); Sprinter != (Walker->second)->triangles.end(); Sprinter++) { //LOG(0, " Testing triangle " << *(Sprinter->second)); if (ContainsBoundaryTriangle(Sprinter->second)) { Tester = triangles->insert(Sprinter->second); if (Tester.second) LOG(0, "Adding triangle " << *(Sprinter->second)); } } LOG(1, "The Polygon of " << endpoints.size() << " endpoints has " << triangles->size() << " unique triangles in total."); return triangles; } ; /** Fills the endpoints of this polygon from the triangles attached to \a *line. * \param *line lines with triangles attached * \return true - polygon contains endpoints, false - line was NULL */ bool BoundaryPolygonSet::FillPolygonFromTrianglesOfLine(const BoundaryLineSet * const line) { Info FunctionInfo(__func__); pair Tester; if (line == NULL) return false; LOG(1, "Filling polygon from line " << *line); for (TriangleMap::const_iterator Runner = line->triangles.begin(); Runner != line->triangles.end(); Runner++) { for (int i = 0; i < 3; i++) { Tester = endpoints.insert((Runner->second)->endpoints[i]); if (Tester.second) LOG(1, " Inserting endpoint " << *((Runner->second)->endpoints[i])); } } return true; } ; /** output operator for BoundaryPolygonSet. * \param &ost output stream * \param &a boundary polygon */ ostream &operator <<(ostream &ost, const BoundaryPolygonSet &a) { ost << "[" << a.Nr << "|"; for (PointSet::const_iterator Runner = a.endpoints.begin(); Runner != a.endpoints.end();) { ost << (*Runner)->node->getName(); Runner++; if (Runner != a.endpoints.end()) ost << ","; } ost << "]"; return ost; } ;