Changeset 73b510 for src


Ignore:
Timestamp:
Dec 17, 2009, 5:50:04 PM (16 years ago)
Author:
Frederik Heber <heber@…>
Branches:
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
Children:
1cf5df
Parents:
2130dd (diff), 125b3c (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge branch 'FixDegeneratedTesselation' into CorrectDegeneratedPolygons

Location:
src
Files:
14 edited

Legend:

Unmodified
Added
Removed
  • src/Makefile.am

    r2130dd r73b510  
    2525
    2626#EXTRA_DIST = ${molecuilder_DATA}
     27
     28FORCE:
     29$(srcdir)/.git-version: FORCE
     30        @if (test -d $(top_srcdir)/../.git && cd $(srcdir) && git describe HEAD) > .git-version-t 2>/dev/null \
     31          && ! diff .git-version-t $(srcdir)/.git-version >/dev/null 2>&1; then \
     32          mv -f .git-version-t $(srcdir)/.git-version; \
     33        else \
     34          rm -f .git-version-t; \
     35        fi
     36
     37EXTRA_DIST = $(srcdir)/.git-version
     38
     39$(srcdir)/version.c: $(srcdir)/.git-version
     40        echo "const char *ESPACKVersion = \"$(PACKAGE_NAME) -- git version: "`cat $(srcdir)/.git-version`"\";" > $@
     41
     42molecuilder_SOURCES += $(srcdir)/version.c
  • src/bondgraph.cpp

    r2130dd r73b510  
    3535/** Parses the bond lengths in a given file and puts them int a matrix form.
    3636 * Allocates \a MatrixContainer for BondGraph::BondLengthMatrix, using MatrixContainer::ParseMatrix(),
    37  * but only if parsing is successfull. Otherwise variable is left as NULL.
     37 * but only if parsing is successful. Otherwise variable is left as NULL.
    3838 * \param *out output stream for debugging
    3939 * \param filename file with bond lengths to parse
  • src/boundary.cpp

    r2130dd r73b510  
    10411041//  TesselStruct->RemoveDegeneratedTriangles();
    10421042
     1043  // check envelope for consistency
     1044  status = CheckListOfBaselines(TesselStruct);
     1045
     1046  // store before correction
     1047  StoreTrianglesinFile(mol, (const Tesselation *&)TesselStruct, filename, "");
     1048
    10431049  // correct degenerated polygons
    10441050  TesselStruct->CorrectAllDegeneratedPolygons();
  • src/boundary.hpp

    r2130dd r73b510  
    3636#define DEBUG 1
    3737#define DoSingleStepOutput 0
    38 #define SingleStepWidth 1
     38#define SingleStepWidth 10
    3939
    4040#define DistancePair pair < double, atom* >
  • src/builder.cpp

    r2130dd r73b510  
    6565#include "molecule.hpp"
    6666#include "periodentafel.hpp"
     67#include "version.h"
    6768
    6869/********************************************* Subsubmenu routine ************************************/
     
    21062107                if (volume != -1)
    21072108                  ExitFlag = 255;
    2108                   eLog() << Verbose(0) << "Not enough arguments given for suspension: -u <density>" << endl;
     2109                  eLog() << Verbose(0) << "Not enough or invalid arguments given for suspension: -u <density>" << endl;
    21092110                  performCriticalExit();
    21102111              } else {
     
    22222223  int j;
    22232224
     2225  cout << ESPACKVersion << endl;
     2226
    22242227  setVerbosity(0);
    22252228
  • src/config.cpp

    r2130dd r73b510  
    10741074  // don't do this here ...
    10751075  //MolList->DissectMoleculeIntoConnectedSubgraphs(mol,this);
    1076 
    1077   delete(mol);
     1076  //delete(mol);
     1077
    10781078  delete(FileBuffer);
    10791079};
  • src/molecule_graph.cpp

    r2130dd r73b510  
    11171117  bool status = true;
    11181118  if (ReferenceStack->IsEmpty()) {
    1119     eLog() << Verbose(0) << "ReferenceStack is empty!" << endl;
    1120     performCriticalExit();
     1119    Log() << Verbose(1) << "ReferenceStack is empty!" << endl;
    11211120    return false;
    11221121  }
  • src/moleculelist.cpp

    r2130dd r73b510  
    402402  input.open(line.c_str());
    403403  if (input == NULL) {
    404     eLog() << Verbose(0) << endl << "Unable to open " << line << ", is the directory correct?" << endl;
    405     performCriticalExit();
     404    Log() << Verbose(1) << endl << "Unable to open " << line << ", is the directory correct?" << endl;
    406405    return false;
    407406  }
  • src/parser.cpp

    r2130dd r73b510  
    158158  //Log() << Verbose(0) << "Opening " << name << " ... "  << input << endl;
    159159  if (input == NULL) {
    160     eLog() << Verbose(0) << endl << "Unable to open " << name << ", is the directory correct?" << endl;
    161     performCriticalExit();
     160    eLog() << Verbose(1) << endl << "Unable to open " << name << ", is the directory correct?" << endl;
     161    //performCriticalExit();
    162162    return false;
    163163  }
  • src/tesselation.cpp

    r2130dd r73b510  
    15871587  bool insertNewLine = true;
    15881588
    1589   if (a->lines.find(b->node->nr) != a->lines.end()) {
    1590     LineMap::iterator FindLine = a->lines.find(b->node->nr);
     1589  LineMap::iterator FindLine = a->lines.find(b->node->nr);
     1590  if (FindLine != a->lines.end()) {
     1591    Log() << Verbose(1) << "INFO: There is at least one line between " << *a << " and " << *b << ": " << *(FindLine->second) << "." << endl;
     1592
    15911593    pair<LineMap::iterator,LineMap::iterator> FindPair;
    15921594    FindPair = a->lines.equal_range(b->node->nr);
    1593     Log() << Verbose(1) << "INFO: There is at least one line between " << *a << " and " << *b << ": " << *(FindLine->second) << "." << endl;
    15941595
    15951596    for (FindLine = FindPair.first; FindLine != FindPair.second; FindLine++) {
     
    19151916  double maxCoordinate[NDIM];
    19161917  BoundaryLineSet BaseLine;
    1917   Vector Oben;
    19181918  Vector helper;
    19191919  Vector Chord;
    19201920  Vector SearchDirection;
    1921 
    1922   Oben.Zero();
     1921  Vector CircleCenter;  // center of the circle, i.e. of the band of sphere's centers
     1922  Vector CirclePlaneNormal; // normal vector defining the plane this circle lives in
     1923  Vector SphereCenter;
     1924  Vector NormalVector;
     1925
     1926  NormalVector.Zero();
    19231927
    19241928  for (i = 0; i < 3; i++) {
     
    19551959  BTS = NULL;
    19561960  for (int k=0;k<NDIM;k++) {
    1957     Oben.Zero();
    1958     Oben.x[k] = 1.;
     1961    NormalVector.Zero();
     1962    NormalVector.x[k] = 1.;
    19591963    BaseLine.endpoints[0] = new BoundaryPointSet(MaxPoint[k]);
    19601964    Log() << Verbose(0) << "Coordinates of start node at " << *BaseLine.endpoints[0]->node << "." << endl;
     
    19631967    ShortestAngle = 999999.; // This will contain the angle, which will be always positive (when looking for second point), when looking for third point this will be the quadrant.
    19641968
    1965     FindSecondPointForTesselation(BaseLine.endpoints[0]->node, Oben, Temporary, &ShortestAngle, RADIUS, LC); // we give same point as next candidate as its bonds are looked into in find_second_...
     1969    FindSecondPointForTesselation(BaseLine.endpoints[0]->node, NormalVector, Temporary, &ShortestAngle, RADIUS, LC); // we give same point as next candidate as its bonds are looked into in find_second_...
    19661970    if (Temporary == NULL)  // have we found a second point?
    19671971      continue;
    19681972    BaseLine.endpoints[1] = new BoundaryPointSet(Temporary);
    19691973
    1970     helper.CopyVector(BaseLine.endpoints[0]->node->node);
    1971     helper.SubtractVector(BaseLine.endpoints[1]->node->node);
    1972     helper.Normalize();
    1973     Oben.ProjectOntoPlane(&helper);
    1974     Oben.Normalize();
    1975     helper.VectorProduct(&Oben);
     1974    // construct center of circle
     1975    CircleCenter.CopyVector(BaseLine.endpoints[0]->node->node);
     1976    CircleCenter.AddVector(BaseLine.endpoints[1]->node->node);
     1977    CircleCenter.Scale(0.5);
     1978
     1979    // construct normal vector of circle
     1980    CirclePlaneNormal.CopyVector(BaseLine.endpoints[0]->node->node);
     1981    CirclePlaneNormal.SubtractVector(BaseLine.endpoints[1]->node->node);
     1982
     1983    double radius = CirclePlaneNormal.NormSquared();
     1984    double CircleRadius = sqrt(RADIUS*RADIUS - radius/4.);
     1985
     1986    NormalVector.ProjectOntoPlane(&CirclePlaneNormal);
     1987    NormalVector.Normalize();
    19761988    ShortestAngle = 2.*M_PI; // This will indicate the quadrant.
    19771989
    1978     Chord.CopyVector(BaseLine.endpoints[0]->node->node); // bring into calling function
    1979     Chord.SubtractVector(BaseLine.endpoints[1]->node->node);
    1980     double radius = Chord.ScalarProduct(&Chord);
    1981     double CircleRadius = sqrt(RADIUS*RADIUS - radius/4.);
    1982     helper.CopyVector(&Oben);
    1983     helper.Scale(CircleRadius);
    1984     // Now, oben and helper are two orthonormalized vectors in the plane defined by Chord (not normalized)
     1990    SphereCenter.CopyVector(&NormalVector);
     1991    SphereCenter.Scale(CircleRadius);
     1992    SphereCenter.AddVector(&CircleCenter);
     1993    // Now, NormalVector and SphereCenter are two orthonormalized vectors in the plane defined by CirclePlaneNormal (not normalized)
    19851994
    19861995    // look in one direction of baseline for initial candidate
    1987     SearchDirection.MakeNormalVector(&Chord, &Oben);  // whether we look "left" first or "right" first is not important ...
     1996    SearchDirection.MakeNormalVector(&CirclePlaneNormal, &NormalVector);  // whether we look "left" first or "right" first is not important ...
    19881997
    19891998    // adding point 1 and point 2 and add the line between them
     
    19932002    //Log() << Verbose(1) << "INFO: OldSphereCenter is at " << helper << ".\n";
    19942003    CandidateForTesselation OptCandidates(&BaseLine);
    1995     FindThirdPointForTesselation(Oben, SearchDirection, helper, OptCandidates, NULL, RADIUS, LC);
     2004    FindThirdPointForTesselation(NormalVector, SearchDirection, SphereCenter, OptCandidates, NULL, RADIUS, LC);
    19962005    Log() << Verbose(0) << "List of third Points is:" << endl;
    19972006    for (TesselPointList::iterator it = OptCandidates.pointlist.begin(); it != OptCandidates.pointlist.end(); it++) {
     
    21672176  Vector CircleCenter;
    21682177  Vector CirclePlaneNormal;
    2169   Vector OldSphereCenter;
     2178  Vector RelativeSphereCenter;
    21702179  Vector SearchDirection;
    21712180  Vector helper;
     
    21742183  double radius, CircleRadius;
    21752184
    2176   Log() << Verbose(0) << "Current baseline is " << *CandidateLine.BaseLine << " of triangle " << T << "." << endl;
    21772185  for (int i=0;i<3;i++)
    2178     if ((T.endpoints[i]->node != CandidateLine.BaseLine->endpoints[0]->node) && (T.endpoints[i]->node != CandidateLine.BaseLine->endpoints[1]->node))
     2186    if ((T.endpoints[i]->node != CandidateLine.BaseLine->endpoints[0]->node) && (T.endpoints[i]->node != CandidateLine.BaseLine->endpoints[1]->node)) {
    21792187      ThirdNode = T.endpoints[i]->node;
     2188      break;
     2189    }
     2190  Log() << Verbose(0) << "Current baseline is " << *CandidateLine.BaseLine << " with ThirdNode " << *ThirdNode << " of triangle " << T << "." << endl;
    21802191
    21812192  // construct center of circle
     
    21912202  radius = CirclePlaneNormal.ScalarProduct(&CirclePlaneNormal);
    21922203  if (radius/4. < RADIUS*RADIUS) {
     2204    // construct relative sphere center with now known CircleCenter
     2205    RelativeSphereCenter.CopyVector(&T.SphereCenter);
     2206    RelativeSphereCenter.SubtractVector(&CircleCenter);
     2207
    21932208    CircleRadius = RADIUS*RADIUS - radius/4.;
    21942209    CirclePlaneNormal.Normalize();
    21952210    Log() << Verbose(1) << "INFO: CircleCenter is at " << CircleCenter << ", CirclePlaneNormal is " << CirclePlaneNormal << " with circle radius " << sqrt(CircleRadius) << "." << endl;
    21962211
    2197     // construct old center
    2198     GetCenterofCircumcircle(&OldSphereCenter, *T.endpoints[0]->node->node, *T.endpoints[1]->node->node, *T.endpoints[2]->node->node);
    2199     helper.CopyVector(&T.NormalVector);  // normal vector ensures that this is correct center of the two possible ones
    2200     radius = CandidateLine.BaseLine->endpoints[0]->node->node->DistanceSquared(&OldSphereCenter);
    2201     helper.Scale(sqrt(RADIUS*RADIUS - radius));
    2202     OldSphereCenter.AddVector(&helper);
    2203     OldSphereCenter.SubtractVector(&CircleCenter);
    2204     Log() << Verbose(1) << "INFO: OldSphereCenter is at " << OldSphereCenter << "." << endl;
    2205 
    2206     // construct SearchDirection
    2207     SearchDirection.MakeNormalVector(&T.NormalVector, &CirclePlaneNormal);
    2208     helper.CopyVector(CandidateLine.BaseLine->endpoints[0]->node->node);
     2212    Log() << Verbose(1) << "INFO: OldSphereCenter is at " << T.SphereCenter << "." << endl;
     2213
     2214    // construct SearchDirection and an "outward pointer"
     2215    SearchDirection.MakeNormalVector(&RelativeSphereCenter, &CirclePlaneNormal);
     2216    helper.CopyVector(&CircleCenter);
    22092217    helper.SubtractVector(ThirdNode->node);
    22102218    if (helper.ScalarProduct(&SearchDirection) < -HULLEPSILON)// ohoh, SearchDirection points inwards!
    22112219      SearchDirection.Scale(-1.);
    2212     SearchDirection.ProjectOntoPlane(&OldSphereCenter);
    2213     SearchDirection.Normalize();
    22142220    Log() << Verbose(1) << "INFO: SearchDirection is " << SearchDirection << "." << endl;
    2215     if (fabs(OldSphereCenter.ScalarProduct(&SearchDirection)) > HULLEPSILON) {
     2221    if (fabs(RelativeSphereCenter.ScalarProduct(&SearchDirection)) > HULLEPSILON) {
    22162222      // rotated the wrong way!
    22172223      eLog() << Verbose(1) << "SearchDirection and RelativeOldSphereCenter are still not orthogonal!" << endl;
     
    22192225
    22202226    // add third point
    2221     FindThirdPointForTesselation(T.NormalVector, SearchDirection, OldSphereCenter, CandidateLine, ThirdNode, RADIUS, LC);
     2227    FindThirdPointForTesselation(T.NormalVector, SearchDirection, T.SphereCenter, CandidateLine, ThirdNode, RADIUS, LC);
    22222228
    22232229  } else {
     
    23502356    AddTesselationPoint((*Sprinter), 2);
    23512357
    2352     Center.CopyVector(&CandidateLine.OptCenter);
     2358
    23532359    // add the lines
    23542360    AddTesselationLine(TPS[0], TPS[1], 0);
     
    23592365    BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount);
    23602366    AddTesselationTriangle();
    2361     Center.Scale(-1.);
     2367    BTS->GetCenter(&Center);
     2368    Center.SubtractVector(&CandidateLine.OptCenter);
     2369    BTS->SphereCenter.CopyVector(&CandidateLine.OptCenter);
    23622370    BTS->GetNormalVector(Center);
    23632371
     
    27662774  Vector NewNormalVector;   // normal vector of the Candidate's triangle
    27672775  Vector helper, OptCandidateCenter, OtherOptCandidateCenter;
     2776  Vector RelativeOldSphereCenter;
     2777  Vector NewPlaneCenter;
    27682778  double CircleRadius; // radius of this circle
    27692779  double radius;
     2780  double otherradius;
    27702781  double alpha, Otheralpha; // angles (i.e. parameter for the circle).
    27712782  int N[NDIM], Nlower[NDIM], Nupper[NDIM];
     
    27832794  CirclePlaneNormal.SubtractVector(CandidateLine.BaseLine->endpoints[1]->node->node);
    27842795
     2796  RelativeOldSphereCenter.CopyVector(&OldSphereCenter);
     2797  RelativeOldSphereCenter.SubtractVector(&CircleCenter);
     2798
    27852799  // calculate squared radius TesselPoint *ThirdNode,f circle
    2786   radius = CirclePlaneNormal.ScalarProduct(&CirclePlaneNormal);
    2787   if (radius/4. < RADIUS*RADIUS) {
    2788     CircleRadius = RADIUS*RADIUS - radius/4.;
     2800  radius = CirclePlaneNormal.NormSquared()/4.;
     2801  if (radius < RADIUS*RADIUS) {
     2802    CircleRadius = RADIUS*RADIUS - radius;
    27892803    CirclePlaneNormal.Normalize();
    2790     //Log() << Verbose(1) << "INFO: CircleCenter is at " << CircleCenter << ", CirclePlaneNormal is " << CirclePlaneNormal << " with circle radius " << sqrt(CircleRadius) << "." << endl;
     2804    Log() << Verbose(1) << "INFO: CircleCenter is at " << CircleCenter << ", CirclePlaneNormal is " << CirclePlaneNormal << " with circle radius " << sqrt(CircleRadius) << "." << endl;
    27912805
    27922806    // test whether old center is on the band's plane
    2793     if (fabs(OldSphereCenter.ScalarProduct(&CirclePlaneNormal)) > HULLEPSILON) {
    2794       eLog() << Verbose(1) << "Something's very wrong here: OldSphereCenter is not on the band's plane as desired by " << fabs(OldSphereCenter.ScalarProduct(&CirclePlaneNormal)) << "!" << endl;
    2795       OldSphereCenter.ProjectOntoPlane(&CirclePlaneNormal);
    2796     }
    2797     radius = OldSphereCenter.ScalarProduct(&OldSphereCenter);
     2807    if (fabs(RelativeOldSphereCenter.ScalarProduct(&CirclePlaneNormal)) > HULLEPSILON) {
     2808      eLog() << Verbose(1) << "Something's very wrong here: RelativeOldSphereCenter is not on the band's plane as desired by " << fabs(RelativeOldSphereCenter.ScalarProduct(&CirclePlaneNormal)) << "!" << endl;
     2809      RelativeOldSphereCenter.ProjectOntoPlane(&CirclePlaneNormal);
     2810    }
     2811    radius = RelativeOldSphereCenter.NormSquared();
    27982812    if (fabs(radius - CircleRadius) < HULLEPSILON) {
    2799       //Log() << Verbose(1) << "INFO: OldSphereCenter is at " << OldSphereCenter << "." << endl;
     2813      Log() << Verbose(1) << "INFO: RelativeOldSphereCenter is at " << RelativeOldSphereCenter << "." << endl;
    28002814
    28012815      // check SearchDirection
    2802       //Log() << Verbose(1) << "INFO: SearchDirection is " << SearchDirection << "." << endl;
    2803       if (fabs(OldSphereCenter.ScalarProduct(&SearchDirection)) > HULLEPSILON) {  // rotated the wrong way!
     2816      Log() << Verbose(1) << "INFO: SearchDirection is " << SearchDirection << "." << endl;
     2817      if (fabs(RelativeOldSphereCenter.ScalarProduct(&SearchDirection)) > HULLEPSILON) {  // rotated the wrong way!
    28042818        eLog() << Verbose(1) << "SearchDirection and RelativeOldSphereCenter are not orthogonal!" << endl;
    28052819      }
     
    28322846
    28332847                // check for three unique points
    2834                 Log() << Verbose(2) << "INFO: Current Candidate is " << *Candidate << " at " << *(Candidate->node) << "." << endl;
     2848                Log() << Verbose(2) << "INFO: Current Candidate is " << *Candidate << " for BaseLine " << *CandidateLine.BaseLine << " with OldSphereCenter " << OldSphereCenter << "." << endl;
    28352849                if ((Candidate != CandidateLine.BaseLine->endpoints[0]->node) && (Candidate != CandidateLine.BaseLine->endpoints[1]->node) ){
    28362850
    2837                   // construct both new centers
    2838                   GetCenterofCircumcircle(&NewSphereCenter, *CandidateLine.BaseLine->endpoints[0]->node->node, *CandidateLine.BaseLine->endpoints[1]->node->node, *Candidate->node);
    2839                   OtherNewSphereCenter.CopyVector(&NewSphereCenter);
    2840 
    2841                   if ((NewNormalVector.MakeNormalVector(CandidateLine.BaseLine->endpoints[0]->node->node, CandidateLine.BaseLine->endpoints[1]->node->node, Candidate->node))
    2842                   && (fabs(NewNormalVector.ScalarProduct(&NewNormalVector)) > HULLEPSILON)
     2851                  // find center on the plane
     2852                  GetCenterofCircumcircle(&NewPlaneCenter, *CandidateLine.BaseLine->endpoints[0]->node->node, *CandidateLine.BaseLine->endpoints[1]->node->node, *Candidate->node);
     2853                  Log() << Verbose(1) << "INFO: NewPlaneCenter is " << NewPlaneCenter << "." << endl;
     2854
     2855                  if (NewNormalVector.MakeNormalVector(CandidateLine.BaseLine->endpoints[0]->node->node, CandidateLine.BaseLine->endpoints[1]->node->node, Candidate->node)
     2856                  && (fabs(NewNormalVector.NormSquared()) > HULLEPSILON)
    28432857                  ) {
    2844                     helper.CopyVector(&NewNormalVector);
    28452858                    Log() << Verbose(1) << "INFO: NewNormalVector is " << NewNormalVector << "." << endl;
    2846                     radius = CandidateLine.BaseLine->endpoints[0]->node->node->DistanceSquared(&NewSphereCenter);
     2859                    radius = CandidateLine.BaseLine->endpoints[0]->node->node->DistanceSquared(&NewPlaneCenter);
     2860                    Log() << Verbose(1) << "INFO: CircleCenter is at " << CircleCenter << ", CirclePlaneNormal is " << CirclePlaneNormal << " with circle radius " << sqrt(CircleRadius) << "." << endl;
     2861                    Log() << Verbose(1) << "INFO: SearchDirection is " << SearchDirection << "." << endl;
     2862                    Log() << Verbose(1) << "INFO: Radius of CircumCenterCircle is " << radius << "." << endl;
    28472863                    if (radius < RADIUS*RADIUS) {
     2864                      otherradius = CandidateLine.BaseLine->endpoints[1]->node->node->DistanceSquared(&NewPlaneCenter);
     2865                      if (fabs(radius - otherradius) > HULLEPSILON) {
     2866                        eLog() << Verbose(1) << "Distance to center of circumcircle is not the same from each corner of the triangle: " << fabs(radius-otherradius) << endl;
     2867                      }
     2868                      // construct both new centers
     2869                      NewSphereCenter.CopyVector(&NewPlaneCenter);
     2870                      OtherNewSphereCenter.CopyVector(&NewPlaneCenter);
     2871                      helper.CopyVector(&NewNormalVector);
    28482872                      helper.Scale(sqrt(RADIUS*RADIUS - radius));
    2849                       Log() << Verbose(2) << "INFO: Distance of NewCircleCenter to NewSphereCenter is " << helper.Norm() << " with sphere radius " << RADIUS << "." << endl;
     2873                      Log() << Verbose(2) << "INFO: Distance of NewPlaneCenter " << NewPlaneCenter << " to either NewSphereCenter is " << helper.Norm() << " of vector " << helper << " with sphere radius " << RADIUS << "." << endl;
    28502874                      NewSphereCenter.AddVector(&helper);
    2851                       NewSphereCenter.SubtractVector(&CircleCenter);
    28522875                      Log() << Verbose(2) << "INFO: NewSphereCenter is at " << NewSphereCenter << "." << endl;
    2853 
    28542876                      // OtherNewSphereCenter is created by the same vector just in the other direction
    28552877                      helper.Scale(-1.);
    28562878                      OtherNewSphereCenter.AddVector(&helper);
    2857                       OtherNewSphereCenter.SubtractVector(&CircleCenter);
    28582879                      Log() << Verbose(2) << "INFO: OtherNewSphereCenter is at " << OtherNewSphereCenter << "." << endl;
    28592880
     
    28612882                      Otheralpha = GetPathLengthonCircumCircle(CircleCenter, CirclePlaneNormal, CircleRadius, OtherNewSphereCenter, OldSphereCenter, NormalVector, SearchDirection);
    28622883                      alpha = min(alpha, Otheralpha);
     2884
    28632885                      // if there is a better candidate, drop the current list and add the new candidate
    28642886                      // otherwise ignore the new candidate and keep the list
     
    28922914                        }
    28932915                      }
    2894 
    28952916                    } else {
    28962917                      Log() << Verbose(1) << "REJECT: NewSphereCenter " << NewSphereCenter << " for " << *Candidate << " is too far away: " << radius << "." << endl;
     
    41274148  Info FunctionInfo(__func__);
    41284149
    4129   /// 1. Find all simply degenerated triangles and sort into a list with each endpoint as key
    4130   map<int, int> * SimplyDegeneratedTriangles = FindAllDegeneratedTriangles();
    4131 
    4132   /// 2. Go through all lines not contained in degenerated triangles.
    4133   UniquePolygonSet ListofFours;
    4134   UniquePolygonSet TestedPolygons;
    4135   for (LineMap::const_iterator LineRunner = LinesOnBoundary.begin(); LineRunner != LinesOnBoundary.end(); LineRunner++) {
    4136     Log() << Verbose(1) << "Current Line is: " << *(LineRunner->second) << endl;
    4137 
    4138     BoundaryPolygonSet *Four = new BoundaryPolygonSet;
    4139 
    4140     /// 2a. Get all four endpoints of the two connected triangles.
    4141     Four->FillPolygonFromTrianglesOfLine((LineRunner->second));
    4142     if (Four->endpoints.size() != 4) {
    4143       Log() << Verbose(0) << "REJECT: There were no four endpoints:" << *Four << endl;
    4144       delete(Four);
    4145       continue;
    4146     }
    4147 
    4148     /// 2b. Get the triangles of all those endpoints
    4149     TriangleSet *T = Four->GetAllContainedTrianglesFromEndpoints();
    4150 
    4151     /// 2c1. Check whether all triangles have (besides sign) same normal vector)
    4152     TriangleSet::const_iterator Runner = T->begin();
    4153     Vector NormalVector;
    4154     NormalVector.CopyVector(&(*Runner)->NormalVector);
    4155     Runner++;
    4156     bool IsPlanar = true;
    4157     for (; Runner != T->end(); Runner++) {
    4158       if (fabs(fabs(NormalVector.ScalarProduct(&(*Runner)->NormalVector)) - 1.) > MYEPSILON)  // check whether all NormalVectors are parallel
    4159         IsPlanar = false;
    4160     }
    4161 
    4162     /// 2c2. check whether triangles are not already simply degenerated.
    4163     size_t DegeneratedCount = 0;
    4164     for (TriangleSet::const_iterator Runner = T->begin(); Runner != T->end(); Runner++) {
    4165       if (SimplyDegeneratedTriangles->find((*Runner)->Nr) != SimplyDegeneratedTriangles->end())
    4166         DegeneratedCount++;
    4167     }
    4168     Log() << Verbose(1) << "Found " << DegeneratedCount << " degenerated triangles." << endl;
    4169 
    4170     if (IsPlanar) {
    4171       if(DegeneratedCount == 0) {
    4172         /// 2c. Find all pairs of those triangles that contain the four endpoints
    4173         const int counter = CountTrianglePairContainingPolygon(Four, T);
    4174         Log() << Verbose(1) << "There are " << counter << " pairs for this polygon of four." << endl;
    4175         if (counter %3 == 0) {
    4176           /// 2d. Check the number of pairs, if greater 1, we have a degenerated polygon (mark down for later use)
    4177           pair < UniquePolygonSet::iterator, bool > Tester = ListofFours.insert(Four);
    4178           if (Tester.second) {
    4179             Log() << Verbose(0) << "ACCEPT: We have a degenerated polygon." << *Four << endl;
    4180           } else {
    4181             Log() << Verbose(0) << "REJECT: Degenerated polygon already present." << *Four << endl;
    4182             delete(Four);
     4150  /// 2. Go through all BoundaryPointSet's, check their triangles' NormalVector
     4151  map <int, int> *DegeneratedTriangles = FindAllDegeneratedTriangles();
     4152  set < BoundaryPointSet *> EndpointCandidateList;
     4153  pair < set < BoundaryPointSet *>::iterator, bool > InsertionTester;
     4154  pair < map < int, Vector *>::iterator, bool > TriangleInsertionTester;
     4155  for (PointMap::const_iterator Runner = PointsOnBoundary.begin(); Runner != PointsOnBoundary.end(); Runner++) {
     4156    Log() << Verbose(0) << "Current point is " << *Runner->second << "." << endl;
     4157    map < int, Vector *> TriangleVectors;
     4158    // gather all NormalVectors
     4159    Log() << Verbose(1) << "Gathering triangles ..." << endl;
     4160    for (LineMap::const_iterator LineRunner = (Runner->second)->lines.begin(); LineRunner != (Runner->second)->lines.end(); LineRunner++)
     4161      for (TriangleMap::const_iterator TriangleRunner = (LineRunner->second)->triangles.begin(); TriangleRunner != (LineRunner->second)->triangles.end(); TriangleRunner++) {
     4162        if (DegeneratedTriangles->find(TriangleRunner->second->Nr) == DegeneratedTriangles->end()) {
     4163          TriangleInsertionTester = TriangleVectors.insert( pair< int, Vector *> ((TriangleRunner->second)->Nr, &((TriangleRunner->second)->NormalVector)) );
     4164          if (TriangleInsertionTester.second)
     4165            Log() << Verbose(1) << " Adding triangle " << *(TriangleRunner->second) << " to triangles to check-list." << endl;
     4166        } else {
     4167          Log() << Verbose(1) << " NOT adding triangle " << *(TriangleRunner->second) << " as it's a simply degenerated one." << endl;
     4168        }
     4169      }
     4170    // check whether there are two that are parallel
     4171    Log() << Verbose(1) << "Finding two parallel triangles ..." << endl;
     4172    for (map < int, Vector *>::iterator VectorWalker = TriangleVectors.begin(); VectorWalker != TriangleVectors.end(); VectorWalker++)
     4173      for (map < int, Vector *>::iterator VectorRunner = VectorWalker; VectorRunner != TriangleVectors.end(); VectorRunner++)
     4174        if (VectorWalker != VectorRunner) { // skip equals
     4175          const double SCP = VectorWalker->second->ScalarProduct(VectorRunner->second);  // ScalarProduct should result in -1. for degenerated triangles
     4176          Log() << Verbose(1) << "Checking " << *VectorWalker->second<< " against " << *VectorRunner->second << ": " << SCP << endl;
     4177          if (fabs(SCP + 1.) < ParallelEpsilon) {
     4178            InsertionTester = EndpointCandidateList.insert((Runner->second));
     4179            if (InsertionTester.second)
     4180              Log() << Verbose(0) << " Adding " << *Runner->second << " to endpoint candidate list." << endl;
     4181            // and break out of both loops
     4182            VectorWalker = TriangleVectors.end();
     4183            VectorRunner = TriangleVectors.end();
     4184            break;
    41834185          }
     4186        }
     4187  }
     4188
     4189  /// 3. Find connected endpoint candidates and put them into a polygon
     4190  UniquePolygonSet ListofDegeneratedPolygons;
     4191  BoundaryPointSet *Walker = NULL;
     4192  BoundaryPointSet *OtherWalker = NULL;
     4193  BoundaryPolygonSet *Current = NULL;
     4194  stack <BoundaryPointSet*> ToCheckConnecteds;
     4195  while (!EndpointCandidateList.empty()) {
     4196    Walker = *(EndpointCandidateList.begin());
     4197    if (Current == NULL) {  // create a new polygon with current candidate
     4198      Log() << Verbose(0) << "Starting new polygon set at point " << *Walker << endl;
     4199      Current = new BoundaryPolygonSet;
     4200      Current->endpoints.insert(Walker);
     4201      EndpointCandidateList.erase(Walker);
     4202      ToCheckConnecteds.push(Walker);
     4203    }
     4204
     4205    // go through to-check stack
     4206    while (!ToCheckConnecteds.empty()) {
     4207      Walker = ToCheckConnecteds.top(); // fetch ...
     4208      ToCheckConnecteds.pop(); // ... and remove
     4209      for (LineMap::const_iterator LineWalker = Walker->lines.begin(); LineWalker != Walker->lines.end(); LineWalker++) {
     4210        OtherWalker = (LineWalker->second)->GetOtherEndpoint(Walker);
     4211        Log() << Verbose(1) << "Checking " << *OtherWalker << endl;
     4212        set < BoundaryPointSet *>::iterator Finder = EndpointCandidateList.find(OtherWalker);
     4213        if (Finder != EndpointCandidateList.end()) {  // found a connected partner
     4214          Log() << Verbose(1) << " Adding to polygon." << endl;
     4215          Current->endpoints.insert(OtherWalker);
     4216          EndpointCandidateList.erase(Finder);  // remove from candidates
     4217          ToCheckConnecteds.push(OtherWalker);  // but check its partners too
    41844218        } else {
    4185           Log() << Verbose(0) << "REJECT: Seems to be the edge line of a degenerated polygon only." << *Four << endl;
    4186           delete(Four);
     4219          Log() << Verbose(1) << " is not connected to " << *Walker << endl;
    41874220        }
    4188       } else {
    4189         Log() << Verbose(0) << "REJECT: This polygon contains some simply degenerated triangles." << endl;
    4190         delete(Four);
    41914221      }
    4192     } else {
    4193       Log() << Verbose(0) << "REJECT: This polygon does not lay on a plane." << endl;
    4194       delete(Four);
    4195     }
    4196 
    4197     delete(T);
    4198   }
    4199 
    4200   /// 3. Combine all edge-connected degenerated polygons
    4201   {
    4202     UniquePolygonSet::iterator PolygonWalker;  // is the inner iterator
    4203     UniquePolygonSet::iterator PolygonSprinter; // is the inner advanced iterator
    4204     for (UniquePolygonSet::iterator PolygonRunner = ListofFours.begin(); PolygonRunner != ListofFours.end(); PolygonRunner++) {
    4205       const BoundaryPolygonSet *P1 = *PolygonRunner;
    4206       Log() << Verbose(1) << "Current Polygon is : " << *P1 << endl;
    4207       PolygonWalker = PolygonRunner;
    4208       PolygonWalker++;
    4209       PolygonSprinter = PolygonWalker;
    4210       while (PolygonWalker != ListofFours.end()) {
    4211         BoundaryPolygonSet *P2 = *PolygonWalker;
    4212         Log() << Verbose(1) << "Current Other Polygon is : " << *P2 << endl;
    4213         PolygonSprinter++;
    4214         Log() << Verbose(1) << "Are " << *P1 << " and " << *P2 << " edge-connected?" << endl;
    4215         if (ArePolygonsEdgeConnected((*PolygonRunner), (P2))) { // if connected
    4216           Log() << Verbose(0) << "Yes!" << endl;
    4217           CombinePolygons((*PolygonRunner), (P2)); // combined and ...
    4218           ListofFours.erase(PolygonWalker); // ... remove from list
    4219           Log() << Verbose(1) << "  New current Polygon is : " << *P1 << endl;
    4220         } else {
    4221           Log() << Verbose(0) << "No." << endl;
    4222         }
    4223         PolygonWalker = PolygonSprinter;
    4224       }
    4225     }
    4226   }
    4227 
    4228   Log() << Verbose(0) << "The following degenerated polygons have been found: " << endl;
    4229   for (UniquePolygonSet::iterator PolygonRunner = ListofFours.begin(); PolygonRunner != ListofFours.end(); PolygonRunner++)
     4222    }
     4223
     4224    Log() << Verbose(0) << "Final polygon is " << *Current << endl;
     4225    ListofDegeneratedPolygons.insert(Current);
     4226    Current = NULL;
     4227  }
     4228
     4229  const int counter = ListofDegeneratedPolygons.size();
     4230
     4231  Log() << Verbose(0) << "The following " << counter << " degenerated polygons have been found: " << endl;
     4232  for (UniquePolygonSet::iterator PolygonRunner = ListofDegeneratedPolygons.begin(); PolygonRunner != ListofDegeneratedPolygons.end(); PolygonRunner++)
    42304233    Log() << Verbose(0) << " " << **PolygonRunner << endl;
    42314234
    42324235  /// 4. Go through all these degenerated polygons
    4233   for (UniquePolygonSet::iterator PolygonRunner = ListofFours.begin(); PolygonRunner != ListofFours.end(); PolygonRunner++) {
     4236  for (UniquePolygonSet::iterator PolygonRunner = ListofDegeneratedPolygons.begin(); PolygonRunner != ListofDegeneratedPolygons.end(); PolygonRunner++) {
    42344237    stack <int> TriangleNrs;
    42354238    Vector NormalVector;
    42364239    /// 4a. Gather all triangles of this polygon
    42374240    TriangleSet *T = (*PolygonRunner)->GetAllContainedTrianglesFromEndpoints();
     4241
     4242    // check whether number is bigger than 2, otherwise it's just a simply degenerated one and nothing to do.
     4243    if (T->size() == 2) {
     4244      Log() << Verbose(1) << " Skipping degenerated polygon, is just a (already simply degenerated) triangle." << endl;
     4245      delete(T);
     4246      continue;
     4247    }
     4248
     4249    // check whether number is even
     4250    // If this case occurs, we have to think about it!
     4251    // The Problem is probably due to two degenerated polygons being connected by a bridging, non-degenerated polygon, as somehow one node has
     4252    // connections to either polygon ...
     4253    if (T->size() % 2 != 0) {
     4254      eLog() << Verbose(0) << " degenerated polygon contains an odd number of triangles, probably contains bridging non-degenerated ones, too!" << endl;
     4255      performCriticalExit();
     4256    }
    42384257
    42394258    TriangleSet::iterator TriangleWalker = T->begin();  // is the inner iterator
     
    42614280    TriangleWalker = T->begin();
    42624281    while (TriangleWalker != T->end()) {  // go through all front triangles
    4263       Log() << Verbose(1) << " Re-creating triangle " << **TriangleWalker << " with NormalVector " << BTS->NormalVector << endl;
     4282      Log() << Verbose(1) << " Re-creating triangle " << **TriangleWalker << " with NormalVector " << (*TriangleWalker)->NormalVector << endl;
    42644283      for (int i = 0; i < 3; i++)
    42654284        AddTesselationPoint((*TriangleWalker)->endpoints[i]->node, i);
     
    42674286      AddTesselationLine(TPS[0], TPS[2], 1);
    42684287      AddTesselationLine(TPS[1], TPS[2], 2);
     4288      if (TriangleNrs.empty())
     4289        eLog() << Verbose(0) << "No more free triangle numbers!" << endl;
    42694290      BTS = new BoundaryTriangleSet(BLS, TriangleNrs.top()); // copy triangle ...
    42704291      AddTesselationTriangle(); // ... and add
     
    42724293      BTS->NormalVector.CopyVector(&(*TriangleWalker)->NormalVector);
    42734294      BTS->NormalVector.Scale(-1.);
    4274       /// 4d. Add all degenerated triangles to the list of simply degenerated triangles
    4275       SimplyDegeneratedTriangles->insert(pair <int, int> ((*TriangleWalker)->Nr, BTS->Nr) );
    4276       SimplyDegeneratedTriangles->insert(pair <int, int> (BTS->Nr, (*TriangleWalker)->Nr) );
    42774295      TriangleWalker++;
    42784296    }
     
    42834301  }
    42844302
     4303  map<int, int> * SimplyDegeneratedTriangles = FindAllDegeneratedTriangles();
    42854304  Log() << Verbose(0) << "Final list of simply degenerated triangles found, containing " << SimplyDegeneratedTriangles->size() << " triangles:" << endl;
    42864305  map<int,int>::iterator it;
    42874306  for (it = SimplyDegeneratedTriangles->begin(); it != SimplyDegeneratedTriangles->end(); it++)
    42884307      Log() << Verbose(0) << (*it).first << " => " << (*it).second << endl;
     4308  delete(SimplyDegeneratedTriangles);
    42894309
    42904310  /// 5. exit
    42914311  UniquePolygonSet::iterator PolygonRunner;
    4292   while (!ListofFours.empty()) {
    4293     PolygonRunner = ListofFours.begin();
     4312  while (!ListofDegeneratedPolygons.empty()) {
     4313    PolygonRunner = ListofDegeneratedPolygons.begin();
    42944314    delete(*PolygonRunner);
    4295     ListofFours.erase(PolygonRunner);
    4296   }
    4297 
    4298   const int counter = SimplyDegeneratedTriangles->size();
    4299   delete(SimplyDegeneratedTriangles);
     4315    ListofDegeneratedPolygons.erase(PolygonRunner);
     4316  }
     4317
    43004318  return counter;
    43014319};
  • src/tesselation.hpp

    r2130dd r73b510  
    4747#define Raster3DSuffix ".r3d"
    4848#define VRMLSUffix ".wrl"
     49
     50#define ParallelEpsilon 1e-3
    4951
    5052// ======================================================= some template functions =========================================
     
    156158    class BoundaryLineSet *lines[3];
    157159    Vector NormalVector;
     160    Vector SphereCenter;
    158161    int Nr;
    159162};
  • src/tesselationhelpers.cpp

    r2130dd r73b510  
    226226  Vector helper;
    227227  double radius, alpha;
    228 
    229   helper.CopyVector(&NewSphereCenter);
     228  Vector RelativeOldSphereCenter;
     229  Vector RelativeNewSphereCenter;
     230
     231  RelativeOldSphereCenter.CopyVector(&OldSphereCenter);
     232  RelativeOldSphereCenter.SubtractVector(&CircleCenter);
     233  RelativeNewSphereCenter.CopyVector(&NewSphereCenter);
     234  RelativeNewSphereCenter.SubtractVector(&CircleCenter);
     235  helper.CopyVector(&RelativeNewSphereCenter);
    230236  // test whether new center is on the parameter circle's plane
    231237  if (fabs(helper.ScalarProduct(&CirclePlaneNormal)) > HULLEPSILON) {
     
    233239    helper.ProjectOntoPlane(&CirclePlaneNormal);
    234240  }
    235   radius = helper.ScalarProduct(&helper);
     241  radius = helper.NormSquared();
    236242  // test whether the new center vector has length of CircleRadius
    237243  if (fabs(radius - CircleRadius) > HULLEPSILON)
    238244    eLog() << Verbose(1) << "The projected center of the new sphere has radius " << radius << " instead of " << CircleRadius << "." << endl;
    239   alpha = helper.Angle(&OldSphereCenter);
     245  alpha = helper.Angle(&RelativeOldSphereCenter);
    240246  // make the angle unique by checking the halfplanes/search direction
    241247  if (helper.ScalarProduct(&SearchDirection) < -HULLEPSILON)  // acos is not unique on [0, 2.*M_PI), hence extra check to decide between two half intervals
    242248    alpha = 2.*M_PI - alpha;
    243   //Log() << Verbose(1) << "INFO: RelativeNewSphereCenter is " << helper << ", RelativeOldSphereCenter is " << OldSphereCenter << " and resulting angle is " << alpha << "." << endl;
    244   radius = helper.Distance(&OldSphereCenter);
     249  Log() << Verbose(1) << "INFO: RelativeNewSphereCenter is " << helper << ", RelativeOldSphereCenter is " << RelativeOldSphereCenter << " and resulting angle is " << alpha << "." << endl;
     250  radius = helper.Distance(&RelativeOldSphereCenter);
    245251  helper.ProjectOntoPlane(&NormalVector);
    246252  // check whether new center is somewhat away or at least right over the current baseline to prevent intersecting triangles
    247253  if ((radius > HULLEPSILON) || (helper.Norm() < HULLEPSILON)) {
    248     //Log() << Verbose(1) << "INFO: Distance between old and new center is " << radius << " and between new center and baseline center is " << helper.Norm() << "." << endl;
     254    Log() << Verbose(1) << "INFO: Distance between old and new center is " << radius << " and between new center and baseline center is " << helper.Norm() << "." << endl;
    249255    return alpha;
    250256  } else {
    251     //Log() << Verbose(1) << "INFO: NewSphereCenter " << helper << " is too close to OldSphereCenter" << OldSphereCenter << "." << endl;
     257    Log() << Verbose(1) << "INFO: NewSphereCenter " << RelativeNewSphereCenter << " is too close to RelativeOldSphereCenter" << RelativeOldSphereCenter << "." << endl;
    252258    return 2.*M_PI;
    253259  }
  • src/vector.cpp

    r2130dd r73b510  
    480480  else
    481481    return false;
     482};
     483
     484/** Checks whether vector is normal to \a *normal.
     485 * @return true - vector is normalized, false - vector is not
     486 */
     487bool Vector::IsEqualTo(const Vector * const a) const
     488{
     489  bool status = true;
     490  for (int i=0;i<NDIM;i++) {
     491    if (fabs(x[i] - a->x[i]) > MYEPSILON)
     492      status = false;
     493  }
     494  return status;
    482495};
    483496
  • src/vector.hpp

    r2130dd r73b510  
    4242  bool IsOne() const;
    4343  bool IsNormalTo(const Vector * const normal) const;
     44  bool IsEqualTo(const Vector * const a) const;
    4445
    4546  void AddVector(const Vector * const y);
Note: See TracChangeset for help on using the changeset viewer.