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); }
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); }
RCoordinateEvent::RCoordinateEvent(const RVector& position, RGraphicsScene& s, RGraphicsView& v) : RInputEvent(position, s, v) { modelPosition = position; screenPosition = v.mapToView(position); // RDocumentInterface& documentInterface = s.getDocumentInterface(); // RUcs ucs = documentInterface.getCurrentUcs(); // ucsPosition = ucs.mapToUcs(modelPosition); }
RVector RSnapGrid::snap(const RVector& position, RGraphicsView& view, double range) { Q_UNUSED(range); RGrid* grid = view.getGrid(); if (grid==NULL) { RVector ret = position; ret.valid = false; return ret; } lastSnap = grid->snapToGrid(position); return lastSnap; }
RVector RSnapEntityBase::snap( const RVector& position, RGraphicsView& view, const QSet<REntity::Id>& candidates, const RBox& queryBox) { RDocument* document = view.getDocument(); if (document==NULL) { return lastSnap; } REntity::Id entityId; double minDist = RMAXDOUBLE; double dist; QSet<REntity::Id>::const_iterator it; for (it=candidates.begin(); it!=candidates.end(); it++) { // 20111112: query direct: //QSharedPointer<REntity> e = document->queryEntityDirect(*it); QSharedPointer<REntity> e = document->queryEntity(*it); if (e.isNull()) { continue; } RVector candidate = position.getClosest2D( snapEntity(e, position, queryBox, view) ); dist = candidate.getDistanceTo2D(position); if (dist<minDist) { lastSnap = candidate; minDist = dist; entityId = e->getId(); } } if (!lastSnap.isValid()) { lastSnap = position; lastSnap.valid = false; return lastSnap; } else { entityIds.insert(entityId); return lastSnap; } }
QList<RVector> RSnapTangential::snapEntity( QSharedPointer<REntity> entity, const RVector& point, const RBox& queryBox, RGraphicsView& view) { QList<RVector> ret; RDocumentInterface* di = view.getDocumentInterface(); if (di==NULL) { return ret; } QSharedPointer<RShape> shape = entity->getClosestShape(point, queryBox.getWidth()/2, true); if (shape.isNull()) { return ret; } QSharedPointer<RCircle> circle = shape.dynamicCast<RCircle>(); if (!circle.isNull()) { QList<RLine> lines = circle->getTangents(di->getLastPosition()); for (int i=0; i<lines.length(); i++) { ret.append(lines[i].getEndPoint()); } } QSharedPointer<RArc> arc = shape.dynamicCast<RArc>(); if (!arc.isNull()) { QList<RLine> lines = arc->getTangents(di->getLastPosition()); for (int i=0; i<lines.length(); i++) { ret.append(lines[i].getEndPoint()); } } QSharedPointer<REllipse> ellipse = shape.dynamicCast<REllipse>(); if (!ellipse.isNull()) { QList<RLine> lines = ellipse->getTangents(di->getLastPosition()); for (int i=0; i<lines.length(); i++) { ret.append(lines[i].getEndPoint()); } } return ret; }
QList<RVector> RSnapPerpendicular::snapEntity( QSharedPointer<REntity> entity, const RVector& point, const RBox& queryBox, RGraphicsView& view) { QList<RVector> ret; RDocumentInterface* di = view.getDocumentInterface(); if (di==NULL) { return ret; } QSharedPointer<RShape> shape = entity->getClosestShape(point, queryBox.getWidth()/2, true); if (shape.isNull()) { return ret; } ret.append(shape->getClosestPointOnShape(di->getLastPosition(), false)); return ret; }
QList<RVector> ROrthoGrid::getIdealGridSpacing(RGraphicsView& view, int minPixelSpacing, const RVector& minSpacing, const RVector& minMetaSpacing) { RS::Unit unit = view.getDocument()->getUnit(); RS::LinearFormat linearFormat = view.getDocument()->getLinearFormat(); QList<RVector> ret; if (isFractionalFormat(linearFormat) && !RUnit::isMetric(unit)) { double idealInchSpacing = RUnit::convert(view.mapDistanceFromView(qMax(minPixelSpacing, 1)), unit, RS::Inch); RVector spacing = RUnit::convert(minSpacing, unit, RS::Inch); spacing.x = inchAutoscale(spacing.x, idealInchSpacing, unit); spacing.y = inchAutoscale(spacing.y, idealInchSpacing, unit); spacing = RUnit::convert(spacing, RS::Inch, unit); // never drop below min spacing: if (spacing.x<minSpacing.x) { spacing.x = minSpacing.x; } if (spacing.y<minSpacing.y) { spacing.y = minSpacing.y; } RVector metaSpacing = spacing; // RVector(1.0 / 64, 1.0 / 64, 1.0 / 64); metaSpacing.x = inchAutoscale(metaSpacing.x, idealInchSpacing * 4, unit); metaSpacing.y = inchAutoscale(metaSpacing.y, idealInchSpacing * 4, unit); metaSpacing = RUnit::convert(metaSpacing, RS::Inch, unit); // never drop below min spacing: if (metaSpacing.x<minMetaSpacing.x) { metaSpacing.x = minMetaSpacing.x; } if (metaSpacing.y<minMetaSpacing.y) { metaSpacing.y = minMetaSpacing.y; } // foot: never show meta grid of < 1 foot: if (unit==RS::Foot) { if (metaSpacing.x<1.0) { metaSpacing.x = 1.0; } if (metaSpacing.y<1.0) { metaSpacing.y = 1.0; } } // if (metaSpacing.x < this->metaSpacing.x) { // metaSpacing.x = this->metaSpacing.x; // } ret.append(spacing); ret.append(metaSpacing); return ret; } else { // ideal (minimum) grid spacing for the given view (some odd number): double idealSpacing = view.mapDistanceFromView(qMax(minPixelSpacing, 1)); // idealSpacing = minSpacing * idealFactor RVector idealFactor(idealSpacing / minSpacing.x, idealSpacing / minSpacing.y); // idealFactor = minSpacing * 10^n RVector n(log(idealFactor.x / minSpacing.x) / log(10.0), log(idealFactor.y / minSpacing.y) / log(10.0)); // factor = minSpacing * 10^ceil(n) RVector factor(minSpacing.x * pow(10.0, ceil(n.x - 1.0e-6)), minSpacing.y * pow(10.0, ceil(n.y - 1.0e-6))); // never drop below min spacing: if (factor.x<1.0) { factor.x = 1.0; } if (factor.y<1.0) { factor.y = 1.0; } // grid spacing: double x, y; x = minSpacing.x * factor.x; y = minSpacing.y * factor.y; ret.append(RVector(x,y)); // meta grid spacing: double mx, my; if (RMath::isNaN(minMetaSpacing.x)) { mx = x * 10; } else { //mx = minMetaSpacing.x * factor.x; mx = minMetaSpacing.x; } if (RMath::isNaN(minMetaSpacing.y)) { my = y * 10; } else { //my = minMetaSpacing.y * factor.y; my = minMetaSpacing.y; } ret.append(RVector(mx, my)); //ret.append(RVector(minSpacing.x * factor.x, minSpacing.y * factor.y)); //ret.append(RVector(minMetaSpacing.x * factor.x, minMetaSpacing.y * factor.y)); //ret.append(ret.at(0) * 10); return ret; } }
RVector RSnapIntersection::snap( const RVector& position, RGraphicsView& view, const QMap<REntity::Id, QSet<int> >& candidates, const RBox& queryBox) { RDocument* document = view.getDocument(); if (document==NULL) { return lastSnap; } REntity::Id entityId1 = REntity::INVALID_ID; REntity::Id entityId2 = REntity::INVALID_ID; lastSnap = RVector::invalid; double minDist = RMAXDOUBLE; double dist; QMap<REntity::Id, QSet<int> >::const_iterator it1; for (it1=candidates.begin(); it1!=candidates.end(); it1++) { if (RMouseEvent::hasMouseMoved()) { lastSnap = RVector::invalid; return RVector::invalid; } QSharedPointer<REntity> e1 = document->queryEntityDirect(it1.key()); if (e1.isNull()) { continue; } if (e1->getType()==RS::EntityText || e1->getType()==RS::EntityAttribute || e1->getType()==RS::EntityAttributeDefinition) { continue; } QMap<REntity::Id, QSet<int> >::const_iterator it2; for (it2=it1; it2!=candidates.end(); it2++) { if (RMouseEvent::hasMouseMoved()) { lastSnap = RVector::invalid; return RVector::invalid; } QSharedPointer<REntity> e2 = document->queryEntityDirect(it2.key()); if (e2.isNull()) { continue; } if (e2->getType()==RS::EntityText || e2->getType()==RS::EntityAttribute || e2->getType()==RS::EntityAttributeDefinition) { continue; } QList<RVector> candidates = e1->getIntersectionPoints(*e2, true, queryBox); if (candidates.isEmpty()) { continue; } RVector candidate = position.getClosest(candidates); dist = candidate.getDistanceTo(position); if (dist<minDist) { lastSnap = candidate; minDist = dist; entityId1 = e1->getId(); entityId2 = e2->getId(); } } } if (!lastSnap.isValid()) { lastSnap = position; lastSnap.valid = false; return lastSnap; } else { if (entityId1!=REntity::INVALID_ID) { entityIds.insert(entityId1); } if (entityId2!=REntity::INVALID_ID) { entityIds.insert(entityId2); } return lastSnap; } }
RVector RRestrictOrthogonal::restrictSnap(const RVector& position, const RVector& relativeZero) { RVector ret; RVector retX; RVector retY; if (documentInterface==NULL) { return ret; } RGraphicsView* view = documentInterface->getLastKnownViewWithFocus(); if (view==NULL) { return ret; } ROrthoGrid* grid = dynamic_cast<ROrthoGrid*>(view->getGrid()); if (grid!=NULL && grid->isIsometric()) { double d1, d2; double a1, a2; switch (grid->getProjection()) { default: case RS::IsoTop: a1 = RMath::deg2rad(30); a2 = RMath::deg2rad(150); // d1 = x / cos(30): d1 = (position.x - relativeZero.x) / (sqrt(3.0)/2); d2 = -d1; break; case RS::IsoLeft: a1 = RMath::deg2rad(150); a2 = RMath::deg2rad(90); d1 = (position.x - relativeZero.x) / (-sqrt(3.0)/2); d2 = (position.y - relativeZero.y); break; case RS::IsoRight: a1 = RMath::deg2rad(30); a2 = RMath::deg2rad(90); d1 = (position.x - relativeZero.x) / (sqrt(3.0)/2); d2 = (position.y - relativeZero.y); break; } retX = relativeZero + RVector::createPolar(d1, a1); retY = relativeZero + RVector::createPolar(d2, a2); } else { retX = RVector(relativeZero.x, position.y); retY = RVector(position.x, relativeZero.y); } switch (mode) { case RRestrictOrthogonal::Vertical: ret = retX; break; case RRestrictOrthogonal::Horizonal: ret = retY; break; case RRestrictOrthogonal::Orthogonal: if (retX.getDistanceTo(position) > retY.getDistanceTo(position)) { ret = retY; } else { ret = retX; } break; } lastSnap = ret; return ret; }
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; }