RVector RSnapEntityBase::snap( const RVector& position, RGraphicsView& view, double range) { entityIds.clear(); RDocument* document = view.getDocument(); lastSnap = RVector::invalid; if (document==NULL) { lastSnap = position; lastSnap.valid = false; return lastSnap; } if (RMath::isNaN(range)) { int rangePixels = RSettings::getSnapRange(); range = view.mapDistanceFromView(rangePixels); } RBox queryBox(position, range); QSet<REntity::Id> candidates = document->queryIntersectedEntitiesXY( queryBox, true, true, RBlock::INVALID_ID); return snap(position, view, candidates, queryBox); }
RVector RSnapIntersection::snap( const RVector& position, RGraphicsView& view, double range) { entityIds.clear(); RDocument* document = view.getDocument(); if (document==NULL) { lastSnap = position; return lastSnap; } if (RMath::isNaN(range)) { int rangePixels = RSettings::getSnapRange(); range = view.mapDistanceFromView(rangePixels); } RBox queryBox(position, range); QMap<REntity::Id, QSet<int> > ids = document->queryIntersectedShapesXY( queryBox, true /*false?*/, true, RBlock::INVALID_ID, QList<RS::EntityType>() << RS::EntityHatch); return snap(position, view, ids, queryBox); }
std::vector<IndexedSubfeature> CollisionTile::queryRenderedSymbols(const mapbox::geometry::box<int16_t>& box, const float scale) { std::vector<IndexedSubfeature> result; std::unordered_map<std::string, std::unordered_set<std::size_t>> sourceLayerFeatures; auto anchor = util::matrixMultiply(rotationMatrix, convertPoint<float>(box.min)); CollisionBox queryBox(anchor, 0, 0, box.max.x - box.min.x, box.max.y - box.min.y, scale); auto predicates = bgi::intersects(getTreeBox(anchor, queryBox)); auto fn = [&] (const Tree& tree_) { for (auto it = tree_.qbegin(predicates); it != tree_.qend(); ++it) { const CollisionBox& blocking = std::get<1>(*it); const IndexedSubfeature& indexedFeature = std::get<2>(*it); auto& seenFeatures = sourceLayerFeatures[indexedFeature.sourceLayerName]; if (seenFeatures.find(indexedFeature.index) == seenFeatures.end()) { auto blockingAnchor = util::matrixMultiply(rotationMatrix, blocking.anchor); float minPlacementScale = findPlacementScale(minScale, anchor, queryBox, blockingAnchor, blocking); if (minPlacementScale >= scale) { seenFeatures.insert(indexedFeature.index); result.push_back(indexedFeature); } } } }; fn(tree); fn(ignoredTree); return result; }
std::vector<IndexedSubfeature> CollisionTile::queryRenderedSymbols(const float minX, const float minY, const float maxX, const float maxY, const float scale) { std::vector<IndexedSubfeature> result; auto anchor = vec2<float>(minX, minY).matMul(rotationMatrix); CollisionBox queryBox(anchor, 0, 0, maxX - minX, maxY - minY, scale); std::vector<CollisionTreeBox> blockingBoxes; tree.query(bgi::intersects(getTreeBox(anchor, queryBox)), std::back_inserter(blockingBoxes)); ignoredTree.query(bgi::intersects(getTreeBox(anchor, queryBox)), std::back_inserter(blockingBoxes)); std::unordered_map<std::string, std::set<std::size_t>> sourceLayerFeatures; for (auto& blockingTreeBox : blockingBoxes) { const auto& blocking = std::get<1>(blockingTreeBox); auto& indexedFeature = blocking.indexedFeature; auto& seenFeatures = sourceLayerFeatures[indexedFeature.sourceLayerName]; if (seenFeatures.find(indexedFeature.index) == seenFeatures.end()) { auto blockingAnchor = blocking.anchor.matMul(rotationMatrix); float minPlacementScale = findPlacementScale(minScale, anchor, queryBox, blockingAnchor, blocking); if (minPlacementScale >= scale) { seenFeatures.insert(indexedFeature.index); result.push_back(indexedFeature); } } } return result; }
void Physics::computeBoundingShapes(const float& elapsedTime) { for (std::set<Entity*>::iterator it = movingEntity.begin(); it != movingEntity.end(); it++) { RigidBody* rigidbody = (*it)->getComponent<RigidBody>(); glm::vec3 delta = rigidbody->predictPosition - (*it)->getPosition(); AxisAlignedBox firstBox = (*it)->getShape().toAxisAlignedBox(); AxisAlignedBox finalBox = AxisAlignedBox(firstBox); finalBox.transform(delta, glm::vec3(1.f), rigidbody->deltaRotation); glm::vec3 queryMin = glm::min(firstBox.min, finalBox.min); glm::vec3 queryMax = glm::min(firstBox.max, finalBox.max); AxisAlignedBox queryBox(queryMin, queryMax); } }
RVector RSnapAuto::snap(const RVector& position, RGraphicsView& view, double range) { entityIds.clear(); if (RMath::isNaN(range)) { int rangePixels = RSettings::getSnapRange(); range = view.mapDistanceFromView(rangePixels); } RDocument* document = view.getDocument(); if (document==NULL) { lastSnap = position; return lastSnap; } RSnapAuto::init(); if (RMath::isNaN(range)) { int rangePixels = RSettings::getSnapRange(); range = view.mapDistanceFromView(rangePixels); } // matching ids per query range: QList<QSet<REntity::Id> > idsList; QList<RBox> queryBoxList; bool foundEntities = false; for (double r=range/1.0; r<=range+RS::PointTolerance; r+=range/1.0) { RBox queryBox(position, r); queryBoxList.append(queryBox); QMap<REntity::Id, QSet<int> > ids = document->queryIntersectedShapesXY( queryBox, true, true, RBlock::INVALID_ID // 20151027: allow snapping to hatch end points, etc: /*, QList<RS::EntityType>() << RS::EntityHatch*/); idsList.append(ids.keys().toSet()); if (ids.isEmpty()) { continue; } foundEntities = true; // intersection if (intersections) { RSnapIntersection snapIntersection; lastSnap = snapIntersection.snap(position, view, ids, queryBox); if (lastSnap.isValid() && lastSnap.getDistanceTo2d(position) < range) { status = RSnap::Intersection; entityIds = snapIntersection.getEntityIds(); return lastSnap; } } lastSnap = RVector::invalid; } // interrupted by mouse move: if (RMouseEvent::hasMouseMoved()) { status = RSnap::Free; return position; } // end points: if (foundEntities && endPoints) { for (int k=0; k<idsList.size() && k<queryBoxList.size(); k++) { // query box and matching IDs cached from intersection snap: RBox queryBox = queryBoxList.at(k); QSet<REntity::Id> ids = idsList.at(k); RSnapEnd snapEnd; lastSnap = snapEnd.snap(position, view, ids, queryBox); if (lastSnap.isValid() && lastSnap.getDistanceTo2d(position) < range) { status = RSnap::Endpoint; entityIds = snapEnd.getEntityIds(); return lastSnap; } } lastSnap = RVector::invalid; } // middle points: if (foundEntities && middlePoints) { for (int k=0; k<idsList.size() && k<queryBoxList.size(); k++) { // query box and matching IDs cached from intersection snap: RBox queryBox = queryBoxList.at(k); QSet<REntity::Id> ids = idsList.at(k); RSnapMiddle snapMiddle; lastSnap = snapMiddle.snap(position, view, ids, queryBox); if (lastSnap.isValid() && lastSnap.getDistanceTo2d(position) < range) { status = RSnap::Middle; entityIds = snapMiddle.getEntityIds(); return lastSnap; } } lastSnap = RVector::invalid; } // center points: if (foundEntities && centerPoints) { for (int k=0; k<idsList.size() && k<queryBoxList.size(); k++) { // query box and matching IDs cached from intersection snap: RBox queryBox = queryBoxList.at(k); QSet<REntity::Id> ids = idsList.at(k); RSnapCenter snapCenter; lastSnap = snapCenter.snap(position, view, ids, queryBox); if (lastSnap.isValid() && lastSnap.getDistanceTo2d(position) < range) { status = RSnap::Center; entityIds = snapCenter.getEntityIds(); return lastSnap; } } lastSnap = RVector::invalid; } // perpendicular: if (foundEntities && perpendicular) { for (int k=0; k<idsList.size() && k<queryBoxList.size(); k++) { // query box and matching IDs cached from intersection snap: RBox queryBox = queryBoxList.at(k); QSet<REntity::Id> ids = idsList.at(k); RSnapPerpendicular snapPerpendicular; lastSnap = snapPerpendicular.snap(position, view, ids, queryBox); if (lastSnap.isValid() && lastSnap.getDistanceTo2d(position) < range) { status = RSnap::Perpendicular; entityIds = snapPerpendicular.getEntityIds(); return lastSnap; } } lastSnap = RVector::invalid; } // reference points: if (foundEntities && referencePoints) { for (int k=0; k<idsList.size() && k<queryBoxList.size(); k++) { // query box and matching IDs cached from intersection snap: RBox queryBox = queryBoxList.at(k); QSet<REntity::Id> ids = idsList.at(k); RSnapReference snapReference; lastSnap = snapReference.snap(position, view, ids, queryBox); if (lastSnap.isValid() && lastSnap.getDistanceTo2d(position) < range) { status = RSnap::Reference; entityIds = snapReference.getEntityIds(); return lastSnap; } } lastSnap = RVector::invalid; } // grid points: if (gridPoints) { RSnapGrid snapGrid; lastSnap = snapGrid.snap(position, view, range); if (lastSnap.isValid() && lastSnap.getDistanceTo2d(position) < range) { status = RSnap::Grid; return lastSnap; } lastSnap = RVector::invalid; } // on entity snap is slow and almost never used: if (foundEntities && pointsOnEntity) { for (int k=0; k<idsList.size() && k<queryBoxList.size(); k++) { // query box and matching IDs cached from intersection snap: RBox queryBox = queryBoxList.at(k); QSet<REntity::Id> ids = idsList.at(k); // on entity RSnapOnEntity snapOnEntity; lastSnap = snapOnEntity.snap(position, view, ids, queryBox); if (lastSnap.isValid() && lastSnap.getDistanceTo2d(position) < range) { status = RSnap::OnEntity; entityIds = snapOnEntity.getEntityIds(); return lastSnap; } } lastSnap = RVector::invalid; } // free: if (freePositioning) { lastSnap = position; status = RSnap::Free; return lastSnap; } return RVector::invalid; }