Changeset 471dec for src/Tesselation


Ignore:
Timestamp:
Mar 28, 2012, 1:23:11 PM (13 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:
03a713
Parents:
368207
git-author:
Frederik Heber <heber@…> (03/14/12 20:22:42)
git-committer:
Frederik Heber <heber@…> (03/28/12 13:23:11)
Message:

Added BoundaryTriangleSet::IsInsideTriangle().

  • this is preparatory for finding a bug in GetClosestPointInsideTriangle().
  • refactored in-test triangle creation into distinct function.
  • added extensive unit test on this function.
Location:
src/Tesselation
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • TabularUnified src/Tesselation/BoundaryTriangleSet.cpp

    r368207 r471dec  
    371371;
    372372
     373/** Checks whether a given point is inside the plane of the triangle and inside the
     374 * bounds defined by its BoundaryLineSet's.
     375 *
     376 * @param point point to check
     377 * @return true - point is inside place and inside all BoundaryLine's
     378 */
     379bool BoundaryTriangleSet::IsInsideTriangle(const Vector &point) const
     380{
     381  Info FunctionInfo(__func__);
     382
     383  // check if it's inside the plane
     384  try {
     385    Plane trianglePlane(
     386        endpoints[0]->node->getPosition(),
     387        endpoints[1]->node->getPosition(),
     388        endpoints[2]->node->getPosition());
     389    if (!trianglePlane.isContained(point)) {
     390      LOG(1, "INFO: Point " << point << " is not inside plane " << trianglePlane << " by "
     391          << trianglePlane.distance(point) << ".");
     392      return false;
     393    }
     394  } catch(LinearDependenceException) {
     395    // triangle is degenerated, it's just a line (i.e. one endpoint is right in between two others
     396    for (size_t i = 0; i < NDIM; ++i) {
     397      try {
     398        Line l = makeLineThrough(
     399            lines[i]->endpoints[0]->node->getPosition(),
     400            lines[i]->endpoints[1]->node->getPosition());
     401        if (l.isContained(GetThirdEndpoint(lines[i])->node->getPosition())) {
     402          // we have the largest of the three lines
     403          LOG(1, "INFO: Linear-dependent case where point " << point << " is on line " << l << ".");
     404          return (l.isContained(point));
     405        }
     406      } catch(ZeroVectorException) {
     407        // two points actually coincide
     408        try {
     409          Line l = makeLineThrough(
     410              lines[i]->endpoints[0]->node->getPosition(),
     411              GetThirdEndpoint(lines[i])->node->getPosition());
     412          LOG(1, "INFO: Degenerated case where point " << point << " is on line " << l << ".");
     413          return (l.isContained(point));
     414        } catch(ZeroVectorException) {
     415          // all three points coincide
     416          if (point.DistanceSquared(lines[i]->endpoints[0]->node->getPosition()) < MYEPSILON) {
     417            LOG(1, "INFO: Full-Degenerated case where point " << point << " is on three endpoints "
     418                << lines[i]->endpoints[0]->node->getPosition() << ".");
     419            return true;
     420          }
     421          else return false;
     422        }
     423      }
     424    }
     425  }
     426
     427  // check whether it lies on the correct side as given by third endpoint for
     428  // each BoundaryLine.
     429  // NOTE: we assume here that endpoints are linear independent, as the case
     430  // has been caught before already extensively
     431  for (size_t i = 0; i < NDIM; ++i) {
     432    Line l = makeLineThrough(
     433        lines[i]->endpoints[0]->node->getPosition(),
     434        lines[i]->endpoints[1]->node->getPosition());
     435    Vector onLine( l.getClosestPoint(point) );
     436    LOG(1, "INFO: Closest point on boundary line is " << onLine << ".");
     437    Vector inTriangleDirection( GetThirdEndpoint(lines[i])->node->getPosition() - onLine );
     438    Vector inPointDirection(point - onLine);
     439    if ((inTriangleDirection.NormSquared() > MYEPSILON) && (inPointDirection.NormSquared() > MYEPSILON))
     440      if (inTriangleDirection.ScalarProduct(inPointDirection) < -MYEPSILON)
     441        return false;
     442  }
     443
     444  return true;
     445}
     446
     447
    373448/** Returns the endpoint which is not contained in the given \a *line.
    374449 * \param *line baseline defining two endpoints
  • TabularUnified src/Tesselation/BoundaryTriangleSet.hpp

    r368207 r471dec  
    4242    bool IsPresentTupel(const BoundaryPointSet * const Points[3]) const;
    4343    bool IsPresentTupel(const BoundaryTriangleSet * const T) const;
     44    bool IsInsideTriangle(const Vector &point) const;
    4445
    4546    Plane getPlane() const;
  • TabularUnified src/Tesselation/unittests/Tesselation_BoundaryTriangleUnitTest.cpp

    r368207 r471dec  
    3030#include "Helpers/defs.hpp"
    3131#include "Atom/TesselPoint.hpp"
     32#include "LinearAlgebra/Plane.hpp"
     33#include "LinearAlgebra/VectorSet.hpp"
    3234#include "Tesselation/BoundaryPointSet.hpp"
    3335#include "Tesselation/BoundaryLineSet.hpp"
     
    4951
    5052
    51 void TesselationBoundaryTriangleTest::setUp()
    52 {
    53   setVerbosity(5);
     53void TesselationBoundaryTriangleTest::createTriangle(const std::vector<Vector> &Vectors)
     54{
     55  CPPUNIT_ASSERT_EQUAL( (size_t)3, Vectors.size() );
    5456
    5557  // create nodes
    56   tesselpoints[0] = new TesselPoint;
    57   tesselpoints[0]->setPosition(Vector(0., 0., 0.));
    58   tesselpoints[0]->setName("1");
    59   tesselpoints[0]->setNr(1);
    60   points[0] = new BoundaryPointSet(tesselpoints[0]);
    61   tesselpoints[1] = new TesselPoint;
    62   tesselpoints[1]->setPosition(Vector(0., 1., 0.));
    63   tesselpoints[1]->setName("2");
    64   tesselpoints[1]->setNr(2);
    65   points[1] = new BoundaryPointSet(tesselpoints[1]);
    66   tesselpoints[2] = new TesselPoint;
    67   tesselpoints[2]->setPosition(Vector(1., 0., 0.));
    68   tesselpoints[2]->setName("3");
    69   tesselpoints[2]->setNr(3);
    70   points[2] = new BoundaryPointSet(tesselpoints[2] );
     58  for (size_t count = 0; count < NDIM; ++count) {
     59    tesselpoints[count] = new TesselPoint;
     60    tesselpoints[count]->setPosition( Vectors[count] );
     61    tesselpoints[count]->setName(toString(count));
     62    tesselpoints[count]->setNr(count);
     63    points[count] = new BoundaryPointSet(tesselpoints[count]);
     64  }
    7165
    7266  // create line
     
    7771  // create triangle
    7872  triangle = new BoundaryTriangleSet(lines, 0);
    79   triangle->GetNormalVector(Vector(0.,0.,1.));
    80 };
    81 
     73  Plane p(Vectors[0], Vectors[1], Vectors[2]);
     74  triangle->GetNormalVector(p.getNormal());
     75}
     76
     77void TesselationBoundaryTriangleTest::setUp()
     78{
     79  setVerbosity(5);
     80
     81  // create nodes
     82  std::vector<Vector> Vectors;
     83  Vectors.push_back( Vector(0., 0., 0.) );
     84  Vectors.push_back( Vector(0., 1., 0.) );
     85  Vectors.push_back( Vector(1., 0., 0.) );
     86
     87  // create triangle
     88  createTriangle(Vectors);
     89}
    8290
    8391void TesselationBoundaryTriangleTest::tearDown()
     
    92100};
    93101
     102/** UnitTest for Tesselation::IsInsideTriangle()
     103 */
     104void TesselationBoundaryTriangleTest::IsInsideTriangleTest()
     105{
     106  // inside points
     107  {
     108    // check each endnode
     109    for (size_t i=0; i< NDIM; ++i) {
     110      const Vector testPoint(triangle->endpoints[i]->node->getPosition());
     111      LOG(1, "INFO: Testing whether " << testPoint << " is an inner point.");
     112      CPPUNIT_ASSERT( triangle->IsInsideTriangle( testPoint ) );
     113    }
     114  }
     115
     116  {
     117    // check points along each BoundaryLine
     118    for (size_t i=0; i< NDIM; ++i) {
     119      Vector offset = triangle->endpoints[i%3]->node->getPosition();
     120      Vector direction = triangle->endpoints[(i+1)%3]->node->getPosition() - offset;
     121      for (double s = 0.1; s < 1.; s+= 0.1) {
     122        Vector testPoint = offset + s*direction;
     123        LOG(1, "INFO: Testing whether " << testPoint << " is an inner point.");
     124        CPPUNIT_ASSERT( triangle->IsInsideTriangle( testPoint ) );
     125      }
     126    }
     127  }
     128
     129  {
     130    // check central point
     131    Vector center;
     132    triangle->GetCenter(center);
     133    LOG(1, "INFO: Testing whether " << center << " is an inner point.");
     134    CPPUNIT_ASSERT( triangle->IsInsideTriangle( center ) );
     135  }
     136
     137  // outside points
     138  {
     139    // check points outside (i.e. those not in xy-plane through origin)
     140    double n[3];
     141    const double boundary = 4.;
     142    const double step = 1.;
     143    // go through the cube and check each point
     144    for (n[0] = -boundary; n[0] <= boundary; n[0]+=step)
     145      for (n[1] = -boundary; n[1] <= boundary; n[1]+=step)
     146        for (n[2] = -boundary; n[2] <= boundary; n[2]+=step) {
     147          const Vector testPoint(n[0], n[1], n[2]);
     148          if (n[2] != 0) {
     149            LOG(1, "INFO: Testing whether " << testPoint << " is not an inner point.");
     150            CPPUNIT_ASSERT( !triangle->IsInsideTriangle( testPoint ) );
     151          }
     152        }
     153  }
     154
     155  {
     156    // check points within the plane but outside of triangle
     157    double n[3];
     158    const double boundary = 4.;
     159    const double step = 1.;
     160    n[2] = 0;
     161    for (n[0] = -boundary; n[0] <= boundary; n[0]+=step)
     162      for (n[1] = -boundary; n[1] <= boundary; n[1]+=step) {
     163        const Vector testPoint(n[0], n[1], n[2]);
     164        if ((n[0] >=0) && (n[1] >=0) && (n[0]<=1) && (n[1]<=1)) {
     165          if (n[0]+n[1] <= 1) {
     166            LOG(1, "INFO: Testing whether " << testPoint << " is an inner point.");
     167            CPPUNIT_ASSERT( triangle->IsInsideTriangle( testPoint) );
     168          } else {
     169            LOG(1, "INFO: Testing whether " << testPoint << " is not an inner point.");
     170            CPPUNIT_ASSERT( !triangle->IsInsideTriangle( testPoint) );
     171          }
     172        } else {
     173          LOG(1, "INFO: Testing whether " << testPoint << " is not an inner point.");
     174          CPPUNIT_ASSERT( !triangle->IsInsideTriangle( testPoint) );
     175        }
     176      }
     177  }
     178}
     179
     180/** UnitTest for Tesselation::IsInsideTriangle()
     181 *
     182 * We test for some specific points that occured in larger examples of the code.
     183 *
     184 */
     185void TesselationBoundaryTriangleTest::IsInsideTriangle_specificTest()
     186{
     187  delete triangle;
     188  {
     189    // test is from --create-micelle 200 --radius 30. --position "0,0,0" of sles.data
     190    // failure is: Intersection (23.1644,24.1867,65.1272) is not inside triangle [659|Na2451,O3652,Na3762].
     191    const Vector testPoint(1.57318,1.57612,10.9874);
     192    const Vector testIntersection(23.1644,24.1867,65.1272);
     193    std::vector<Vector> vectors;
     194    vectors.push_back( Vector(23.0563,30.4673,73.7555) );
     195    vectors.push_back( Vector(25.473,25.1512,68.5467) );
     196    vectors.push_back( Vector(23.1644,24.1867,65.1272) );
     197    createTriangle(vectors);
     198    CPPUNIT_ASSERT( triangle->IsInsideTriangle( testIntersection ) );
     199  }
     200}
     201
    94202/** UnitTest for Tesselation::IsInnerPoint()
    95203 */
  • TabularUnified src/Tesselation/unittests/Tesselation_BoundaryTriangleUnitTest.hpp

    r368207 r471dec  
    1919#include <cppunit/extensions/HelperMacros.h>
    2020
     21#include <vector>
     22
     23#include "LinearAlgebra/Vector.hpp"
    2124#include "LinkedCell/linkedcell.hpp"
    2225#include "Tesselation/tesselation.hpp"
     
    2932{
    3033    CPPUNIT_TEST_SUITE( TesselationBoundaryTriangleTest) ;
     34    CPPUNIT_TEST ( IsInsideTriangleTest );
     35    CPPUNIT_TEST ( IsInsideTriangle_specificTest );
    3136    CPPUNIT_TEST ( GetClosestPointOnPlaneTest );
    3237    CPPUNIT_TEST ( GetClosestPointOffPlaneTest );
     
    3641      void setUp();
    3742      void tearDown();
     43      void IsInsideTriangleTest();
     44      void IsInsideTriangle_specificTest();
    3845      void GetClosestPointOnPlaneTest();
    3946      void GetClosestPointOffPlaneTest();
    4047
    4148private:
     49      void createTriangle(const std::vector<Vector> &Vectors);
     50
    4251      static const double SPHERERADIUS;
    4352
Note: See TracChangeset for help on using the changeset viewer.