static std::vector<unsigned> calculateActiveGroup(const Cell_handle &cell, unsigned iNearest, const std::vector<SupportItem> &items) { DEBUG_START; Vector_3 xOld = cell->info().point - CGAL::Origin(); std::vector<unsigned> activeGroup; unsigned numUnresolvedCurrent = 0; bool nearestFound = false; for (unsigned iPlane : cell->info().associations) { const SupportItem &item = items[iPlane]; double delta = item.direction * xOld - item.value; std::cout << " delta for plane #" << iPlane << "= " << delta << "; resolved: " << item.resolved << std::endl; if (!item.resolved) { ++numUnresolvedCurrent; if (iPlane == iNearest) { activeGroup.push_back(iPlane); nearestFound = true; } } else activeGroup.push_back(iPlane); } std::cout << " Number of current unresolved items: " << numUnresolvedCurrent << std::endl; if (numUnresolvedCurrent == 0) { DEBUG_END; return std::vector<unsigned>(); } ASSERT(numUnresolvedCurrent > 0 && "Nothing to be resolved"); ASSERT(nearestFound && "Failed to find nearest point inside given " "cell"); ASSERT(activeGroup.size() > NUM_FACET_VERTICES && "Not enough planes"); DEBUG_END; return activeGroup; }
/** * Gets the material for the given point * @param p The point to get the material for * @return The material at the given point */ Contents StoneWeatherer::getContents( const Point & p ) const { // Get a handle to the cell that contains the given point Cell_handle ch = newDT->locate( p ); if ( newDT->is_infinite( ch ) ) { return AIR; } else { return ch->info(); } }
static unsigned getNearestOuterItemID(const Cell_handle &cell, const std::vector<SupportItem> &items, const Vertex_handle &infinity) { DEBUG_START; Plane_3 plane = getOppositeFacetPlane(cell, infinity); Point_3 point = dual(plane); cell->info().point = point; double distanceMin = MINIMIZATION_STARTING_VALUE; unsigned iNearest = 0; const auto &associations = cell->info().associations; unsigned numUnresolved = 0; for (unsigned iPlane : associations) { SupportItem item = items[iPlane]; Vector_3 u = item.direction; double value = item.value; double distance = value - u * (point - CGAL::Origin()); if (!item.resolved) { ASSERT(distance > 0. && "Incorrect resolved flag"); if (distance < distanceMin) { iNearest = iPlane; distanceMin = distance; } ++numUnresolved; } } if (numUnresolved > 0) ASSERT(distanceMin < MINIMIZATION_STARTING_VALUE && "Failed to find"); cell->info().distance = distanceMin; DEBUG_END; return iNearest; }
void DualPolyhedron_3::associateVertex(const Vertex_handle &vertex) { DEBUG_START; int iPlane = vertex->info(); if (isOuterVertex(vertex)) { Cell_handle cell; int iVertex, iInfinity; bool result = is_edge(vertex, infinite_vertex(), cell, iVertex, iInfinity); ASSERT(result && "Wrong set"); TDelaunay_3::Edge edge(cell, iVertex, iInfinity); auto circulator = incident_cells(edge); auto end = circulator; do { Cell_handle currentCell = circulator; ASSERT(currentCell->has_vertex(vertex)); ASSERT(currentCell->has_vertex(infinite_vertex())); currentCell->info().associations.insert(iPlane); items[iPlane].associations.insert(currentCell); items[iPlane].resolved = true; ++circulator; } while (circulator != end); } else { Vector_3 direction = items[iPlane].direction; Cell_handle bestCell = findBestCell(direction, infinite_vertex(), infinite_cell()); bestCell->info().associations.insert(iPlane); /* FIXME: Maybe the association for a plane is singular? */ items[iPlane].associations.insert(bestCell); } DEBUG_END; }
/** * Finds a circumcenter in the grid and labels its associated cell * @param point The location of the circumcenter * @param cell The cell to label * @param midpoint Stores the weighted midpoint of non-air cells * @param volume Accumulates the volume of non-air cells */ void UniformGrid::locateAndLabel( const Point & point, Cell_handle & cell, double * midpoint, double & volume ) const { Point3D p( point.x(), point.y(), point.z() ); unsigned int x = ( unsigned int ) ( ( p.x - xmin ) * inv_Xsize ); unsigned int y = ( unsigned int ) ( ( p.y - ymin ) * inv_Ysize ); unsigned int z = ( unsigned int ) ( ( p.z - zmin ) * inv_Zsize ); unsigned int i = ( ( ( My * z ) + y ) * Mx ) + x; unsigned int start = grid[ i ]; unsigned int end = grid[ i + 1 ]; double tetrahedronVolume = 0.0; for ( i = start; i < end; ++i ) { if ( tetrahedrons[ L[ i ] ]->contains( p ) ) { cell->info() = tetrahedrons[ L[ i ] ]->cell->info(); if ( cell->info() > AIR ) { tetrahedronVolume = Tetrahedron::volume( cell ); #pragma omp critical(updateVolume) { volume += tetrahedronVolume; midpoint[ 0 ] += p.x * tetrahedronVolume; midpoint[ 1 ] += p.y * tetrahedronVolume; midpoint[ 2 ] += p.z * tetrahedronVolume; } } return; } } cell->info() = AIR; }
bool DualPolyhedron_3::lift(Cell_handle cell, unsigned iNearest) { DEBUG_START; Vector_3 xOld = cell->info().point - CGAL::Origin(); std::cout << "Old tangient point: " << xOld << std::endl; const auto activeGroup = calculateActiveGroup(cell, iNearest, items); if (activeGroup.empty()) { DEBUG_END; return false; } Vector_3 xNew = leastSquaresPoint(activeGroup, items); std::cout << "New tangient point: " << xNew << std::endl; ASSERT(cell->has_vertex(infinite_vertex())); unsigned infinityIndex = cell->index(infinite_vertex()); std::vector<Vertex_handle> vertices; Vertex_handle dominator; double alphaMax = 0.; double alphaMax2 = 0.; for (unsigned i = 0; i < NUM_CELL_VERTICES; ++i) { if (i == infinityIndex) continue; vertices.push_back(cell->vertex(i)); Vertex_handle vertex = mirror_vertex(cell, i); Plane_3 plane = ::dual(vertex->point()); double alpha; bool succeeded; std::tie(succeeded, alpha) = calculateAlpha(xOld, xNew, plane); if (!succeeded) return false; std::cout << "Alpha #" << i << ": " << alpha << std::endl; ASSERT(alpha <= 1. && "Wrongly computed alpha"); if (alpha > alphaMax) { alphaMax2 = alphaMax; alphaMax = alpha; dominator = vertex; } } std::cout << "Maximal alpha: " << alphaMax << std::endl; std::cout << "Maximal alpha 2nd: " << alphaMax2 << std::endl; ASSERT(alphaMax < 1. && "What to do then?"); if (alphaMax > 0.) { std::cout << "Full move is impossible, performing partial move" << std::endl; partiallyMove(xOld, xNew, vertices, dominator, alphaMax, alphaMax2); } else { std::cout << "Performing full move" << std::endl; if (!fullyMove(vertices, xNew, activeGroup)) { DEBUG_END; return false; } } DEBUG_END; return true; }