| 130 | }; |
| 131 | |
| 132 | Expected<ProjectedFillMesh> fillProjected( const MeshTopology& tp, const ProjectFillInput& input ) |
| 133 | { |
| 134 | MR_TIMER; |
| 135 | ProjectedFillMesh res; |
| 136 | |
| 137 | auto holeVertIds = std::make_unique<PlanarTriangulation::HolesVertIds>( |
| 138 | PlanarTriangulation::findHoleVertIdsByHoleEdges( tp, input.paths ) ); |
| 139 | |
| 140 | auto fillResult = PlanarTriangulation::triangulateDisjointContours( input.holes2d, holeVertIds.get(), &res.paths ); |
| 141 | holeVertIds.reset(); |
| 142 | if ( !fillResult ) |
| 143 | return unexpected( "Cannot triangulate contours with self-intersections" ); |
| 144 | |
| 145 | res.mesh = std::move( *fillResult ); |
| 146 | |
| 147 | |
| 148 | if ( input.paths.size() != res.paths.size() ) |
| 149 | return unexpected( "Patch surface borders size different from original mesh borders size" ); |
| 150 | |
| 151 | std::vector<EdgePath> invertedHoles; |
| 152 | invertedHoles.reserve( res.paths.size() ); |
| 153 | for ( int i = 0; i < res.paths.size(); ++i ) |
| 154 | { |
| 155 | if ( input.paths[i].size() != res.paths[i].size() ) |
| 156 | return unexpected( "Patch surface borders size different from original mesh borders size" ); |
| 157 | |
| 158 | // degenerate holes might invert sometimes (it is expected as far as planar triangulation does not now about input topology) |
| 159 | if ( res.paths[i].empty() || res.mesh.topology.right( res.paths[i].front() ) ) |
| 160 | if ( !res.paths[i].empty() ) |
| 161 | MR::reverse( invertedHoles.emplace_back( res.paths[i] ) ); |
| 162 | } |
| 163 | if ( !invertedHoles.empty() ) |
| 164 | { |
| 165 | auto invertedParts = fillContourLeft( res.mesh.topology, invertedHoles ); |
| 166 | auto invertedEdges = getIncidentEdges( res.mesh.topology, invertedParts ); |
| 167 | res.mesh.topology.flipOrientation( &invertedEdges ); |
| 168 | |
| 169 | // validate one more time |
| 170 | for ( int i = 0; i < res.paths.size(); ++i ) |
| 171 | if ( res.paths[i].empty() || res.mesh.topology.right( res.paths[i].front() ) ) |
| 172 | if ( !res.paths[i].empty() ) |
| 173 | return unexpected( "Patch surface borders are incompatible with mesh borders" ); |
| 174 | } |
| 175 | return res; |
| 176 | } |
| 177 | |
| 178 | Expected<void> fillContours2D( Mesh& mesh, const std::vector<EdgeId>& holeRepresentativeEdges ) |
| 179 | { |
no test coverage detected