| 262 | } |
| 263 | |
| 264 | Expected<void> fillPlanarHole( ObjectMeshData& data, std::vector<EdgeLoop>& holeContours ) |
| 265 | { |
| 266 | MR_TIMER; |
| 267 | |
| 268 | if ( !data.mesh ) |
| 269 | return unexpected( "fillPlanarHole: no input mesh" ); |
| 270 | |
| 271 | auto& mesh = *data.mesh; |
| 272 | auto& tp = mesh.topology; |
| 273 | |
| 274 | // take first edge from each contour and check that it is a hole boundary |
| 275 | EdgePath holesEdges; |
| 276 | for ( const auto& path : holeContours ) |
| 277 | { |
| 278 | if ( path.empty() ) |
| 279 | continue; |
| 280 | for ( auto e : path ) |
| 281 | if ( tp.right( e ).valid() ) |
| 282 | return unexpected( "fillPlanarHole: not hole contour given" ); |
| 283 | holesEdges.push_back( path.front().sym() ); |
| 284 | } |
| 285 | |
| 286 | for ( auto& loop : holeContours ) |
| 287 | { |
| 288 | // if not closed, add edge to enclose |
| 289 | if ( loop.empty() ) |
| 290 | continue; |
| 291 | if ( tp.org( loop.front() ) == tp.dest( loop.back() ) ) |
| 292 | continue; |
| 293 | auto newEdge = makeBridgeEdge( tp, loop.back().sym(), tp.prev( loop.front() ) ); |
| 294 | if ( !newEdge ) |
| 295 | continue; |
| 296 | loop.emplace_back( newEdge ); |
| 297 | } |
| 298 | |
| 299 | const auto fsz0 = tp.faceSize(); |
| 300 | if ( !holesEdges.empty() ) |
| 301 | { |
| 302 | auto fillSuccess = fillContours2D( mesh, holesEdges ); |
| 303 | if ( !fillSuccess.has_value() ) |
| 304 | { |
| 305 | return unexpected( "Cannot fill section: " + fillSuccess.error() ); |
| 306 | } |
| 307 | } |
| 308 | |
| 309 | const auto fsz = tp.faceSize(); |
| 310 | data.selectedFaces.resize( fsz ); |
| 311 | data.selectedFaces.set( FaceId{ fsz0 }, fsz - fsz0, true ); |
| 312 | data.selectedFaces &= tp.getValidFaces(); |
| 313 | |
| 314 | tp.excludeLoneEdges( data.selectedEdges ); |
| 315 | tp.excludeLoneEdges( data.creases ); |
| 316 | |
| 317 | auto& fcm = data.faceColors; |
| 318 | auto& tpf = data.texturePerFace; |
| 319 | if ( fcm.empty() && tpf.empty() ) |
| 320 | return {}; |
| 321 | if ( !fcm.empty() ) |
no test coverage detected