| 252 | } |
| 253 | |
| 254 | Expected<MR::Mesh> selfBoolean( const Mesh& inMesh ) |
| 255 | { |
| 256 | auto box = Box3d( inMesh.computeBoundingBox() ); |
| 257 | CoordinateConverters converters{ .toInt = getToIntConverter( box ),.toFloat = getToFloatConverter( box ) }; |
| 258 | std::vector<EdgeTri> intersections; |
| 259 | ContinuousContours contours; |
| 260 | |
| 261 | Mesh mesh = inMesh; |
| 262 | |
| 263 | int iters = 0; |
| 264 | const int cMaxFixLoneIterations = 3; // lets not do it many times |
| 265 | for ( ;; ++iters ) |
| 266 | { |
| 267 | // find intersections |
| 268 | intersections = findSelfCollidingEdgeTrisPrecise( mesh, converters.toInt ); |
| 269 | // order intersections |
| 270 | contours = orderSelfIntersectionContours( mesh.topology, intersections ); |
| 271 | |
| 272 | // find lone |
| 273 | auto loneProcessing = detail::subdivideSelfLone( mesh, converters, contours ); |
| 274 | if ( loneProcessing == detail::LoneProccessingState::None ) |
| 275 | break; |
| 276 | else if ( loneProcessing == detail::LoneProccessingState::DegenerateOnly || iters == cMaxFixLoneIterations ) |
| 277 | { |
| 278 | // in some rare cases there are lone contours with zero area that cannot be resolved |
| 279 | // they lead to infinite loop, so just try to remove them |
| 280 | removeLoneContours( contours, true ); |
| 281 | break; |
| 282 | } |
| 283 | } |
| 284 | |
| 285 | auto holePairs = detail::findSelfContoursMapping( contours ); |
| 286 | auto meshCpy = mesh; // for now lets do copy each time, TODO: do copy only if needed |
| 287 | auto intContours = getOneMeshSelfIntersectionContours( mesh, contours, converters ); |
| 288 | |
| 289 | // update non-closed |
| 290 | ParallelFor( holePairs, [&] ( size_t hpId ) |
| 291 | { |
| 292 | auto [f, s, r] = holePairs[hpId]; |
| 293 | auto& cf = contours[f]; |
| 294 | if ( isClosed( cf ) ) |
| 295 | return; |
| 296 | |
| 297 | if ( cf.capacity() < 2 * cf.size() + 3 ) |
| 298 | cf.reserve( 2 * cf.size() + 3 ); |
| 299 | auto& icf = intContours[f].intersections; |
| 300 | if ( icf.capacity() < 2 * icf.size() + 3 ) |
| 301 | icf.reserve( 2 * icf.size() + 3 ); |
| 302 | |
| 303 | auto& cs = contours[s]; |
| 304 | auto& ics = intContours[s].intersections; |
| 305 | |
| 306 | auto prev = mesh.topology.prev( cf.front().edge ); |
| 307 | auto next = mesh.topology.next( cf.back().edge ); |
| 308 | auto svId = mesh.topology.dest( prev ); |
| 309 | auto fvId = mesh.topology.dest( next ); |
| 310 | |
| 311 | auto triFVerts = mesh.topology.getTriVerts( cf.front().tri() ); |
no test coverage detected