| 692 | } |
| 693 | |
| 694 | void ApplyAreaFeature::ProcessBuildingPolygon(m2::PointD const & p1, m2::PointD const & p2, m2::PointD const & p3) |
| 695 | { |
| 696 | // For building we must filter degenerate polygons because now we have to reconstruct |
| 697 | // building outline by bunch of polygons. |
| 698 | // TODO(pastk) : filter degenerates in the generator.(see a TODO above). |
| 699 | m2::PointD const v1 = p2 - p1; |
| 700 | m2::PointD const v2 = p3 - p1; |
| 701 | if (v1.IsAlmostZero() || v2.IsAlmostZero()) |
| 702 | return; |
| 703 | |
| 704 | double const crossProduct = m2::CrossProduct(v1.Normalize(), v2.Normalize()); |
| 705 | double constexpr kEps = 0.01; |
| 706 | if (fabs(crossProduct) < kEps) |
| 707 | return; |
| 708 | |
| 709 | // Triangles near to degenerate are drawn two-side, because we can't strictly determine |
| 710 | // vertex traversal direction. |
| 711 | double constexpr kTwoSideEps = 0.05; |
| 712 | bool const isTwoSide = fabs(crossProduct) < kTwoSideEps; |
| 713 | |
| 714 | auto const i1 = GetIndex(p1); |
| 715 | auto const i2 = GetIndex(p2); |
| 716 | auto const i3 = GetIndex(p3); |
| 717 | if (crossProduct < 0) |
| 718 | { |
| 719 | m_triangles.push_back(p1); |
| 720 | m_triangles.push_back(p2); |
| 721 | m_triangles.push_back(p3); |
| 722 | BuildEdges(i1, i2, i3, isTwoSide); |
| 723 | } |
| 724 | else |
| 725 | { |
| 726 | m_triangles.push_back(p1); |
| 727 | m_triangles.push_back(p3); |
| 728 | m_triangles.push_back(p2); |
| 729 | BuildEdges(i1, i3, i2, isTwoSide); |
| 730 | } |
| 731 | } |
| 732 | |
| 733 | int ApplyAreaFeature::GetIndex(m2::PointD const & pt) |
| 734 | { |
nothing calls this directly
no test coverage detected