Ignore:
Timestamp:
Aug 10, 2009, 4:11:47 PM (16 years ago)
Author:
Frederik Heber <heber@…>
Children:
ada6d2
Parents:
0cf171
Message:

New function ConvexizeNonconvexEnvelope() to calculate the volume of a non-convex envelope.

The central idea is that the volume of a convex envelope is easy to determine as a sum of pyramids with respect to a center inside the envelope. Hence, if we can "reduce" the non-convex envelope to a convex one in such a way that we know the added volume, we may determine the volume of a non-convex envelope.
The nice side effect is that we may use our Find_non_convex_border() algorithm to calculate also the convex envelope.

  • We go through all BoundaryPoints and check whether one of its Baselines does not fulfill the ConvexCriterion. If so, we remove it, as it can not be a boundary point on the convex envelope, and re-construct the attached triangles. The added volume is a general tetraeder, whose formula is known.
  • FIX: Find_convex_border() - We check whether AddPoint is successful or not.
  • builder.cpp: case 'o' - changed to use ConvexizeNonconvexEnvelope() instead of Find_convex_border()
  • Tesselation:AddPoint() - now takes second argument which is the index for BPS and always set BPS to either the newly created or the already present point. Return argument discerns between new and already present point.
  • Tesselation::BPS, BLS, BTS are now public not private. We have to access them from ConvexizeNonconvexEnvelope()
File:
1 edited

Legend:

Unmodified
Added
Removed
  • molecuilder/src/boundary.cpp

    r0cf171 r70c4567  
    476476  for (int axis = 0; axis < NDIM; axis++)
    477477    for (Boundaries::iterator runner = BoundaryPoints[axis].begin(); runner != BoundaryPoints[axis].end(); runner++)
    478         mol->TesselStruct->AddPoint(runner->second.second);
     478        if (!mol->TesselStruct->AddPoint(runner->second.second, 0))
     479          *out << Verbose(3) << "WARNING: Point " << *(runner->second.second) << " is already present!" << endl;
    479480
    480481  *out << Verbose(2) << "I found " << mol->TesselStruct->PointsOnBoundaryCount << " points on the convex boundary." << endl;
     
    560561};
    561562
     563/** Creates a convex envelope from a given non-convex one.
     564 * -# We go through all PointsOnBoundary.
     565 * -# We look at each of its lines and CheckConvexityCriterion().
     566 * -# If any returns concave, this Point cannot be on the final convex envelope.
     567 * -# Hence, we remove it and re-create all its triangles from its getCircleOfConnectedPoints()
     568 * -# We calculate the additional volume
     569 * -# We go over the points until none yields a concave spot anymore.
     570 *
     571 * Note: This routine - for free - calculates the difference in volume between convex and
     572 * non-convex envelope, as the former is easy to calculate - VolumeOfConvexEnvelope() - it
     573 * can be used to compute volumes of arbitrary shapes.
     574 * \param *out output stream for debugging
     575 * \param *TesselStruct non-convex envelope, is changed in return!
     576 * \param *configuration contains IsAngstroem()
     577 * \return volume difference between the non- and the created convex envelope
     578 */
     579double ConvexizeNonconvexEnvelope(ofstream *out, class Tesselation *TesselStruct)
     580{
     581  double volume = 0;
     582  class BoundaryPointSet *point = NULL;
     583  class BoundaryLineSet *line = NULL;
     584  class BoundaryTriangleSet *triangle = NULL;
     585  Vector OldPoint, TetraederVector[3];
     586  *out << Verbose(0) << "Begin of ConvexizeNonconvexEnvelope" << endl;
     587
     588  if (TesselStruct == NULL) {
     589    *out << Verbose(1) << "ERROR: TesselStruct is empty!" << endl;
     590    return volume;
     591  }
     592
     593  bool AllConvex = true;
     594  bool Convexity = false;
     595  do {
     596    AllConvex = true;
     597    for (PointMap::iterator PointRunner = TesselStruct->PointsOnBoundary.begin(); PointRunner != TesselStruct->PointsOnBoundary.end(); PointRunner++) {
     598      point = PointRunner->second;
     599      *out << Verbose(1) << "INFO: Current point is " << *point << "." << endl;
     600      Convexity = true;
     601      for (LineMap::iterator LineRunner = point->lines.begin(); LineRunner != point->lines.end(); LineRunner++) {
     602        line = LineRunner->second;
     603        *out << Verbose(2) << "INFO: Current line is " << *line << "." << endl;
     604        if (line->CheckConvexityCriterion(out)) {
     605          // convex
     606        } else { // concave
     607          Convexity = false; // we have to go again through all ...
     608          break;  // no need to check the others too
     609        }
     610      }
     611      AllConvex = AllConvex && Convexity;
     612      if (!Convexity) {
     613        *out << Verbose(1) << "... point cannot be on convex envelope." << endl;
     614        OldPoint.CopyVector(point->node->node);
     615        // get list of connected points
     616        BoundaryPointSet *Otherpoint = line->GetOtherEndpoint(point);
     617        list<TesselPoint*> *CircleofPoints = TesselStruct->getCircleOfConnectedPoints(out, point->node, Otherpoint->node->node);
     618        // remove all triangles
     619        int *numbers = NULL;
     620        int count = 0;
     621        int i=0;
     622        for (LineMap::iterator LineRunner = point->lines.begin(); LineRunner != point->lines.end(); LineRunner++)
     623          count+=LineRunner->second->triangles.size();
     624        numbers = new int[count];
     625        for (LineMap::iterator LineRunner = point->lines.begin(); LineRunner != point->lines.end(); LineRunner++) {
     626          line = LineRunner->second;
     627          for (TriangleMap::iterator TriangleRunner = line->triangles.begin(); TriangleRunner != line->triangles.end(); TriangleRunner++) {
     628            triangle = TriangleRunner->second;
     629            *out << Verbose(2) << "Erasing triangle " << *triangle << "." << endl;
     630            numbers[i] = triangle->Nr;
     631            TesselStruct->TrianglesOnBoundary.erase(triangle->Nr);
     632            delete(triangle);
     633            i++;
     634          }
     635        }
     636        *out << Verbose(1) << i << " triangles were removed." << endl;
     637
     638        // re-create all triangles by going through connected points list
     639        list<TesselPoint*>::iterator OtherCircleRunner = CircleofPoints->end();
     640        OtherCircleRunner--;
     641        i=0;
     642        for (list<TesselPoint*>::iterator CircleRunner = CircleofPoints->begin(); CircleRunner != CircleofPoints->end(); CircleRunner++) {
     643          *out << Verbose(2) << "Adding new triangle points."<< endl;
     644          TesselStruct->AddPoint(point->node, 0);
     645          TesselStruct->AddPoint(*CircleRunner, 1);
     646          TesselStruct->AddPoint(*OtherCircleRunner, 2);
     647          *out << Verbose(2) << "Adding new triangle lines."<< endl;
     648          TesselStruct->AddTriangleLine(TesselStruct->BPS[0], TesselStruct->BPS[1], 0);
     649          TesselStruct->AddTriangleLine(TesselStruct->BPS[0], TesselStruct->BPS[2], 1);
     650          TesselStruct->AddTriangleLine(TesselStruct->BPS[1], TesselStruct->BPS[2], 2);
     651          TesselStruct->BTS = new class BoundaryTriangleSet(TesselStruct->BLS, numbers[i]);
     652          TesselStruct->TrianglesOnBoundary.insert(TrianglePair(numbers[i], triangle));
     653          *out << Verbose(2) << "Created triangle " << *TesselStruct->BTS << "." << endl;
     654          // calculate volume summand as a general tetraeder
     655          for (int j=0;j<3;j++) {
     656            TetraederVector[j].CopyVector(TesselStruct->BPS[j]->node->node);
     657            TetraederVector[j].SubtractVector(&OldPoint);
     658          }
     659          OldPoint.CopyVector(&TetraederVector[0]);
     660          OldPoint.VectorProduct(&TetraederVector[1]);
     661          volume += 1./6. * fabs(OldPoint.ScalarProduct(&TetraederVector[2]));
     662          // advance other shank
     663          OtherCircleRunner++;
     664          if (OtherCircleRunner == CircleofPoints->end())
     665            OtherCircleRunner = CircleofPoints->begin();
     666          // advance number
     667          i++;
     668          if (i > count)
     669            *out << Verbose(2) << "WARNING: Maximum of numbers reached!" << endl;
     670        }
     671        *out << Verbose(1) << i << " triangles were created." << endl;
     672       
     673        delete[](numbers);
     674      }
     675    }
     676  } while (!AllConvex);
     677  *out << Verbose(0) << "End of ConvexizeNonconvexEnvelope" << endl;
     678
     679  // end
     680  return volume;
     681};
    562682
    563683/** Determines the volume of a cluster.
Note: See TracChangeset for help on using the changeset viewer.