void ccGraphicalTransformationTool::clear() { m_toTransform.detatchAllChildren(); m_rotation.toIdentity(); m_translation = CCVector3d(0,0,0); m_rotationCenter = CCVector3d(0,0,0); }
void ccGraphicalTransformationTool::reset() { m_rotation.toIdentity(); m_translation = CCVector3d(0,0,0); updateAllGLTransformations(); }
bool ccGraphicalTransformationTool::start() { assert(!m_processing); assert(m_associatedWin); if (!m_associatedWin) return false; unsigned childNum = m_toTransform.getChildrenNumber(); if (childNum == 0) return false; m_rotation.toIdentity(); m_translation = CCVector3d(0,0,0); m_rotationCenter = CCVector3d::fromArray(m_toTransform.getBB_recursive().getCenter().u); //m_rotation center == selected entities center //activate "moving mode" in associated GL window m_associatedWin->setInteractionMode(ccGLWindow::TRANSFORM_ENTITY); m_associatedWin->setPickingMode(ccGLWindow::NO_PICKING); //the user must not close this window! m_associatedWin->setUnclosable(true); connect(m_associatedWin, SIGNAL(rotation(const ccGLMatrixd&)), this, SLOT(glRotate(const ccGLMatrixd&))); connect(m_associatedWin, SIGNAL(translation(const CCVector3d&)), this, SLOT(glTranslate(const CCVector3d&))); m_associatedWin->displayNewMessage(QString(),ccGLWindow::UPPER_CENTER_MESSAGE); //clear the area m_associatedWin->displayNewMessage("[Rotation/Translation mode]",ccGLWindow::UPPER_CENTER_MESSAGE,false,3600,ccGLWindow::MANUAL_TRANSFORMATION_MESSAGE); m_associatedWin->redraw(true, false); return ccOverlayDialog::start(); }
bool ccGenericPointCloud::isClicked(const CCVector2d& clickPos, int& nearestPointIndex, double& nearestSquareDist, const double* MM, const double* MP, const int* VP, double pickWidth/*=2.0*/, double pickHeight/*=2.0*/) { ccGLMatrix trans; bool noGLTrans = !getAbsoluteGLTransformation(trans); //back project the clicked point in 3D CCVector3d clickPosd(clickPos.x, clickPos.y, 0); CCVector3d X(0,0,0); ccGL::Unproject<double, double>(clickPosd, MM, MP, VP, X); nearestPointIndex = -1; nearestSquareDist = -1.0; #if defined(_OPENMP) #pragma omp parallel for #endif //brute force works quite well in fact?! for (unsigned i=0; i<size(); ++i) { const CCVector3* P = getPoint(i); CCVector3d Qs; if (noGLTrans) { ccGL::Project<PointCoordinateType, double>(*P,MM,MP,VP,Qs); } else { CCVector3 Q = *P; trans.apply(Q); ccGL::Project<PointCoordinateType, double>(Q,MM,MP,VP,Qs); } if (fabs(Qs.x-clickPos.x) <= pickWidth && fabs(Qs.y-clickPos.y) <= pickHeight) { double squareDist = CCVector3d(X.x-P->x, X.y-P->y, X.z-P->z).norm2d(); if (nearestPointIndex < 0 || squareDist < nearestSquareDist) { nearestSquareDist = squareDist; nearestPointIndex = static_cast<int>(i); } } } return (nearestPointIndex >= 0); }
void ccCameraParamEditDlg::cameraCenterChanged() { if (!m_associatedWin) return; m_associatedWin->blockSignals(true); m_associatedWin->setCameraPos( CCVector3d( exDoubleSpinBox->value(), eyDoubleSpinBox->value(), ezDoubleSpinBox->value() )); m_associatedWin->blockSignals(false); m_associatedWin->redraw(); }
//============================================pivotChanged==================================================// // GLWindow->setPivotPoint(CCVector3d & P);//设置的时候阻塞信号 void ccCameraParamEditDlg::pivotChanged() { if (!m_associatedWin) return; m_associatedWin->blockSignals(true); m_associatedWin->setPivotPoint(CCVector3d(rcxDoubleSpinBox->value(), rcyDoubleSpinBox->value(), rczDoubleSpinBox->value()) ); m_associatedWin->blockSignals(false); //重新绘制场景 m_associatedWin->redraw(); }
CCVector3d ccGlobalShiftManager::BestShift(const CCVector3d& P) { if (!NeedShift(P)) { return CCVector3d(0,0,0); } CCVector3d shift( fabs(P[0]) >= MAX_COORDINATE_ABS_VALUE ? -P[0] : 0, fabs(P[1]) >= MAX_COORDINATE_ABS_VALUE ? -P[1] : 0, fabs(P[2]) >= MAX_COORDINATE_ABS_VALUE ? -P[2] : 0 ); //round-off to the nearest hundred shift.x = static_cast<int>(shift.x / 100) * 100.0; shift.y = static_cast<int>(shift.y / 100) * 100.0; shift.z = static_cast<int>(shift.z / 100) * 100.0; return shift; }
bool ccPointPairRegistrationDlg::convertToSphereCenter(CCVector3d& P, ccHObject* entity, PointCoordinateType& sphereRadius) { sphereRadius = -PC_ONE; if ( !entity || !useSphereToolButton->isChecked() || !entity->isKindOf(CC_TYPES::POINT_CLOUD) ) //only works with cloud right now { //nothing to do return true; } //we'll now try to detect the sphere double searchRadius = radiusDoubleSpinBox->value(); double maxRMSPercentage = maxRmsSpinBox->value() / 100.0; ccGenericPointCloud* cloud = static_cast<ccGenericPointCloud*>(entity); assert(cloud); //crop points inside a box centered on the current point ccBBox box; box.add(CCVector3::fromArray((P - CCVector3d(1,1,1)*searchRadius).u)); box.add(CCVector3::fromArray((P + CCVector3d(1,1,1)*searchRadius).u)); CCLib::ReferenceCloud* part = cloud->crop(box,true); bool success = false; if (part && part->size() > 16) { PointCoordinateType radius; CCVector3 C; double rms; ccProgressDialog pDlg(true, this); //first roughly search for the sphere if (CCLib::GeometricalAnalysisTools::detectSphereRobust(part,0.5,C,radius,rms,&pDlg,0.9)) { if (radius / searchRadius < 0.5 || radius / searchRadius > 2.0) { ccLog::Warning(QString("[ccPointPairRegistrationDlg] Detected sphere radius (%1) is too far from search radius!").arg(radius)); } else { //now look again (more precisely) { delete part; box.clear(); box.add(C - CCVector3(1,1,1)*radius*static_cast<PointCoordinateType>(1.05)); //add 5% box.add(C + CCVector3(1,1,1)*radius*static_cast<PointCoordinateType>(1.05)); //add 5% part = cloud->crop(box,true); if (part && part->size() > 16) CCLib::GeometricalAnalysisTools::detectSphereRobust(part,0.5,C,radius,rms,&pDlg,0.99); } ccLog::Print(QString("[ccPointPairRegistrationDlg] Detected sphere radius = %1 (rms = %2)").arg(radius).arg(rms)); if (radius / searchRadius < 0.5 || radius / searchRadius > 2.0) { ccLog::Warning("[ccPointPairRegistrationDlg] Sphere radius is too far from search radius!"); } else if (rms / searchRadius >= maxRMSPercentage) { ccLog::Warning("[ccPointPairRegistrationDlg] RMS is too high!"); } else { sphereRadius = radius; P = CCVector3d::fromArray(C.u); success = true; } } } else { ccLog::Warning("[ccPointPairRegistrationDlg] Failed to fit a sphere around the picked point!"); } } else { //not enough memory? No points inside the ccLog::Warning("[ccPointPairRegistrationDlg] Failed to crop points around the picked point?!"); } if (part) delete part; return success; }
void ccPointListPickingDlg::exportToASCII(ExportFormat format) { if (!m_associatedCloud) return; //get all labels std::vector<cc2DLabel*> labels; unsigned count = getPickedPoints(labels); if (count == 0) return; QSettings settings; settings.beginGroup("PointListPickingDlg"); QString filename = settings.value("filename", "picking_list.txt").toString(); settings.endGroup(); filename = QFileDialog::getSaveFileName(this, "Export to ASCII", filename, AsciiFilter::GetFileFilter()); if (filename.isEmpty()) return; settings.beginGroup("PointListPickingDlg"); settings.setValue("filename", filename); settings.endGroup(); FILE* fp = fopen(qPrintable(filename),"wt"); if (!fp) { ccLog::Error(QString("Failed to open file '%1' for saving!").arg(filename)); return; } //if a global shift exists, ask the user if it should be applied CCVector3d shift = m_associatedCloud->getGlobalShift(); double scale = m_associatedCloud->getGlobalScale(); if (shift.norm2() != 0 || scale != 1.0) { if (QMessageBox::warning( this, "Apply global shift", "Do you want to apply global shift/scale to exported points?", QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes ) == QMessageBox::No) { //reset shift shift = CCVector3d(0,0,0); scale = 1.0; } } //starting index int startIndex = startIndexSpinBox->value(); for (unsigned i=0; i<count; ++i) { assert(labels[i]->size() == 1); const cc2DLabel::PickedPoint& PP = labels[i]->getPoint(0); const CCVector3* P = PP.cloud->getPoint(PP.index); if (format == PLP_ASCII_EXPORT_IXYZ) fprintf(fp,"%i,",i+startIndex); fprintf(fp,"%.12f,%.12f,%.12f\n", static_cast<double>(P->x)/scale - shift.x, static_cast<double>(P->y)/scale - shift.y, static_cast<double>(P->z)/scale - shift.z); } fclose(fp); ccLog::Print(QString("[I/O] File '%1' saved successfully").arg(filename)); }
bool ccClipBox::move3D(const CCVector3d& uInput) { if (m_activeComponent == NONE || !m_box.isValid()) return false; CCVector3d u = uInput; //Arrows if (m_activeComponent >= X_MINUS_ARROW && m_activeComponent <= CROSS) { if (m_glTransEnabled) m_glTrans.inverse().applyRotation(u); switch(m_activeComponent) { case X_MINUS_ARROW: m_box.minCorner().x += static_cast<PointCoordinateType>(u.x); if (m_box.minCorner().x > m_box.maxCorner().x) m_box.minCorner().x = m_box.maxCorner().x; break; case X_PLUS_ARROW: m_box.maxCorner().x += static_cast<PointCoordinateType>(u.x); if (m_box.minCorner().x > m_box.maxCorner().x) m_box.maxCorner().x = m_box.minCorner().x; break; case Y_MINUS_ARROW: m_box.minCorner().y += static_cast<PointCoordinateType>(u.y); if (m_box.minCorner().y > m_box.maxCorner().y) m_box.minCorner().y = m_box.maxCorner().y; break; case Y_PLUS_ARROW: m_box.maxCorner().y += static_cast<PointCoordinateType>(u.y); if (m_box.minCorner().y > m_box.maxCorner().y) m_box.maxCorner().y = m_box.minCorner().y; break; case Z_MINUS_ARROW: m_box.minCorner().z += static_cast<PointCoordinateType>(u.z); if (m_box.minCorner().z > m_box.maxCorner().z) m_box.minCorner().z = m_box.maxCorner().z; break; case Z_PLUS_ARROW: m_box.maxCorner().z += static_cast<PointCoordinateType>(u.z); if (m_box.minCorner().z > m_box.maxCorner().z) m_box.maxCorner().z = m_box.minCorner().z; break; case CROSS: m_box += CCVector3::fromArray(u.u); break; default: assert(false); return false; } //send 'modified' signal emit boxModified(&m_box); } else if (m_activeComponent == SPHERE) { //handled by move2D! return false; } else if (m_activeComponent >= X_MINUS_TORUS && m_activeComponent <= Z_PLUS_TORUS) { //we guess the rotation order by comparing the current screen 'normal' //and the vector prod of u and the current rotation axis CCVector3d Rb(0,0,0); switch(m_activeComponent) { case X_MINUS_TORUS: Rb.x = -1; break; case X_PLUS_TORUS: Rb.x = 1; break; case Y_MINUS_TORUS: Rb.y = -1; break; case Y_PLUS_TORUS: Rb.y = 1; break; case Z_MINUS_TORUS: Rb.z = -1; break; case Z_PLUS_TORUS: Rb.z = 1; break; default: assert(false); return false; } CCVector3d R = Rb; if (m_glTransEnabled) m_glTrans.applyRotation(R); CCVector3d RxU = R.cross(u); //look for the most parallel dimension int minDim = 0; double maxDot = m_viewMatrix.getColumnAsVec3D(0).dot(RxU); for (int i=1; i<3; ++i) { double dot = m_viewMatrix.getColumnAsVec3D(i).dot(RxU); if (fabs(dot) > fabs(maxDot)) { maxDot = dot; minDim = i; } } //angle is proportional to absolute displacement double angle_rad = u.norm()/m_box.getDiagNorm() * M_PI; if (maxDot < 0.0) angle_rad = -angle_rad; ccGLMatrixd rotMat; rotMat.initFromParameters(angle_rad,Rb,CCVector3d(0,0,0)); CCVector3 C = m_box.getCenter(); ccGLMatrixd transMat; transMat.setTranslation(-C); transMat = rotMat * transMat; transMat.setTranslation(transMat.getTranslationAsVec3D() + CCVector3d::fromArray(C.u)); m_glTrans = m_glTrans * ccGLMatrix(transMat.inverse().data()); enableGLTransformation(true); } else { assert(false); return false; } update(); return true; }
bool ccPolyline::fromFile_MeOnly(QFile& in, short dataVersion, int flags) { if (!ccHObject::fromFile_MeOnly(in, dataVersion, flags)) return false; if (dataVersion<28) return false; //as the associated cloud (=vertices) can't be saved directly (as it may be shared by multiple polylines) //we only store its unique ID (dataVersion>=28) --> we hope we will find it at loading time (i.e. this //is the responsibility of the caller to make sure that all dependencies are saved together) uint32_t vertUniqueID = 0; if (in.read((char*)&vertUniqueID,4) < 0) return ReadError(); //[DIRTY] WARNING: temporarily, we set the vertices unique ID in the 'm_associatedCloud' pointer!!! *(uint32_t*)(&m_theAssociatedCloud) = vertUniqueID; //number of points (references to) (dataVersion>=28) uint32_t pointCount = 0; if (in.read((char*)&pointCount,4) < 0) return ReadError(); if (!reserve(pointCount)) return false; //points (references to) (dataVersion>=28) for (uint32_t i=0; i<pointCount; ++i) { uint32_t pointIndex = 0; if (in.read((char*)&pointIndex,4) < 0) return ReadError(); addPointIndex(pointIndex); } //'global shift & scale' (dataVersion>=39) if (dataVersion >= 39) { if (!loadShiftInfoFromFile(in)) return ReadError(); } else { m_globalScale = 1.0; m_globalShift = CCVector3d(0,0,0); } QDataStream inStream(&in); //Closing state (dataVersion>=28) inStream >> m_isClosed; //RGB Color (dataVersion>=28) inStream >> m_rgbColor.r; inStream >> m_rgbColor.g; inStream >> m_rgbColor.b; //2D mode (dataVersion>=28) inStream >> m_mode2D; //Foreground mode (dataVersion>=28) inStream >> m_foreground; //Width of the line (dataVersion>=31) if (dataVersion >= 31) ccSerializationHelper::CoordsFromDataStream(inStream,flags,&m_width,1); else m_width = 0; return true; }
bool ccGBLSensor::applyViewport(ccGenericGLDisplay* win/*=0*/) { if (!win) { win = getDisplay(); if (!win) { ccLog::Warning("[ccGBLSensor::applyViewport] No associated display!"); return false; } } ccIndexedTransformation trans; if (!getActiveAbsoluteTransformation(trans)) { return false; } //scanner main directions CCVector3d sensorX(trans.data()[0],trans.data()[1],trans.data()[2]); CCVector3d sensorY(trans.data()[4],trans.data()[5],trans.data()[6]); CCVector3d sensorZ(trans.data()[8],trans.data()[9],trans.data()[10]); switch(getRotationOrder()) { case ccGBLSensor::YAW_THEN_PITCH: { double theta = (getMinYaw() + getMaxYaw())/2; ccGLMatrixd rotz; rotz.initFromParameters(theta,sensorZ,CCVector3d(0,0,0)); rotz.applyRotation(sensorX); rotz.applyRotation(sensorY); double phi = 0; //(getMinPitch() + getMaxPitch())/2; ccGLMatrixd roty; roty.initFromParameters(-phi,sensorY,CCVector3d(0,0,0)); //theta = 0 corresponds to the upward vertical direction! roty.applyRotation(sensorX); roty.applyRotation(sensorZ); break; } case ccGBLSensor::PITCH_THEN_YAW: { double phi = (getMinPitch() + getMaxPitch())/2; ccGLMatrixd roty; roty.initFromParameters(-phi,sensorY,CCVector3d(0,0,0)); //theta = 0 corresponds to the upward vertical direction! roty.applyRotation(sensorX); roty.applyRotation(sensorZ); double theta = (getMinYaw() + getMaxYaw())/2; ccGLMatrixd rotz; rotz.initFromParameters(theta,sensorZ,CCVector3d(0,0,0)); rotz.applyRotation(sensorX); rotz.applyRotation(sensorY); break; } default: assert(false); break; } //center camera on sensor CCVector3d sensorCenterd = CCVector3d::fromArray(trans.getTranslation()); ccGLMatrixd viewMat = ccGLMatrixd::FromViewDirAndUpDir(sensorX,sensorZ); viewMat.invert(); viewMat.setTranslation(sensorCenterd); //TODO: can we set the right FOV? win->setupProjectiveViewport(viewMat,0,1.0f,true,true); return true; }
void qFacets::exportFacets() { assert(m_app); if (!m_app) return; //disclaimer accepted? if (!ShowDisclaimer(m_app)) return; //Retrive selected facets FacetSet facets; getFacetsInCurrentSelection(facets); if (facets.empty()) { m_app->dispToConsole("Couldn't find any facet in the current selection!",ccMainAppInterface::ERR_CONSOLE_MESSAGE); return; } assert(!facets.empty()); FacetsExportDlg fDlg(FacetsExportDlg::SHAPE_FILE_IO,m_app->getMainWindow()); //persistent settings (default export path) QSettings settings; settings.beginGroup("qFacets"); QString facetsSavePath = settings.value("exportPath",QApplication::applicationDirPath()).toString(); fDlg.destinationPathLineEdit->setText(facetsSavePath + QString("/facets.shp")); if (!fDlg.exec()) return; QString filename = fDlg.destinationPathLineEdit->text(); //save current export path to persistent settings settings.setValue("exportPath",QFileInfo(filename).absolutePath()); if (QFile(filename).exists()) { //if the file already exists, ask for confirmation! if (QMessageBox::warning(m_app->getMainWindow(),"File already exists!","File already exists! Are you sure you want to overwrite it?",QMessageBox::Yes,QMessageBox::No) == QMessageBox::No) return; } //fields (shapefile) - WARNING names must not have more than 10 chars! ShpFilter::IntegerField facetIndex("index"); ShpFilter::DoubleField facetSurface("surface"); ShpFilter::DoubleField facetRMS("rms"); ShpFilter::IntegerField facetDipDir("dip_dir"); ShpFilter::IntegerField facetDip("dip"); ShpFilter::IntegerField familyIndex("family_ind"); ShpFilter::IntegerField subfamilyIndex("subfam_ind"); ShpFilter::DoubleField3D facetNormal("normal"); ShpFilter::DoubleField3D facetBarycenter("center"); ShpFilter::DoubleField horizExtension("horiz_ext"); ShpFilter::DoubleField vertExtension("vert_ext"); ShpFilter::DoubleField surfaceExtension("surf_ext"); size_t facetCount = facets.size(); assert(facetCount != 0); try { facetIndex.values.reserve(facetCount); facetSurface.values.reserve(facetCount); facetRMS.values.reserve(facetCount); facetDipDir.values.reserve(facetCount); facetDip.values.reserve(facetCount); familyIndex.values.reserve(facetCount); subfamilyIndex.values.reserve(facetCount); facetNormal.values.reserve(facetCount); facetBarycenter.values.reserve(facetCount); horizExtension.values.reserve(facetCount); vertExtension.values.reserve(facetCount); surfaceExtension.values.reserve(facetCount); } catch (const std::bad_alloc&) { m_app->dispToConsole("Not enough memory!",ccMainAppInterface::ERR_CONSOLE_MESSAGE); return; } ccHObject toSave("facets"); //depending on the 'main orientation', the job is more or less easy ;) bool useNativeOrientation = fDlg.nativeOriRadioButton->isChecked(); bool useGlobalOrientation = fDlg.verticalOriRadioButton->isChecked(); bool useCustomOrientation = fDlg.customOriRadioButton->isChecked(); //Default base CCVector3 X(1,0,0), Y(0,1,0), Z(0,0,1); //'vertical' orientation (potentially specified by the user) if (!useNativeOrientation) { if (useCustomOrientation) { Z = CCVector3( static_cast<PointCoordinateType>(fDlg.nXLineEdit->text().toDouble()), static_cast<PointCoordinateType>(fDlg.nYLineEdit->text().toDouble()), static_cast<PointCoordinateType>(fDlg.nZLineEdit->text().toDouble()) ); Z.normalize(); } else if (useGlobalOrientation) { //we compute the mean orientation (weighted by each facet's surface) CCVector3d Nsum(0,0,0); for (FacetSet::iterator it = facets.begin(); it != facets.end(); ++it) { double surf = (*it)->getSurface(); CCVector3 N = (*it)->getNormal(); Nsum.x += static_cast<double>(N.x) * surf; Nsum.y += static_cast<double>(N.y) * surf; Nsum.z += static_cast<double>(N.z) * surf; } Nsum.normalize(); Z = CCVector3( static_cast<PointCoordinateType>(Nsum.x), static_cast<PointCoordinateType>(Nsum.y), static_cast<PointCoordinateType>(Nsum.z) ); } //update X & Y CCVector3 D = Z.cross(CCVector3(0,0,1)); if (D.norm2() > ZERO_TOLERANCE) //otherwise the vertical dir hasn't changed! { X = -D; X.normalize(); Y = Z.cross(X); } } //we compute the mean center (weighted by each facet's surface) CCVector3 C(0,0,0); { double weightSum = 0; for (FacetSet::iterator it = facets.begin(); it != facets.end(); ++it) { double surf = (*it)->getSurface(); CCVector3 Ci = (*it)->getCenter(); C += Ci * static_cast<PointCoordinateType>(surf); weightSum += surf; } if (weightSum) C /= static_cast<PointCoordinateType>(weightSum); } //determine the 'global' orientation matrix ccGLMatrix oriRotMat; oriRotMat.toIdentity(); if (!useNativeOrientation) { oriRotMat.getColumn(0)[0] = static_cast<float>(X.x); oriRotMat.getColumn(0)[1] = static_cast<float>(X.y); oriRotMat.getColumn(0)[2] = static_cast<float>(X.z); oriRotMat.getColumn(1)[0] = static_cast<float>(Y.x); oriRotMat.getColumn(1)[1] = static_cast<float>(Y.y); oriRotMat.getColumn(1)[2] = static_cast<float>(Y.z); oriRotMat.getColumn(2)[0] = static_cast<float>(Z.x); oriRotMat.getColumn(2)[1] = static_cast<float>(Z.y); oriRotMat.getColumn(2)[2] = static_cast<float>(Z.z); oriRotMat.invert(); ccGLMatrix transMat; transMat.setTranslation(-C); oriRotMat = oriRotMat * transMat; oriRotMat.setTranslation(oriRotMat.getTranslationAsVec3D() + C); } //for each facet for (FacetSet::iterator it=facets.begin(); it!=facets.end(); ++it) { ccFacet* facet = *it; ccPolyline* poly = facet->getContour(); //if necessary, we create a (temporary) new facet if (!useNativeOrientation) { CCLib::GenericIndexedCloudPersist* vertices = poly->getAssociatedCloud(); if (!vertices || vertices->size() < 3) continue; //create (temporary) new polyline ccPolyline* newPoly = new ccPolyline(*poly); ccPointCloud* pc = (newPoly ? dynamic_cast<ccPointCloud*>(newPoly->getAssociatedCloud()) : 0); if (pc) { pc->applyGLTransformation_recursive(&oriRotMat); } else { m_app->dispToConsole(QString("Failed to change the orientation of polyline '%1'! (not enough memory)").arg(poly->getName()),ccMainAppInterface::WRN_CONSOLE_MESSAGE); continue; } newPoly->set2DMode(true); poly = newPoly; } toSave.addChild(poly, useNativeOrientation ? ccHObject::DP_NONE : ccHObject::DP_PARENT_OF_OTHER); //save associated meta-data as 'shapefile' fields { //main parameters FacetMetaData data; GetFacetMetaData(facet, data); //horizontal and vertical extensions double horizExt = 0, vertExt = 0; ComputeFacetExtensions(data.normal,poly,horizExt,vertExt); facetIndex.values.push_back(data.facetIndex); facetSurface.values.push_back(data.surface); facetRMS.values.push_back(data.rms); facetDipDir.values.push_back(data.dipDir_deg); facetDip.values.push_back(data.dip_deg); familyIndex.values.push_back(data.familyIndex); subfamilyIndex.values.push_back(data.subfamilyIndex); facetNormal.values.push_back(CCVector3d(data.normal.x,data.normal.y,data.normal.z)); facetBarycenter.values.push_back(CCVector3d(data.center.x,data.center.y,data.center.z)); vertExtension.values.push_back(vertExt); horizExtension.values.push_back(horizExt); surfaceExtension.values.push_back(horizExt*vertExt); } } //save entities if (toSave.getChildrenNumber()) { std::vector<ShpFilter::GenericField*> fields; fields.push_back(&facetIndex); fields.push_back(&facetBarycenter); fields.push_back(&facetNormal); fields.push_back(&facetRMS); fields.push_back(&horizExtension); fields.push_back(&vertExtension); fields.push_back(&surfaceExtension); fields.push_back(&facetSurface); fields.push_back(&facetDipDir); fields.push_back(&facetDip); fields.push_back(&familyIndex); fields.push_back(&subfamilyIndex); ShpFilter filter; filter.treatClosedPolylinesAsPolygons(true); ShpFilter::SaveParameters params; params.alwaysDisplaySaveDialog = false; if (filter.saveToFile(&toSave,fields,filename,params) == CC_FERR_NO_ERROR) { m_app->dispToConsole(QString("[qFacets] File '%1' successfully saved").arg(filename),ccMainAppInterface::STD_CONSOLE_MESSAGE); } else { m_app->dispToConsole(QString("[qFacets] Failed to save file '%1'!").arg(filename),ccMainAppInterface::WRN_CONSOLE_MESSAGE); } } }
bool ccGlobalShiftManager::Handle( const CCVector3d& P, double diagonal, Mode mode, bool useInputCoordinatesShiftIfPossible, CCVector3d& coordinatesShift, double* coordinatesScale, bool* applyAll/*=0*/) { assert(diagonal >= 0); if (applyAll) { *applyAll = false; } //default scale double scale = (coordinatesScale ? std::max(*coordinatesScale, ZERO_TOLERANCE) : 1.0); bool needShift = NeedShift(P); bool needRescale = NeedRescale(diagonal); //if we can't display a dialog and no usable shift is specified, there's nothing we can do... if (mode == NO_DIALOG && !useInputCoordinatesShiftIfPossible) { coordinatesShift = CCVector3d(0,0,0); if (coordinatesScale) { *coordinatesScale = 1.0; } if (needShift || needRescale) { ccLog::Warning("[ccGlobalShiftManager] Entity has very big coordinates: original accuracy may be lost! (you should apply a Global Shift or Scale)"); } return false; } //is shift necessary? if ( needShift || needRescale || mode == ALWAYS_DISPLAY_DIALOG ) { //shift information already provided? (typically from a previous entity) if (useInputCoordinatesShiftIfPossible && mode != ALWAYS_DISPLAY_DIALOG) { //either we are in non interactive mode (which means that shift is 'forced' by caller) if (mode == NO_DIALOG //or we are in interactive mode and existing shift is pertinent || (!NeedShift(P*scale + coordinatesShift) && !NeedRescale(diagonal*scale)) ) { //user should use the provided shift information return true; } //--> otherwise we (should) ask for a better one } //let's deduce the right values (AUTO mode) if (mode == NO_DIALOG_AUTO_SHIFT) { //guess best shift & scale info from input point/diagonal if (needShift) { coordinatesShift = BestShift(P); } if (coordinatesScale && needRescale) { *coordinatesScale = BestScale(diagonal); } return true; } //otherwise let's ask the user for those values ccShiftAndScaleCloudDlg sasDlg(P, diagonal); if (!applyAll) { sasDlg.showApplyAllButton(false); } if (!coordinatesScale) { sasDlg.showScaleItems(false); } scale = 1.0; CCVector3d shift(0,0,0); if (useInputCoordinatesShiftIfPossible) { //shift on load already provided? (typically from a previous file) shift = coordinatesShift; if (coordinatesScale) { scale = *coordinatesScale; } if (mode != ALWAYS_DISPLAY_DIALOG) { sasDlg.showWarning(true); //if we are here, it means that the provided shift isn't concordant } } else { //guess best shift & scale info from input point/diagonal if (needShift) { shift = BestShift(P); } if (needRescale) { scale = BestScale(diagonal); } } //add "suggested" entry int index = sasDlg.addShiftInfo(ccShiftAndScaleCloudDlg::ShiftInfo("Suggested", shift, scale)); sasDlg.setCurrentProfile(index); //add "last" entry (if available) { ccShiftAndScaleCloudDlg::ShiftInfo lastInfo; if (sasDlg.getLast(lastInfo)) { sasDlg.addShiftInfo(lastInfo); } } //add entries from file (if any) sasDlg.addFileInfo(); //automatically make the first available shift that works //(different than the suggested one) active { for (size_t i=static_cast<size_t>(std::max(0,index+1)); i<sasDlg.infoCount(); ++i) { ccShiftAndScaleCloudDlg::ShiftInfo info; if (sasDlg.getInfo(i,info)) { //check if they work if ( !NeedShift((CCVector3d(P) + info.shift) * info.scale ) && !NeedRescale(diagonal*info.scale) ) { sasDlg.setCurrentProfile(static_cast<int>(i)); break; } } } } sasDlg.showTitle(needShift || needRescale); if (sasDlg.exec()) { coordinatesShift = sasDlg.getShift(); if (coordinatesScale) { *coordinatesScale = sasDlg.getScale(); } if (applyAll) { *applyAll = sasDlg.applyAll(); } return true; } } coordinatesShift = CCVector3d(0,0,0); if (coordinatesScale) { *coordinatesScale = 1.0; } return false; }
CCVector3d ccShiftAndScaleCloudDlg::getShift() const { return CCVector3d( m_ui->shiftX->value(), m_ui->shiftY->value(), m_ui->shiftZ->value() ); }