source: src/Tesselation/boundary.cpp@ 2bfc5b

Action_Thermostats Add_AtomRandomPerturbation Add_FitFragmentPartialChargesAction Add_RotateAroundBondAction Add_SelectAtomByNameAction Added_ParseSaveFragmentResults AddingActions_SaveParseParticleParameters Adding_Graph_to_ChangeBondActions Adding_MD_integration_tests Adding_ParticleName_to_Atom Adding_StructOpt_integration_tests AtomFragments Automaking_mpqc_open AutomationFragmentation_failures Candidate_v1.5.4 Candidate_v1.6.0 Candidate_v1.6.1 ChangeBugEmailaddress ChangingTestPorts ChemicalSpaceEvaluator CombiningParticlePotentialParsing Combining_Subpackages Debian_Package_split Debian_package_split_molecuildergui_only Disabling_MemDebug Docu_Python_wait EmpiricalPotential_contain_HomologyGraph EmpiricalPotential_contain_HomologyGraph_documentation Enable_parallel_make_install Enhance_userguide Enhanced_StructuralOptimization Enhanced_StructuralOptimization_continued Example_ManyWaysToTranslateAtom Exclude_Hydrogens_annealWithBondGraph FitPartialCharges_GlobalError Fix_BoundInBox_CenterInBox_MoleculeActions Fix_ChargeSampling_PBC Fix_ChronosMutex Fix_FitPartialCharges Fix_FitPotential_needs_atomicnumbers Fix_ForceAnnealing Fix_IndependentFragmentGrids Fix_ParseParticles Fix_ParseParticles_split_forward_backward_Actions Fix_PopActions Fix_QtFragmentList_sorted_selection Fix_Restrictedkeyset_FragmentMolecule Fix_StatusMsg Fix_StepWorldTime_single_argument Fix_Verbose_Codepatterns Fix_fitting_potentials Fixes ForceAnnealing_goodresults ForceAnnealing_oldresults ForceAnnealing_tocheck ForceAnnealing_with_BondGraph ForceAnnealing_with_BondGraph_continued ForceAnnealing_with_BondGraph_continued_betteresults ForceAnnealing_with_BondGraph_contraction-expansion FragmentAction_writes_AtomFragments FragmentMolecule_checks_bonddegrees GeometryObjects Gui_Fixes Gui_displays_atomic_force_velocity ImplicitCharges IndependentFragmentGrids IndependentFragmentGrids_IndividualZeroInstances IndependentFragmentGrids_IntegrationTest IndependentFragmentGrids_Sole_NN_Calculation JobMarket_RobustOnKillsSegFaults JobMarket_StableWorkerPool JobMarket_unresolvable_hostname_fix MoreRobust_FragmentAutomation ODR_violation_mpqc_open PartialCharges_OrthogonalSummation PdbParser_setsAtomName PythonUI_with_named_parameters QtGui_reactivate_TimeChanged_changes Recreated_GuiChecks Rewrite_FitPartialCharges RotateToPrincipalAxisSystem_UndoRedo SaturateAtoms_findBestMatching SaturateAtoms_singleDegree StoppableMakroAction Subpackage_CodePatterns Subpackage_JobMarket Subpackage_LinearAlgebra Subpackage_levmar Subpackage_mpqc_open Subpackage_vmg Switchable_LogView ThirdParty_MPQC_rebuilt_buildsystem TrajectoryDependenant_MaxOrder TremoloParser_IncreasedPrecision TremoloParser_MultipleTimesteps TremoloParser_setsAtomName Ubuntu_1604_changes stable
Last change on this file since 2bfc5b was ada8df, checked in by Frederik Heber <heber@…>, 9 years ago

Removed FindEmbeddingHole which lacked implementation so far.

  • Property mode set to 100644
File size: 39.9 KB
RevLine 
[bcf653]1/*
2 * Project: MoleCuilder
3 * Description: creates and alters molecular systems
[0aa122]4 * Copyright (C) 2010-2012 University of Bonn. All rights reserved.
[5aaa43]5 * Copyright (C) 2013 Frederik Heber. All rights reserved.
[94d5ac6]6 *
7 *
8 * This file is part of MoleCuilder.
9 *
10 * MoleCuilder is free software: you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation, either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * MoleCuilder is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with MoleCuilder. If not, see <http://www.gnu.org/licenses/>.
[bcf653]22 */
23
[f66195]24/** \file boundary.cpp
[edb93c]25 *
26 * Implementations and super-function for envelopes
[2319ed]27 */
28
[bf3817]29// include config.h
30#ifdef HAVE_CONFIG_H
31#include <config.h>
32#endif
33
[ad011c]34#include "CodePatterns/MemDebug.hpp"
[112b09]35
[6f0841]36#include "Atom/atom.hpp"
[129204]37#include "Bond/bond.hpp"
[8eb17a]38#include "boundary.hpp"
[34c43a]39#include "BoundaryLineSet.hpp"
40#include "BoundaryPointSet.hpp"
41#include "BoundaryTriangleSet.hpp"
42#include "Box.hpp"
43#include "CandidateForTesselation.hpp"
44#include "CodePatterns/Info.hpp"
45#include "CodePatterns/Log.hpp"
46#include "CodePatterns/Verbose.hpp"
[f66195]47#include "config.hpp"
[3bdb6d]48#include "Element/element.hpp"
[34c43a]49#include "LinearAlgebra/Plane.hpp"
50#include "LinearAlgebra/RealSpaceMatrix.hpp"
[53c7fc]51#include "LinkedCell/linkedcell.hpp"
52#include "LinkedCell/PointCloudAdaptor.hpp"
[f66195]53#include "molecule.hpp"
[34c43a]54#include "RandomNumbers/RandomNumberGeneratorFactory.hpp"
55#include "RandomNumbers/RandomNumberGenerator.hpp"
[f66195]56#include "tesselation.hpp"
57#include "tesselationhelpers.hpp"
[b34306]58#include "World.hpp"
[2319ed]59
[986ed3]60#include <iostream>
[36166d]61#include <iomanip>
62
[357fba]63#include<gsl/gsl_poly.h>
[d6eb80]64#include<time.h>
[2319ed]65
[357fba]66// ========================================== F U N C T I O N S =================================
[2319ed]67
68
[357fba]69/** Determines greatest diameters of a cluster defined by its convex envelope.
70 * Looks at lines parallel to one axis and where they intersect on the projected planes
[2319ed]71 * \param *out output stream for debugging
[357fba]72 * \param *BoundaryPoints NDIM set of boundary points defining the convex envelope on each projected plane
73 * \param *mol molecule structure representing the cluster
[776b64]74 * \param *&TesselStruct Tesselation structure with triangles
[357fba]75 * \param IsAngstroem whether we have angstroem or atomic units
76 * \return NDIM array of the diameters
[e4ea46]77 */
[e138de]78double *GetDiametersOfCluster(const Boundaries *BoundaryPtr, const molecule *mol, Tesselation *&TesselStruct, const bool IsAngstroem)
[caf5d6]79{
[ce7bfd]80 //Info FunctionInfo(__func__);
[357fba]81 // get points on boundary of NULL was given as parameter
82 bool BoundaryFreeFlag = false;
[ad37ab]83 double OldComponent = 0.;
84 double tmp = 0.;
85 double w1 = 0.;
86 double w2 = 0.;
87 Vector DistanceVector;
88 Vector OtherVector;
89 int component = 0;
90 int Othercomponent = 0;
[776b64]91 Boundaries::const_iterator Neighbour;
92 Boundaries::const_iterator OtherNeighbour;
[ad37ab]93 double *GreatestDiameter = new double[NDIM];
94
[776b64]95 const Boundaries *BoundaryPoints;
96 if (BoundaryPtr == NULL) {
[357fba]97 BoundaryFreeFlag = true;
[e138de]98 BoundaryPoints = GetBoundaryPoints(mol, TesselStruct);
[86234b]99 } else {
[776b64]100 BoundaryPoints = BoundaryPtr;
[47d041]101 LOG(0, "Using given boundary points set.");
[86234b]102 }
[357fba]103 // determine biggest "diameter" of cluster for each axis
104 for (int i = 0; i < NDIM; i++)
105 GreatestDiameter[i] = 0.;
106 for (int axis = 0; axis < NDIM; axis++)
107 { // regard each projected plane
[47d041]108 //LOG(1, "Current axis is " << axis << ".");
[357fba]109 for (int j = 0; j < 2; j++)
110 { // and for both axis on the current plane
111 component = (axis + j + 1) % NDIM;
112 Othercomponent = (axis + 1 + ((j + 1) & 1)) % NDIM;
[47d041]113 //LOG(1, "Current component is " << component << ", Othercomponent is " << Othercomponent << ".");
[776b64]114 for (Boundaries::const_iterator runner = BoundaryPoints[axis].begin(); runner != BoundaryPoints[axis].end(); runner++) {
[47d041]115 //LOG(1, "Current runner is " << *(runner->second.second) << ".");
[357fba]116 // seek for the neighbours pair where the Othercomponent sign flips
117 Neighbour = runner;
118 Neighbour++;
119 if (Neighbour == BoundaryPoints[axis].end()) // make it wrap around
120 Neighbour = BoundaryPoints[axis].begin();
[d74077]121 DistanceVector = (runner->second.second->getPosition()) - (Neighbour->second.second->getPosition());
[776b64]122 do { // seek for neighbour pair where it flips
[0a4f7f]123 OldComponent = DistanceVector[Othercomponent];
[357fba]124 Neighbour++;
125 if (Neighbour == BoundaryPoints[axis].end()) // make it wrap around
126 Neighbour = BoundaryPoints[axis].begin();
[d74077]127 DistanceVector = (runner->second.second->getPosition()) - (Neighbour->second.second->getPosition());
[47d041]128 //LOG(2, "OldComponent is " << OldComponent << ", new one is " << DistanceVector.x[Othercomponent] << ".");
[776b64]129 } while ((runner != Neighbour) && (fabs(OldComponent / fabs(
[0a4f7f]130 OldComponent) - DistanceVector[Othercomponent] / fabs(
131 DistanceVector[Othercomponent])) < MYEPSILON)); // as long as sign does not flip
[776b64]132 if (runner != Neighbour) {
[357fba]133 OtherNeighbour = Neighbour;
134 if (OtherNeighbour == BoundaryPoints[axis].begin()) // make it wrap around
135 OtherNeighbour = BoundaryPoints[axis].end();
136 OtherNeighbour--;
[47d041]137 //LOG(1, "The pair, where the sign of OtherComponent flips, is: " << *(Neighbour->second.second) << " and " << *(OtherNeighbour->second.second) << ".");
[357fba]138 // now we have found the pair: Neighbour and OtherNeighbour
[d74077]139 OtherVector = (runner->second.second->getPosition()) - (OtherNeighbour->second.second->getPosition());
[47d041]140 //LOG(1, "Distances to Neighbour and OtherNeighbour are " << DistanceVector.x[component] << " and " << OtherVector.x[component] << ".");
141 //LOG(1, "OtherComponents to Neighbour and OtherNeighbour are " << DistanceVector.x[Othercomponent] << " and " << OtherVector.x[Othercomponent] << ".");
[357fba]142 // do linear interpolation between points (is exact) to extract exact intersection between Neighbour and OtherNeighbour
[0a4f7f]143 w1 = fabs(OtherVector[Othercomponent]);
144 w2 = fabs(DistanceVector[Othercomponent]);
145 tmp = fabs((w1 * DistanceVector[component] + w2
146 * OtherVector[component]) / (w1 + w2));
[357fba]147 // mark if it has greater diameter
[47d041]148 //LOG(1, "Comparing current greatest " << GreatestDiameter[component] << " to new " << tmp << ".");
[357fba]149 GreatestDiameter[component] = (GreatestDiameter[component]
150 > tmp) ? GreatestDiameter[component] : tmp;
151 } //else
[47d041]152 //LOG(1, "Saw no sign flip, probably top or bottom node.");
[3d919e]153 }
154 }
155 }
[47d041]156 LOG(0, "RESULT: The biggest diameters are "
[357fba]157 << GreatestDiameter[0] << " and " << GreatestDiameter[1] << " and "
158 << GreatestDiameter[2] << " " << (IsAngstroem ? "angstrom"
[47d041]159 : "atomiclength") << ".");
[03648b]160
[357fba]161 // free reference lists
162 if (BoundaryFreeFlag)
163 delete[] (BoundaryPoints);
[e4ea46]164
[357fba]165 return GreatestDiameter;
[e4ea46]166}
167;
[03648b]168
[042f82]169
[357fba]170/** Determines the boundary points of a cluster.
171 * Does a projection per axis onto the orthogonal plane, transforms into spherical coordinates, sorts them by the angle
172 * and looks at triples: if the middle has less a distance than the allowed maximum height of the triangle formed by the plane's
173 * center and first and last point in the triple, it is thrown out.
[f01769]174 *
175 * \todo When storing const ptrs in tesselation structures, remove const_cast
176 *
[357fba]177 * \param *out output stream for debugging
178 * \param *mol molecule structure representing the cluster
[776b64]179 * \param *&TesselStruct pointer to Tesselation structure
[e4ea46]180 */
[e138de]181Boundaries *GetBoundaryPoints(const molecule *mol, Tesselation *&TesselStruct)
[caf5d6]182{
[ce7bfd]183 //Info FunctionInfo(__func__);
[357fba]184 PointMap PointsOnBoundary;
185 LineMap LinesOnBoundary;
186 TriangleMap TrianglesOnBoundary;
[833b15]187 Vector MolCenter = mol->DetermineCenterOfAll();
[357fba]188 Vector helper;
[ad37ab]189 BoundariesTestPair BoundaryTestPair;
190 Vector AxisVector;
191 Vector AngleReferenceVector;
192 Vector AngleReferenceNormalVector;
193 Vector ProjectedVector;
[5309ba]194 Boundaries *BoundaryPoints = new Boundaries[NDIM]; // first is alpha, second is (r, Nr)
[ad37ab]195 double angle = 0.;
[042f82]196
[357fba]197 // 3a. Go through every axis
198 for (int axis = 0; axis < NDIM; axis++) {
199 AxisVector.Zero();
200 AngleReferenceVector.Zero();
201 AngleReferenceNormalVector.Zero();
[0a4f7f]202 AxisVector[axis] = 1.;
203 AngleReferenceVector[(axis + 1) % NDIM] = 1.;
204 AngleReferenceNormalVector[(axis + 2) % NDIM] = 1.;
[042f82]205
[47d041]206 LOG(1, "Axisvector is " << AxisVector << " and AngleReferenceVector is " << AngleReferenceVector << ", and AngleReferenceNormalVector is " << AngleReferenceNormalVector << ".");
[042f82]207
[357fba]208 // 3b. construct set of all points, transformed into cylindrical system and with left and right neighbours
[59fff1]209 // Boundaries stores non-const TesselPoint ref, hence we need iterator here
[f01769]210 for (molecule::const_iterator iter = mol->begin(); iter != mol->end(); ++iter) {
[833b15]211 ProjectedVector = (*iter)->getPosition() - (MolCenter);
[273382]212 ProjectedVector.ProjectOntoPlane(AxisVector);
[042f82]213
[357fba]214 // correct for negative side
[776b64]215 const double radius = ProjectedVector.NormSquared();
[357fba]216 if (fabs(radius) > MYEPSILON)
[273382]217 angle = ProjectedVector.Angle(AngleReferenceVector);
[357fba]218 else
219 angle = 0.; // otherwise it's a vector in Axis Direction and unimportant for boundary issues
[042f82]220
[47d041]221 //LOG(1, "Checking sign in quadrant : " << ProjectedVector.Projection(&AngleReferenceNormalVector) << ".");
[273382]222 if (ProjectedVector.ScalarProduct(AngleReferenceNormalVector) > 0) {
[357fba]223 angle = 2. * M_PI - angle;
224 }
[47d041]225 LOG(1, "Inserting " << **iter << ": (r, alpha) = (" << radius << "," << angle << "): " << ProjectedVector);
[f01769]226 BoundaryTestPair = BoundaryPoints[axis].insert(
227 BoundariesPair(angle, TesselPointDistancePair (radius, const_cast<atom *>(*iter))));
[357fba]228 if (!BoundaryTestPair.second) { // same point exists, check first r, then distance of original vectors to center of gravity
[47d041]229 LOG(2, "Encountered two vectors whose projection onto axis " << axis << " is equal: ");
230 LOG(2, "Present vector: " << *BoundaryTestPair.first->second.second);
231 LOG(2, "New vector: " << **iter);
[776b64]232 const double ProjectedVectorNorm = ProjectedVector.NormSquared();
233 if ((ProjectedVectorNorm - BoundaryTestPair.first->second.first) > MYEPSILON) {
234 BoundaryTestPair.first->second.first = ProjectedVectorNorm;
[f01769]235 BoundaryTestPair.first->second.second = const_cast<atom *>(*iter);
[47d041]236 LOG(2, "Keeping new vector due to larger projected distance " << ProjectedVectorNorm << ".");
[776b64]237 } else if (fabs(ProjectedVectorNorm - BoundaryTestPair.first->second.first) < MYEPSILON) {
[833b15]238 helper = (*iter)->getPosition() - (MolCenter);
[776b64]239 const double oldhelperNorm = helper.NormSquared();
[833b15]240 helper = BoundaryTestPair.first->second.second->getPosition() - (MolCenter);
[776b64]241 if (helper.NormSquared() < oldhelperNorm) {
[f01769]242 BoundaryTestPair.first->second.second = const_cast<atom *>(*iter);
[47d041]243 LOG(2, "Keeping new vector due to larger distance to molecule center " << helper.NormSquared() << ".");
[357fba]244 } else {
[47d041]245 LOG(2, "Keeping present vector due to larger distance to molecule center " << oldhelperNorm << ".");
[357fba]246 }
247 } else {
[47d041]248 LOG(2, "Keeping present vector due to larger projected distance " << ProjectedVectorNorm << ".");
[357fba]249 }
[018741]250 }
[3d919e]251 }
[357fba]252 // printing all inserted for debugging
253 // {
[47d041]254 // std::stringstream output;
255 // output << "Printing list of candidates for axis " << axis << " which we have inserted so far: ";
[357fba]256 // int i=0;
257 // for(Boundaries::iterator runner = BoundaryPoints[axis].begin(); runner != BoundaryPoints[axis].end(); runner++) {
258 // if (runner != BoundaryPoints[axis].begin())
[47d041]259 // output << ", " << i << ": " << *runner->second.second;
[357fba]260 // else
[47d041]261 // output << i << ": " << *runner->second.second;
[357fba]262 // i++;
263 // }
[47d041]264 // LOG(1, output.str());
[357fba]265 // }
266 // 3c. throw out points whose distance is less than the mean of left and right neighbours
267 bool flag = false;
[47d041]268 LOG(1, "Looking for candidates to kick out by convex condition ... ");
[357fba]269 do { // do as long as we still throw one out per round
270 flag = false;
[accebe]271 Boundaries::iterator left = BoundaryPoints[axis].begin();
272 Boundaries::iterator right = BoundaryPoints[axis].begin();
273 Boundaries::iterator runner = BoundaryPoints[axis].begin();
274 bool LoopOnceDone = false;
275 while (!LoopOnceDone) {
276 runner = right;
277 right++;
[357fba]278 // set neighbours correctly
279 if (runner == BoundaryPoints[axis].begin()) {
280 left = BoundaryPoints[axis].end();
281 } else {
282 left = runner;
283 }
284 left--;
285 if (right == BoundaryPoints[axis].end()) {
286 right = BoundaryPoints[axis].begin();
[accebe]287 LoopOnceDone = true;
[357fba]288 }
289 // check distance
[3d919e]290
[357fba]291 // construct the vector of each side of the triangle on the projected plane (defined by normal vector AxisVector)
292 {
293 Vector SideA, SideB, SideC, SideH;
[833b15]294 SideA = left->second.second->getPosition() - (MolCenter);
[273382]295 SideA.ProjectOntoPlane(AxisVector);
[47d041]296 // LOG(1, "SideA: " << SideA);
[3d919e]297
[833b15]298 SideB = right->second.second->getPosition() -(MolCenter);
[273382]299 SideB.ProjectOntoPlane(AxisVector);
[47d041]300 // LOG(1, "SideB: " << SideB);
[3d919e]301
[d74077]302 SideC = left->second.second->getPosition() - right->second.second->getPosition();
[273382]303 SideC.ProjectOntoPlane(AxisVector);
[47d041]304 // LOG(1, "SideC: " << SideC);
[3d919e]305
[833b15]306 SideH = runner->second.second->getPosition() -(MolCenter);
[273382]307 SideH.ProjectOntoPlane(AxisVector);
[47d041]308 // LOG(1, "SideH: " << SideH);
[3d919e]309
[357fba]310 // calculate each length
[ad37ab]311 const double a = SideA.Norm();
312 //const double b = SideB.Norm();
313 //const double c = SideC.Norm();
314 const double h = SideH.Norm();
[357fba]315 // calculate the angles
[273382]316 const double alpha = SideA.Angle(SideH);
317 const double beta = SideA.Angle(SideC);
318 const double gamma = SideB.Angle(SideH);
319 const double delta = SideC.Angle(SideH);
[ad37ab]320 const double MinDistance = a * sin(beta) / (sin(delta)) * (((alpha < M_PI / 2.) || (gamma < M_PI / 2.)) ? 1. : -1.);
[47d041]321 //LOG(1, " I calculated: a = " << a << ", h = " << h << ", beta(" << left->second.second->Name << "," << left->second.second->Name << "-" << right->second.second->Name << ") = " << beta << ", delta(" << left->second.second->Name << "," << runner->second.second->Name << ") = " << delta << ", Min = " << MinDistance << ".");
322 LOG(1, "Checking CoG distance of runner " << *runner->second.second << " " << h << " against triangle's side length spanned by (" << *left->second.second << "," << *right->second.second << ") of " << MinDistance << ".");
[357fba]323 if ((fabs(h / fabs(h) - MinDistance / fabs(MinDistance)) < MYEPSILON) && ((h - MinDistance)) < -MYEPSILON) {
324 // throw out point
[47d041]325 LOG(1, "Throwing out " << *runner->second.second << ".");
[357fba]326 BoundaryPoints[axis].erase(runner);
[accebe]327 runner = right;
[357fba]328 flag = true;
[3d919e]329 }
330 }
331 }
[357fba]332 } while (flag);
[3d919e]333 }
[357fba]334 return BoundaryPoints;
[6ac7ee]335};
336
[357fba]337/** Tesselates the convex boundary by finding all boundary points.
338 * \param *out output stream for debugging
[776b64]339 * \param *mol molecule structure with Atom's and Bond's.
[bdc91e]340 * \param *BoundaryPts set of boundary points to use or NULL
[357fba]341 * \param *TesselStruct Tesselation filled with points, lines and triangles on boundary on return
[6bd7e0]342 * \param *LCList atoms in LinkedCell_deprecated list
[357fba]343 * \param *filename filename prefix for output of vertex data
344 * \return *TesselStruct is filled with convex boundary and tesselation is stored under \a *filename.
[6ac7ee]345 */
[6bd7e0]346void FindConvexBorder(const molecule* mol, Boundaries *BoundaryPts, Tesselation *&TesselStruct, const LinkedCell_deprecated *LCList, const char *filename)
[6ac7ee]347{
[ce7bfd]348 //Info FunctionInfo(__func__);
[357fba]349 bool BoundaryFreeFlag = false;
350 Boundaries *BoundaryPoints = NULL;
[3d919e]351
[776b64]352 if (TesselStruct != NULL) // free if allocated
353 delete(TesselStruct);
354 TesselStruct = new class Tesselation;
[3d919e]355
[357fba]356 // 1. Find all points on the boundary
[bdc91e]357 if (BoundaryPts == NULL) {
358 BoundaryFreeFlag = true;
359 BoundaryPoints = GetBoundaryPoints(mol, TesselStruct);
[357fba]360 } else {
[bdc91e]361 BoundaryPoints = BoundaryPts;
[47d041]362 LOG(0, "Using given boundary points set.");
[3d919e]363 }
364
[357fba]365// printing all inserted for debugging
[47d041]366 if (DoLog(1)) {
367 for (int axis=0; axis < NDIM; axis++) {
368 std::stringstream output;
369 output << "Printing list of candidates for axis " << axis << " which we have inserted so far: ";
370 int i=0;
371 for(Boundaries::iterator runner = BoundaryPoints[axis].begin(); runner != BoundaryPoints[axis].end(); runner++) {
372 if (runner != BoundaryPoints[axis].begin())
373 output << ", " << i << ": " << *runner->second.second;
374 else
375 output << i << ": " << *runner->second.second;
376 i++;
377 }
378 LOG(1, output.str());
[a37350]379 }
[bdc91e]380 }
[3d919e]381
[357fba]382 // 2. fill the boundary point list
383 for (int axis = 0; axis < NDIM; axis++)
384 for (Boundaries::iterator runner = BoundaryPoints[axis].begin(); runner != BoundaryPoints[axis].end(); runner++)
[776b64]385 if (!TesselStruct->AddBoundaryPoint(runner->second.second, 0))
[47d041]386 LOG(2, "Point " << *(runner->second.second) << " is already present.");
[e4ea46]387
[47d041]388 LOG(0, "I found " << TesselStruct->PointsOnBoundaryCount << " points on the convex boundary.");
[357fba]389 // now we have the whole set of edge points in the BoundaryList
[018741]390
[357fba]391 // listing for debugging
[47d041]392 //if (DoLog(1)) {
393 // std::stringstream output;
394 // output << "Listing PointsOnBoundary:";
[357fba]395 // for(PointMap::iterator runner = PointsOnBoundary.begin(); runner != PointsOnBoundary.end(); runner++) {
[47d041]396 // output << " " << *runner->second;
[357fba]397 // }
[47d041]398 // LOG(1, output.str());
399 //}
[018741]400
[357fba]401 // 3a. guess starting triangle
[e138de]402 TesselStruct->GuessStartingTriangle();
[018741]403
[357fba]404 // 3b. go through all lines, that are not yet part of two triangles (only of one so far)
[caa06ef]405 PointCloudAdaptor< molecule > cloud(const_cast<molecule *>(mol), mol->name);
[34c43a]406 TesselStruct->TesselateOnBoundary(cloud);
[3d919e]407
[357fba]408 // 3c. check whether all atoms lay inside the boundary, if not, add to boundary points, segment triangle into three with the new point
[34c43a]409 if (!TesselStruct->InsertStraddlingPoints(cloud, LCList))
[47d041]410 ELOG(1, "Insertion of straddling points failed!");
[3d919e]411
[47d041]412 LOG(0, "I created " << TesselStruct->TrianglesOnBoundary.size() << " intermediate triangles with " << TesselStruct->LinesOnBoundary.size() << " lines and " << TesselStruct->PointsOnBoundary.size() << " points.");
[ef0e6d]413
414 // 4. Store triangles in tecplot file
[d51975]415 StoreTrianglesinFile(mol, TesselStruct, filename, "_intermed");
[ef0e6d]416
[357fba]417 // 3d. check all baselines whether the peaks of the two adjacent triangles with respect to center of baseline are convex, if not, make the baseline between the two peaks and baseline endpoints become the new peaks
[ad37ab]418 bool AllConvex = true;
[093645]419 class BoundaryLineSet *line = NULL;
420 do {
421 AllConvex = true;
[776b64]422 for (LineMap::iterator LineRunner = TesselStruct->LinesOnBoundary.begin(); LineRunner != TesselStruct->LinesOnBoundary.end(); LineRunner++) {
[093645]423 line = LineRunner->second;
[47d041]424 LOG(1, "INFO: Current line is " << *line << ".");
[e138de]425 if (!line->CheckConvexityCriterion()) {
[47d041]426 LOG(1, "... line " << *line << " is concave, flipping it.");
[093645]427
428 // flip the line
[e138de]429 if (TesselStruct->PickFarthestofTwoBaselines(line) == 0.)
[47d041]430 ELOG(1, "Correction of concave baselines failed!");
[57066a]431 else {
[e138de]432 TesselStruct->FlipBaseline(line);
[47d041]433 LOG(1, "INFO: Correction of concave baselines worked.");
[accebe]434 LineRunner = TesselStruct->LinesOnBoundary.begin(); // LineRunner may have been erase if line was deleted from LinesOnBoundary
[57066a]435 }
[093645]436 }
437 }
438 } while (!AllConvex);
[3d919e]439
[ef0e6d]440 // 3e. we need another correction here, for TesselPoints that are below the surface (i.e. have an odd number of concave triangles surrounding it)
[776b64]441// if (!TesselStruct->CorrectConcaveTesselPoints(out))
[47d041]442// ELOG(1, "Correction of concave tesselpoints failed!");
[ef0e6d]443
[47d041]444 LOG(0, "I created " << TesselStruct->TrianglesOnBoundary.size() << " triangles with " << TesselStruct->LinesOnBoundary.size() << " lines and " << TesselStruct->PointsOnBoundary.size() << " points.");
[3d919e]445
[357fba]446 // 4. Store triangles in tecplot file
[d51975]447 StoreTrianglesinFile(mol, TesselStruct, filename, "");
[ef0e6d]448
[357fba]449 // free reference lists
450 if (BoundaryFreeFlag)
451 delete[] (BoundaryPoints);
[3d919e]452};
[6ac7ee]453
[d4fa23]454/** For testing removes one boundary point after another to check for leaks.
455 * \param *out output stream for debugging
456 * \param *TesselStruct Tesselation containing envelope with boundary points
457 * \param *mol molecule
458 * \param *filename name of file
459 * \return true - all removed, false - something went wrong
460 */
[e138de]461bool RemoveAllBoundaryPoints(class Tesselation *&TesselStruct, const molecule * const mol, const char * const filename)
[d4fa23]462{
[ce7bfd]463 //Info FunctionInfo(__func__);
[d4fa23]464 int i=0;
465 char number[MAXSTRINGSIZE];
466
467 if ((TesselStruct == NULL) || (TesselStruct->PointsOnBoundary.empty())) {
[47d041]468 ELOG(1, "TesselStruct is empty.");
[d4fa23]469 return false;
470 }
471
472 PointMap::iterator PointRunner;
473 while (!TesselStruct->PointsOnBoundary.empty()) {
[47d041]474 if (DoLog(1)) {
475 std::stringstream output;
476 output << "Remaining points are: ";
477 for (PointMap::iterator PointSprinter = TesselStruct->PointsOnBoundary.begin(); PointSprinter != TesselStruct->PointsOnBoundary.end(); PointSprinter++)
478 output << *(PointSprinter->second) << "\t";
479 LOG(1, output.str());
480 }
[d4fa23]481
482 PointRunner = TesselStruct->PointsOnBoundary.begin();
483 // remove point
[e138de]484 TesselStruct->RemovePointFromTesselatedSurface(PointRunner->second);
[d4fa23]485
486 // store envelope
487 sprintf(number, "-%04d", i++);
[e138de]488 StoreTrianglesinFile(mol, (const Tesselation *&)TesselStruct, filename, number);
[d4fa23]489 }
490
491 return true;
492};
493
[08ef35]494/** Creates a convex envelope from a given non-convex one.
[093645]495 * -# First step, remove concave spots, i.e. singular "dents"
496 * -# We go through all PointsOnBoundary.
497 * -# We CheckConvexityCriterion() for all its lines.
498 * -# If all its lines are concave, it cannot be on the convex envelope.
499 * -# Hence, we remove it and re-create all its triangles from its getCircleOfConnectedPoints()
500 * -# We calculate the additional volume.
501 * -# We go over all lines until none yields a concavity anymore.
502 * -# Second step, remove concave lines, i.e. line-shape "dents"
503 * -# We go through all LinesOnBoundary
504 * -# We CheckConvexityCriterion()
505 * -# If it returns concave, we flip the line in this quadrupel of points (abusing the degeneracy of the tesselation)
506 * -# We CheckConvexityCriterion(),
507 * -# if it's concave, we continue
508 * -# if not, we mark an error and stop
[08ef35]509 * Note: This routine - for free - calculates the difference in volume between convex and
[ee0032]510 * non-convex envelope, as the former is easy to calculate - Tesselation::getVolumeOfConvexEnvelope() - it
[08ef35]511 * can be used to compute volumes of arbitrary shapes.
512 * \param *out output stream for debugging
513 * \param *TesselStruct non-convex envelope, is changed in return!
[093645]514 * \param *mol molecule
515 * \param *filename name of file
[08ef35]516 * \return volume difference between the non- and the created convex envelope
517 */
[5f7b95]518double ConvexizeNonconvexEnvelope(
519 Tesselation *&TesselStruct,
520 const molecule * const mol,
521 const char * const filename,
522 bool DebugOutputEveryStep)
[08ef35]523{
[ce7bfd]524 //Info FunctionInfo(__func__);
[08ef35]525 double volume = 0;
526 class BoundaryPointSet *point = NULL;
527 class BoundaryLineSet *line = NULL;
[ad37ab]528 bool Concavity = false;
[57066a]529 char dummy[MAXSTRINGSIZE];
[ad37ab]530 PointMap::iterator PointRunner;
531 PointMap::iterator PointAdvance;
532 LineMap::iterator LineRunner;
533 LineMap::iterator LineAdvance;
534 TriangleMap::iterator TriangleRunner;
535 TriangleMap::iterator TriangleAdvance;
536 int run = 0;
[093645]537
538 // check whether there is something to work on
[08ef35]539 if (TesselStruct == NULL) {
[47d041]540 ELOG(1, "TesselStruct is empty!");
[08ef35]541 return volume;
542 }
543
[b8d215]544 LOG(1, "INFO: Making tesselated surface with " << TesselStruct->TrianglesOnBoundaryCount
545 << " convex ...");
546
[2ef2cc]547 // first purge all degenerate triangles
548 TesselStruct->RemoveDegeneratedTriangles();
549
[1d9b7aa]550 do {
551 Concavity = false;
[d289c6]552
[5f7b95]553 if (DebugOutputEveryStep) {
554 sprintf(dummy, "-%d", run++);
555 //CalculateConcavityPerBoundaryPoint(TesselStruct);
556 LOG(1, "INFO: Writing " << run << "th tesselation file.");
557 StoreTrianglesinFile(mol, (const Tesselation *&)TesselStruct, filename, dummy);
558 }
[57066a]559
[d289c6]560 // first step: remove all full-concave point
[1d9b7aa]561 PointRunner = TesselStruct->PointsOnBoundary.begin();
562 PointAdvance = PointRunner; // we need an advanced point, as the PointRunner might get removed
563 while (PointRunner != TesselStruct->PointsOnBoundary.end()) {
564 PointAdvance++;
565 point = PointRunner->second;
[b8d215]566 LOG(2, "INFO: Current point is " << *point << ".");
[aac19f]567 // check that at least a single line is concave
568 LineMap::iterator LineRunner = point->lines.begin();
569 for (; LineRunner != point->lines.end(); LineRunner++) {
570 const BoundaryLineSet * line = LineRunner->second;
[b8d215]571 LOG(3, "INFO: Current line of point " << *point << " is " << *line << ".");
[aac19f]572 if (!line->CheckConvexityCriterion())
573 break;
[d289c6]574 }
[aac19f]575 // remove the point if needed
576 if (LineRunner != point->lines.end()) {
577 const double tmp = TesselStruct->RemoveFullConcavePointFromTesselatedSurface(point);
578 if (tmp > 0.) {
579 volume += tmp;
580 Concavity = true;
581 }
[1d9b7aa]582 }
583 PointRunner = PointAdvance;
[093645]584 }
585
[5f7b95]586 if (DebugOutputEveryStep) {
587 sprintf(dummy, "-%d", run++);
588 //CalculateConcavityPerBoundaryPoint(TesselStruct);
589 LOG(1, "INFO: Writing " << run << "th tesselation file.");
590 StoreTrianglesinFile(mol, (const Tesselation *&)TesselStruct, filename, dummy);
591 }
[093645]592
[d289c6]593 // second step: flip baselines, i.e. add general tetraeder at concave lines
594 // when the tetraeder does not intersect with other already present triangles
[1d9b7aa]595 LineRunner = TesselStruct->LinesOnBoundary.begin();
596 LineAdvance = LineRunner; // we need an advanced line, as the LineRunner might get removed
[81ffd8]597 std::map<double, std::pair<BoundaryLineSet *, double> > GainMap;
[1d9b7aa]598 while (LineRunner != TesselStruct->LinesOnBoundary.end()) {
599 LineAdvance++;
600 line = LineRunner->second;
[d289c6]601 if (!line->CheckConvexityCriterion()) {
602 LOG(2, "INFO: concave line is " << *line << ".");
603 // gather the other points
604 BoundaryPointSet *BPS[4];
605 int m = 0;
606 {
607 for (TriangleMap::iterator runner = line->triangles.begin(); runner != line->triangles.end(); runner++)
608 for (int j = 0; j < 3; j++) // all of their endpoints and baselines
609 if (!line->ContainsBoundaryPoint(runner->second->endpoints[j])) // and neither of its endpoints
610 BPS[m++] = runner->second->endpoints[j];
611 }
612 BPS[2] = line->endpoints[0];
613 BPS[3] = line->endpoints[1];
614 LOG(3, "DEBUG: other line would consist of " << *BPS[0] << " and "
615 << *BPS[1] << ".");
616
617 // check for already present (third) side of the tetraeder as we then
618 // would create a degenerate triangle
619 bool TetraederSidePresent = false;
620 {
621 class TesselPoint *TriangleCandidates[3];
622 TriangleCandidates[0] = BPS[0]->node;
623 TriangleCandidates[1] = BPS[1]->node;
624 TriangleCandidates[2] = BPS[2]->node;
625 if ((TesselStruct->GetPresentTriangle(TriangleCandidates) != NULL)) {
626 LOG(2, "REJECT: Triangle side " << *TriangleCandidates[0] << ","
627 << *TriangleCandidates[1] << "," << *TriangleCandidates[2] << " present.");
628 TetraederSidePresent = true;
629 }
630 TriangleCandidates[2] = BPS[3]->node;
631 if ((TesselStruct->GetPresentTriangle(TriangleCandidates) != NULL)) {
632 LOG(2, "REJECT: Triangle side " << *TriangleCandidates[0] << ","
633 << *TriangleCandidates[1] << "," << *TriangleCandidates[2] << " present.");
634 TetraederSidePresent = true;
635 }
636 }
637
638 if ((BPS[0] != BPS[1]) && (m == 2) && (!TetraederSidePresent)) {
639 // check whether all adjacent triangles do not intersect with new line
640 bool no_line_intersects = true;
641 Vector Intersection;
642 TriangleSet triangles;
643 TriangleSet *firsttriangles = TesselStruct->GetAllTriangles(line->endpoints[0]);
644 TriangleSet *secondtriangles = TesselStruct->GetAllTriangles(line->endpoints[1]);
645 triangles.insert( firsttriangles->begin(), firsttriangles->end() );
646 triangles.insert( secondtriangles->begin(), secondtriangles->end() );
647 delete firsttriangles;
648 delete secondtriangles;
649 for (TriangleSet::const_iterator triangleiter = triangles.begin();
650 triangleiter != triangles.end(); ++triangleiter) {
651 const BoundaryTriangleSet * triangle = *triangleiter;
652 bool line_intersects = triangle->GetIntersectionInsideTriangle(
653 BPS[0]->node->getPosition(),
654 BPS[1]->node->getPosition(),
655 Intersection);
656 // switch result when coinciding with endpoint
657 bool concave_adjacent_line = false;
658 bool intersection_is_endnode = false;
659 for (int j=0;j<2;++j) {
660 if (Intersection.DistanceSquared(BPS[j]->node->getPosition()) < MYEPSILON) {
661 intersection_is_endnode = true;
662 // check whether its an adjacent triangle and if it's concavely connected
663 // only then are we in danger of cutting through it and need to check
664 // sign of normal vector and intersecting line
665 for (int i=0;i<2;++i)
666 for (int lineindex=0;lineindex < 3;++lineindex)
667 if ((triangle->lines[lineindex]->ContainsBoundaryPoint(line->endpoints[i]))
668 && (triangle->lines[lineindex]->ContainsBoundaryPoint(BPS[j]))) {
669 concave_adjacent_line = !triangle->lines[lineindex]->CheckConvexityCriterion();
670 }
671 if (concave_adjacent_line) {
672 const Vector intersector =
673 BPS[(j+1)%2]->node->getPosition() - Intersection;
674 if (triangle->NormalVector.ScalarProduct(intersector) >= -MYEPSILON) {
675 LOG(4, "ACCEPT: Intersection coincides with first endpoint "
676 << *BPS[j] << ".");
677 line_intersects = false;
678 } else {
679 LOG(4, "REJECT: Intersection ends on wrong side of triangle.");
680 }
681 } else {
682 LOG(4, "ACCEPT: Intersection coincides with first endpoint "
683 << *BPS[j] << ".");
684 line_intersects = false;
685 }
686 }
687 }
688 // if we have an intersection, check that it is within either
689 // endpoint, i.e. check that scalar product between vectors going
690 // from intersction to either endpoint has negative sign (both
691 // vectors point in opposite directions)
692 if (!intersection_is_endnode && line_intersects) {
693 const Vector firstvector = BPS[0]->node->getPosition() - Intersection;
694 const Vector secondvector = BPS[1]->node->getPosition() - Intersection;
695 if (firstvector.ScalarProduct(secondvector) >= 0)
696 line_intersects = false;
697 }
698 no_line_intersects &= !line_intersects;
699 }
700
701 if (no_line_intersects) {
702 // calculate the volume
[81ffd8]703 const double tmp = line->CalculateConvexity();
704 const double gain =
705 CalculateVolumeofGeneralTetraeder(
706 BPS[0]->node->getPosition(),
707 BPS[1]->node->getPosition(),
708 BPS[2]->node->getPosition(),
709 BPS[3]->node->getPosition());
710
711 GainMap.insert(std::make_pair(tmp, std::make_pair(line,gain) ));
[d289c6]712 LOG(2, "DEBUG: Adding concave line " << *line << " with gain of "
[81ffd8]713 << gain << ".");
[d289c6]714 } else {
715 // if 2 or 3 don't
716 LOG(2, "DEBUG: We don't added concave line " << *line
717 << " as other line intersects with adjacent triangles.");
718 }
[57066a]719 }
[1d9b7aa]720 }
721 LineRunner = LineAdvance;
722 }
[d289c6]723 // flip line with most gain
724 if (!GainMap.empty()) {
[81ffd8]725 line = GainMap.begin()->second.first;
726 const double tmp = GainMap.begin()->second.second;
[d289c6]727 volume += tmp;
[81ffd8]728
[d289c6]729// GainMap.clear();
730
731 // and flip the line
[81ffd8]732 LOG(1, "INFO: Flipping current most concave line " << *line << " with gain of "
[d289c6]733 << tmp << ".");
734 TesselStruct->FlipBaseline(line);
735 Concavity = true;
736 }
737 } while ((Concavity)); // && (run < 100)
[093645]738
[e138de]739 CalculateConcavityPerBoundaryPoint(TesselStruct);
740 StoreTrianglesinFile(mol, (const Tesselation *&)TesselStruct, filename, "");
[0077b5]741
742 // end
[d289c6]743 LOG(0, "RESULT: Added volume in convexization is " << volume << ".");
[0077b5]744 return volume;
745};
746
[6ac7ee]747
[7dea7c]748/** Stores triangles to file.
749 * \param *out output stream for debugging
750 * \param *mol molecule with atoms and bonds
[71b20e]751 * \param *TesselStruct Tesselation with boundary triangles
[7dea7c]752 * \param *filename prefix of filename
753 * \param *extraSuffix intermediate suffix
754 */
[71b20e]755void StoreTrianglesinFile(const molecule * const mol, const Tesselation * const TesselStruct, const char *filename, const char *extraSuffix)
[7dea7c]756{
[ce7bfd]757 //Info FunctionInfo(__func__);
[caa06ef]758 PointCloudAdaptor< molecule > cloud(const_cast<molecule *>(mol), mol->name);
[7dea7c]759 // 4. Store triangles in tecplot file
760 if (filename != NULL) {
761 if (DoTecplotOutput) {
762 string OutputName(filename);
763 OutputName.append(extraSuffix);
764 OutputName.append(TecplotSuffix);
765 ofstream *tecplot = new ofstream(OutputName.c_str());
[34c43a]766 WriteTecplotFile(tecplot, TesselStruct, cloud, -1);
[7dea7c]767 tecplot->close();
768 delete(tecplot);
769 }
770 if (DoRaster3DOutput) {
771 string OutputName(filename);
772 OutputName.append(extraSuffix);
773 OutputName.append(Raster3DSuffix);
774 ofstream *rasterplot = new ofstream(OutputName.c_str());
[34c43a]775 WriteRaster3dFile(rasterplot, TesselStruct, cloud);
[7dea7c]776 rasterplot->close();
777 delete(rasterplot);
778 }
779 }
780};
[03648b]781
[6ac7ee]782/** Tesselates the non convex boundary by rolling a virtual sphere along the surface of the molecule.
783 * \param *out output stream for debugging
784 * \param *mol molecule structure with Atom's and Bond's
[776b64]785 * \param *&TesselStruct Tesselation filled with points, lines and triangles on boundary on return
[6bd7e0]786 * \param *&LCList atoms in LinkedCell_deprecated list
[57066a]787 * \param RADIUS radius of the virtual sphere
[6ac7ee]788 * \param *filename filename prefix for output of vertex data
[4fc93f]789 * \return true - tesselation successful, false - tesselation failed
[6ac7ee]790 */
[6bd7e0]791bool FindNonConvexBorder(molecule* const mol, Tesselation *&TesselStruct, const LinkedCell_deprecated *&LCList, const double RADIUS, const char *filename = NULL)
[03648b]792{
[ce7bfd]793 //Info FunctionInfo(__func__);
[3d919e]794 bool freeLC = false;
[4fc93f]795 bool status = false;
[6613ec]796 CandidateForTesselation *baseline = NULL;
[1e168b]797 bool OneLoopWithoutSuccessFlag = true; // marks whether we went once through all baselines without finding any without two triangles
[a2a2f7]798// bool TesselationFailFlag = false;
[357fba]799
[a7b761b]800 mol->getAtomCount();
[357fba]801
[776b64]802 if (TesselStruct == NULL) {
[47d041]803 LOG(1, "Allocating Tesselation struct ...");
[776b64]804 TesselStruct= new Tesselation;
[ef0e6d]805 } else {
[776b64]806 delete(TesselStruct);
[47d041]807 LOG(1, "Re-Allocating Tesselation struct ...");
[776b64]808 TesselStruct = new Tesselation;
[3d919e]809 }
[ad37ab]810
[57066a]811 // initialise Linked Cell
[caa06ef]812 PointCloudAdaptor< molecule > cloud(mol, mol->name);
[3d919e]813 if (LCList == NULL) {
[6bd7e0]814 LCList = new LinkedCell_deprecated(cloud, 2.*RADIUS);
[3d919e]815 freeLC = true;
816 }
817
[57066a]818 // 1. get starting triangle
[ce70970]819 if (!TesselStruct->FindStartingTriangle(RADIUS, LCList)) {
[47d041]820 ELOG(0, "No valid starting triangle found.");
[b5c2d7]821 //performCriticalExit();
[ce70970]822 }
[f8bd7d]823 if (filename != NULL) {
824 if ((DoSingleStepOutput && ((TesselStruct->TrianglesOnBoundary.size() % SingleStepWidth == 0)))) { // if we have a new triangle and want to output each new triangle configuration
[34c43a]825 TesselStruct->Output(filename, cloud);
[f8bd7d]826 }
827 }
[3d919e]828
[57066a]829 // 2. expand from there
[1e168b]830 while ((!TesselStruct->OpenLines.empty()) && (OneLoopWithoutSuccessFlag)) {
[b40a93]831 (cerr << "There are " << TesselStruct->TrianglesOnBoundary.size() << " triangles and " << TesselStruct->OpenLines.size() << " open lines to scan for candidates." << endl);
832 // 2a. print OpenLines without candidates
[47d041]833 LOG(1, "There are the following open lines to scan for a candidates:");
[1e168b]834 for (CandidateMap::iterator Runner = TesselStruct->OpenLines.begin(); Runner != TesselStruct->OpenLines.end(); Runner++)
[b40a93]835 if (Runner->second->pointlist.empty())
[47d041]836 LOG(1, " " << *(Runner->second));
[1e168b]837
[734816]838 // 2b. find best candidate for each OpenLine
[a2a2f7]839 const bool TesselationFailFlag = TesselStruct->FindCandidatesforOpenLines(RADIUS, LCList);
840 ASSERT( TesselationFailFlag,
841 "FindNonConvexBorder() - at least one open line without candidate exists.");
[3d919e]842
[734816]843 // 2c. print OpenLines with candidates again
[47d041]844 LOG(1, "There are " << TesselStruct->OpenLines.size() << " open lines to scan for the best candidates:");
[1e168b]845 for (CandidateMap::iterator Runner = TesselStruct->OpenLines.begin(); Runner != TesselStruct->OpenLines.end(); Runner++)
[47d041]846 LOG(1, " " << *(Runner->second));
[1e168b]847
[734816]848 // 2d. search for smallest ShortestAngle among all candidates
849 double ShortestAngle = 4.*M_PI;
[1e168b]850 for (CandidateMap::iterator Runner = TesselStruct->OpenLines.begin(); Runner != TesselStruct->OpenLines.end(); Runner++) {
851 if (Runner->second->ShortestAngle < ShortestAngle) {
852 baseline = Runner->second;
853 ShortestAngle = baseline->ShortestAngle;
[47d041]854 LOG(1, "New best candidate is " << *baseline->BaseLine << " with point " << *(*baseline->pointlist.begin()) << " and angle " << baseline->ShortestAngle);
[1e168b]855 }
856 }
[734816]857 // 2e. if we found one, add candidate
[f67b6e]858 if ((ShortestAngle == 4.*M_PI) || (baseline->pointlist.empty()))
[7dea7c]859 OneLoopWithoutSuccessFlag = false;
[1e168b]860 else {
[474961]861 TesselStruct->AddCandidatePolygon(*baseline, RADIUS, LCList);
[1e168b]862 }
863
[734816]864 // 2f. write temporary envelope
[1e168b]865 if (filename != NULL) {
866 if ((DoSingleStepOutput && ((TesselStruct->TrianglesOnBoundary.size() % SingleStepWidth == 0)))) { // if we have a new triangle and want to output each new triangle configuration
[34c43a]867 TesselStruct->Output(filename, cloud);
[1e168b]868 }
[3d919e]869 }
870 }
[4fc93f]871// // check envelope for consistency
872// status = CheckListOfBaselines(TesselStruct);
873//
874// // look whether all points are inside of the convex envelope, otherwise add them via degenerated triangles
875// //->InsertStraddlingPoints(mol, LCList);
[9879f6]876// for (molecule::const_iterator iter = mol->begin(); iter != mol->end(); ++iter) {
[57066a]877// class TesselPoint *Runner = NULL;
[9879f6]878// Runner = *iter;
[47d041]879// LOG(1, "Checking on " << Runner->Name << " ... ");
[e138de]880// if (!->IsInnerPoint(Runner, LCList)) {
[47d041]881// LOG(2, Runner->Name << " is outside of envelope, adding via degenerated triangles.");
[e138de]882// ->AddBoundaryPointByDegeneratedTriangle(Runner, LCList);
[57066a]883// } else {
[47d041]884// LOG(2, Runner->Name << " is inside of or on envelope.");
[57066a]885// }
886// }
[357fba]887
[f67b6e]888// // Purges surplus triangles.
889// TesselStruct->RemoveDegeneratedTriangles();
[b32dbb]890//
891// // check envelope for consistency
892// status = CheckListOfBaselines(TesselStruct);
[b998c3]893
[b8d215]894// cout << "before correction" << endl;
[c72112]895
[b998c3]896 // store before correction
[c72112]897 StoreTrianglesinFile(mol, TesselStruct, filename, "");
[b998c3]898
[6613ec]899// // correct degenerated polygons
900// TesselStruct->CorrectAllDegeneratedPolygons();
901//
[e69c87]902 // check envelope for consistency
903 status = CheckListOfBaselines(TesselStruct);
[ef0e6d]904
[57066a]905 // write final envelope
[e138de]906 CalculateConcavityPerBoundaryPoint(TesselStruct);
[b8d215]907// cout << "after correction" << endl;
[c72112]908 StoreTrianglesinFile(mol, TesselStruct, filename, "");
[8c54a3]909
[3d919e]910 if (freeLC)
911 delete(LCList);
[4fc93f]912
913 return status;
[6ac7ee]914};
Note: See TracBrowser for help on using the repository browser.