// public methods: QScriptValue REcmaSnapGrid::snap (QScriptContext* context, QScriptEngine* engine) { //REcmaHelper::functionStart("REcmaSnapGrid::snap", context, engine); //qDebug() << "ECMAScript WRAPPER: REcmaSnapGrid::snap"; //QCoreApplication::processEvents(); QScriptValue result = engine->undefinedValue(); // public function: can be called from ECMA wrapper of ECMA shell: RSnapGrid* self = getSelf("snap", context); //Q_ASSERT(self!=NULL); if (self==NULL) { return REcmaHelper::throwError("self is NULL", context); } if( context->argumentCount() == 2 && ( context->argument(0).isVariant() || context->argument(0).isQObject() || context->argument(0).isNull() ) /* type: RVector */ && ( context->argument(1).isVariant() || context->argument(1).isQObject() || context->argument(1).isNull() ) /* type: RGraphicsView */ ){ // prepare arguments: // argument isCopyable and has default constructor and isSimpleClass RVector* ap0 = qscriptvalue_cast< RVector* >( context->argument( 0 ) ); if (ap0 == NULL) { return REcmaHelper::throwError("RSnapGrid: Argument 0 is not of type RVector.", context); } RVector a0 = *ap0; // argument is reference RGraphicsView* ap1 = qscriptvalue_cast< RGraphicsView* >( context->argument( 1 ) ); if( ap1 == NULL ){ return REcmaHelper::throwError("RSnapGrid: Argument 1 is not of type RGraphicsView*.", context); } RGraphicsView& a1 = *ap1; // end of arguments // call C++ function: // return type 'RVector' RVector cppResult = self->snap(a0 , a1); // return type: RVector // not standard type nor reference result = qScriptValueFromValue(engine, cppResult); } else if( context->argumentCount() == 3 && ( context->argument(0).isVariant() || context->argument(0).isQObject() || context->argument(0).isNull() ) /* type: RVector */ && ( context->argument(1).isVariant() || context->argument(1).isQObject() || context->argument(1).isNull() ) /* type: RGraphicsView */ && ( context->argument(2).isNumber() ) /* type: double */ ){ // prepare arguments: // argument isCopyable and has default constructor and isSimpleClass RVector* ap0 = qscriptvalue_cast< RVector* >( context->argument( 0 ) ); if (ap0 == NULL) { return REcmaHelper::throwError("RSnapGrid: Argument 0 is not of type RVector.", context); } RVector a0 = *ap0; // argument is reference RGraphicsView* ap1 = qscriptvalue_cast< RGraphicsView* >( context->argument( 1 ) ); if( ap1 == NULL ){ return REcmaHelper::throwError("RSnapGrid: Argument 1 is not of type RGraphicsView*.", context); } RGraphicsView& a1 = *ap1; // argument isStandardType double a2 = (double) context->argument( 2 ). toNumber(); // end of arguments // call C++ function: // return type 'RVector' RVector cppResult = self->snap(a0 , a1 , a2); // return type: RVector // not standard type nor reference result = qScriptValueFromValue(engine, cppResult); } else { return REcmaHelper::throwError("Wrong number/types of arguments for RSnapGrid.snap().", context); } //REcmaHelper::functionEnd("REcmaSnapGrid::snap", context, engine); return result; }
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; }