float CollisionTile::placeFeature(const CollisionFeature &feature, const bool allowOverlap, const bool avoidEdges) { float minPlacementScale = minScale; for (auto& box : feature.boxes) { const auto anchor = box.anchor.matMul(rotationMatrix); if (!allowOverlap) { std::vector<CollisionTreeBox> blockingBoxes; tree.query(bgi::intersects(getTreeBox(anchor, box)), std::back_inserter(blockingBoxes)); for (auto& blockingTreeBox : blockingBoxes) { const auto& blocking = std::get<1>(blockingTreeBox); auto blockingAnchor = blocking.anchor.matMul(rotationMatrix); minPlacementScale = findPlacementScale(minPlacementScale, anchor, box, blockingAnchor, blocking); if (minPlacementScale >= maxScale) return minPlacementScale; } } if (avoidEdges) { const vec2<float> tl = { box.x1, box.y1 }; const vec2<float> tr = { box.x2, box.y1 }; const vec2<float> bl = { box.x1, box.y2 }; const vec2<float> br = { box.x2, box.y2 }; const vec2<float> rtl = tl.matMul(reverseRotationMatrix); const vec2<float> rtr = tr.matMul(reverseRotationMatrix); const vec2<float> rbl = bl.matMul(reverseRotationMatrix); const vec2<float> rbr = br.matMul(reverseRotationMatrix); CollisionBox rotatedBox(box.anchor, ::fmin(::fmin(rtl.x, rtr.x), ::fmin(rbl.x, rbr.x)), ::fmin(::fmin(rtl.y, rtr.y), ::fmin(rbl.y, rbr.y)), ::fmax(::fmax(rtl.x, rtr.x), ::fmax(rbl.x, rbr.x)), ::fmax(::fmax(rtl.y, rtr.y), ::fmax(rbl.y, rbr.y)), box.maxScale); for (auto& blocking : edges) { minPlacementScale = findPlacementScale(minPlacementScale, box.anchor, rotatedBox, blocking.anchor, blocking); if (minPlacementScale >= maxScale) return minPlacementScale; } } } return minPlacementScale; }
float CollisionTile::placeFeature(const CollisionFeature& feature, const bool allowOverlap, const bool avoidEdges) { float minPlacementScale = minScale; for (auto& box : feature.boxes) { const auto anchor = util::matrixMultiply(rotationMatrix, box.anchor); if (!allowOverlap) { for (auto it = tree.qbegin(bgi::intersects(getTreeBox(anchor, box))); it != tree.qend(); ++it) { const CollisionBox& blocking = std::get<1>(*it); Point<float> blockingAnchor = util::matrixMultiply(rotationMatrix, blocking.anchor); minPlacementScale = findPlacementScale(minPlacementScale, anchor, box, blockingAnchor, blocking); if (minPlacementScale >= maxScale) return minPlacementScale; } } if (avoidEdges) { const Point<float> tl = { box.x1, box.y1 }; const Point<float> tr = { box.x2, box.y1 }; const Point<float> bl = { box.x1, box.y2 }; const Point<float> br = { box.x2, box.y2 }; const Point<float> rtl = util::matrixMultiply(reverseRotationMatrix, tl); const Point<float> rtr = util::matrixMultiply(reverseRotationMatrix, tr); const Point<float> rbl = util::matrixMultiply(reverseRotationMatrix, bl); const Point<float> rbr = util::matrixMultiply(reverseRotationMatrix, br); CollisionBox rotatedBox(box.anchor, ::fmin(::fmin(rtl.x, rtr.x), ::fmin(rbl.x, rbr.x)), ::fmin(::fmin(rtl.y, rtr.y), ::fmin(rbl.y, rbr.y)), ::fmax(::fmax(rtl.x, rtr.x), ::fmax(rbl.x, rbr.x)), ::fmax(::fmax(rtl.y, rtr.y), ::fmax(rbl.y, rbr.y)), box.maxScale); for (auto& blocking : edges) { minPlacementScale = findPlacementScale(minPlacementScale, box.anchor, rotatedBox, blocking.anchor, blocking); if (minPlacementScale >= maxScale) return minPlacementScale; } } } return minPlacementScale; }