Extrudes the given polygon along the direction, converts it into an opening or applies all openings as necessary.
| 521 | |
| 522 | // Extrudes the given polygon along the direction, converts it into an opening or applies all openings as necessary. |
| 523 | void ProcessExtrudedArea(const Schema_2x3::IfcExtrudedAreaSolid& solid, const TempMesh& curve, |
| 524 | const IfcVector3& extrusionDir, TempMesh& result, ConversionData &conv, bool collect_openings) |
| 525 | { |
| 526 | // Outline: 'curve' is now a list of vertex points forming the underlying profile, extrude along the given axis, |
| 527 | // forming new triangles. |
| 528 | const bool has_area = solid.SweptArea->ProfileType == "AREA" && curve.mVerts.size() > 2; |
| 529 | if (solid.Depth < ai_epsilon) { |
| 530 | if( has_area ) { |
| 531 | result.Append(curve); |
| 532 | } |
| 533 | return; |
| 534 | } |
| 535 | |
| 536 | result.mVerts.reserve(curve.mVerts.size()*(has_area ? 4 : 2)); |
| 537 | result.mVertcnt.reserve(curve.mVerts.size() + 2); |
| 538 | std::vector<IfcVector3> in = curve.mVerts; |
| 539 | |
| 540 | // First step: transform all vertices into the target coordinate space |
| 541 | IfcMatrix4 trafo; |
| 542 | ConvertAxisPlacement(trafo, solid.Position); |
| 543 | |
| 544 | IfcVector3 vmin, vmax; |
| 545 | MinMaxChooser<IfcVector3>()(vmin, vmax); |
| 546 | for(IfcVector3& v : in) { |
| 547 | v *= trafo; |
| 548 | |
| 549 | vmin = std::min(vmin, v); |
| 550 | vmax = std::max(vmax, v); |
| 551 | } |
| 552 | |
| 553 | vmax -= vmin; |
| 554 | const IfcFloat diag = vmax.Length(); |
| 555 | IfcVector3 dir = IfcMatrix3(trafo) * extrusionDir; |
| 556 | |
| 557 | // reverse profile polygon if it's winded in the wrong direction in relation to the extrusion direction |
| 558 | IfcVector3 profileNormal = TempMesh::ComputePolygonNormal(in.data(), in.size()); |
| 559 | if( profileNormal * dir < 0.0 ) { |
| 560 | std::reverse(in.begin(), in.end()); |
| 561 | } |
| 562 | |
| 563 | std::vector<IfcVector3> nors; |
| 564 | const bool openings = !!conv.apply_openings && conv.apply_openings->size(); |
| 565 | |
| 566 | // Compute the normal vectors for all opening polygons as a prerequisite |
| 567 | // to TryAddOpenings_Poly2Tri() |
| 568 | // XXX this belongs into the aforementioned function |
| 569 | if( openings ) { |
| 570 | |
| 571 | if( !conv.settings.useCustomTriangulation ) { |
| 572 | // it is essential to apply the openings in the correct spatial order. The direction |
| 573 | // doesn't matter, but we would screw up if we started with e.g. a door in between |
| 574 | // two windows. |
| 575 | std::sort(conv.apply_openings->begin(), conv.apply_openings->end(), TempOpening::DistanceSorter(in[0])); |
| 576 | } |
| 577 | |
| 578 | nors.reserve(conv.apply_openings->size()); |
| 579 | for(TempOpening& t : *conv.apply_openings) { |
| 580 | TempMesh &bounds = *t.profileMesh; |
no test coverage detected