| 338 | } |
| 339 | |
| 340 | void distanceMapFromContours( DistanceMap & distMap, const Polyline2& polyline, const ContourToDistanceMapParams& params, |
| 341 | const ContoursDistanceMapOptions& options ) |
| 342 | { |
| 343 | MR_TIMER; |
| 344 | assert( polyline.topology.isConsistentlyOriented() ); |
| 345 | assert( distMap.resX() == params.resolution.x ); |
| 346 | assert( distMap.resY() == params.resolution.y ); |
| 347 | if ( !polyline.topology.lastNotLoneEdge().valid() ) |
| 348 | return; |
| 349 | |
| 350 | if ( options.offsetParameters ) |
| 351 | { |
| 352 | bool goodSize = options.offsetParameters->perEdgeOffset.size() >= polyline.topology.undirectedEdgeSize(); |
| 353 | if ( !goodSize ) |
| 354 | { |
| 355 | assert( false ); |
| 356 | spdlog::error( "Offset per edges should contain offset for all edges" ); |
| 357 | return; |
| 358 | } |
| 359 | } |
| 360 | |
| 361 | const Vector3f originPoint = Vector3f{ params.orgPoint.x, params.orgPoint.y, 0.f } + |
| 362 | Vector3f{ params.pixelSize.x / 2.f, params.pixelSize.y / 2.f, 0.f }; |
| 363 | |
| 364 | size_t size = size_t( params.resolution.x ) * params.resolution.y; |
| 365 | if ( options.outClosestEdges ) |
| 366 | options.outClosestEdges->resize( size ); |
| 367 | |
| 368 | const auto maxDistSq = sqr( options.maxDist ); |
| 369 | const auto minDistSq = sqr( options.minDist ); |
| 370 | ParallelFor( (size_t)0, size, [&] ( size_t i ) |
| 371 | { |
| 372 | if ( options.region && !options.region->test( PixelId( int( i ) ) ) ) |
| 373 | { |
| 374 | distMap.set( i, DistanceMap::NOT_VALID_VALUE ); |
| 375 | return; |
| 376 | } |
| 377 | size_t x = i % params.resolution.x; |
| 378 | size_t y = i / params.resolution.x; |
| 379 | Vector2f p; |
| 380 | p.x = params.pixelSize.x * x + originPoint.x; |
| 381 | p.y = params.pixelSize.y * y + originPoint.y; |
| 382 | Polyline2ProjectionWithOffsetResult res; |
| 383 | if ( options.offsetParameters ) |
| 384 | { |
| 385 | res = findProjectionOnPolyline2WithOffset( p, polyline, options.offsetParameters->perEdgeOffset, options.maxDist, nullptr, options.minDist ); |
| 386 | } |
| 387 | else |
| 388 | { |
| 389 | auto noOffsetRes = findProjectionOnPolyline2( p, polyline, maxDistSq, nullptr, minDistSq ); |
| 390 | res.line = noOffsetRes.line; |
| 391 | res.point = noOffsetRes.point; |
| 392 | res.dist = std::sqrt( noOffsetRes.distSq ); |
| 393 | } |
| 394 | |
| 395 | if ( options.outClosestEdges ) |
| 396 | ( *options.outClosestEdges )[i] = res.line; |
| 397 | |