Download src/Mod/Measure/Gui/ViewProviderMeasureBase.cpp from AbdulElahGwaith/FreeCAD: direct link, hf CLI and curl.
- Browser
- Download file 24.5 kB
-
https://huggingface.co/AbdulElahGwaith/FreeCAD/resolve/main/src/Mod/Measure/Gui/ViewProviderMeasureBase.cpp
- Command line
-
hf download hf://AbdulElahGwaith/FreeCAD/src/Mod/Measure/Gui/ViewProviderMeasureBase.cpp
-
curl -L -o ViewProviderMeasureBase.cpp https://huggingface.co/AbdulElahGwaith/FreeCAD/resolve/main/src/Mod/Measure/Gui/ViewProviderMeasureBase.cpp
24.5 kB
| // SPDX-License-Identifier: LGPL-2.1-or-later | |
| /*************************************************************************** | |
| * Copyright (c) 2023 David Friedli <david[at]friedli-be.ch> * | |
| * * | |
| * This file is part of FreeCAD. * | |
| * * | |
| * FreeCAD is free software: you can redistribute it and/or modify it * | |
| * under the terms of the GNU Lesser General Public License as * | |
| * published by the Free Software Foundation, either version 2.1 of the * | |
| * License, or (at your option) any later version. * | |
| * * | |
| * FreeCAD is distributed in the hope that it will be useful, but * | |
| * WITHOUT ANY WARRANTY; without even the implied warranty of * | |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * | |
| * Lesser General Public License for more details. * | |
| * * | |
| * You should have received a copy of the GNU Lesser General Public * | |
| * License along with FreeCAD. If not, see * | |
| * <https://www.gnu.org/licenses/>. * | |
| * * | |
| **************************************************************************/ | |
| using namespace MeasureGui; | |
| using namespace Measure; | |
| PROPERTY_SOURCE(MeasureGui::ViewProviderMeasureGroup, Gui::ViewProviderDocumentObjectGroup) | |
| ViewProviderMeasureGroup::ViewProviderMeasureGroup() | |
| {} | |
| ViewProviderMeasureGroup::~ViewProviderMeasureGroup() = default; | |
| QIcon ViewProviderMeasureGroup::getIcon() const | |
| { | |
| return Gui::BitmapFactory().pixmap("Measurement-Group.svg"); | |
| } | |
| // NOLINTBEGIN | |
| PROPERTY_SOURCE(MeasureGui::ViewProviderMeasureBase, Gui::ViewProviderDocumentObject) | |
| // NOLINTEND | |
| ViewProviderMeasureBase::ViewProviderMeasureBase() | |
| { | |
| static const char* agroup = "Appearance"; | |
| // NOLINTBEGIN | |
| ADD_PROPERTY_TYPE( | |
| TextColor, | |
| (Preferences::defaultTextColor()), | |
| agroup, | |
| App::Prop_None, | |
| "Color for the measurement text" | |
| ); | |
| ADD_PROPERTY_TYPE( | |
| TextBackgroundColor, | |
| (Preferences::defaultTextBackgroundColor()), | |
| agroup, | |
| App::Prop_None, | |
| "Color for the measurement text background" | |
| ); | |
| ADD_PROPERTY_TYPE( | |
| LineColor, | |
| (Preferences::defaultLineColor()), | |
| agroup, | |
| App::Prop_None, | |
| "Color for the measurement lines" | |
| ); | |
| ADD_PROPERTY_TYPE( | |
| FontSize, | |
| (Preferences::defaultFontSize()), | |
| agroup, | |
| App::Prop_None, | |
| "Size of measurement text" | |
| ); | |
| // NOLINTEND | |
| pGlobalSeparator = new SoSeparator(); | |
| pGlobalSeparator->ref(); | |
| // Connect visibility of delta measurements to the ModeSwitch | |
| auto visibilitySwitch = new SoSwitch(); | |
| getRoot()->insertChild(visibilitySwitch, 0); | |
| visibilitySwitch->addChild(pGlobalSeparator); | |
| visibilitySwitch->whichChild.connectFrom(&pcModeSwitch->whichChild); | |
| // setupAnnoSceneGraph() - sets up the annotation scene graph | |
| pLabel = new Gui::SoFrameLabel(); | |
| pLabel->ref(); | |
| pColor = new SoBaseColor(); | |
| pColor->ref(); | |
| pLabelTranslation = new SoTransform(); | |
| pLabelTranslation->ref(); | |
| auto ps = getSoPickStyle(); | |
| // Dragger | |
| SoSeparator* dragSeparator = new SoSeparator(); | |
| pDragger = new SoTranslate2Dragger(); | |
| pDragger->ref(); | |
| pDraggerOrientation = new SoTransform(); | |
| pDraggerOrientation->ref(); | |
| dragSeparator->addChild(pDraggerOrientation); | |
| dragSeparator->addChild(pDragger); | |
| // Transform drag location by dragger local orientation and connect to labelTranslation | |
| auto matrixEngine = new SoComposeMatrix(); | |
| matrixEngine->rotation.connectFrom(&pDraggerOrientation->rotation); | |
| auto transformEngine = new SoTransformVec3f(); | |
| transformEngine->vector.connectFrom(&pDragger->translation); | |
| transformEngine->matrix.connectFrom(&matrixEngine->matrix); | |
| pLabelTranslation->translation.connectFrom(&transformEngine->point); | |
| pTextSeparator = new SoSeparator(); | |
| pTextSeparator->ref(); | |
| pTextSeparator->addChild(dragSeparator); | |
| pTextSeparator->addChild(pLabelTranslation); | |
| pTextSeparator->addChild(pLabel); | |
| // Empty line separator which can be populated by inherited class | |
| pLineSeparator = new SoSeparator(); | |
| pLineSeparator->ref(); | |
| pLineSeparator->addChild(ps); | |
| pLineSeparator->addChild(getSoLineStylePrimary()); | |
| pLineSeparator->addChild(pColor); | |
| // Secondary line separator | |
| pLineSeparatorSecondary = new SoSeparator(); | |
| pLineSeparatorSecondary->ref(); | |
| pLineSeparatorSecondary->addChild(ps); | |
| pLineSeparatorSecondary->addChild(getSoLineStyleSecondary()); | |
| pLineSeparatorSecondary->addChild(pColor); | |
| pRootSeparator = new SoAnnotation(); | |
| pRootSeparator->ref(); | |
| pRootSeparator->addChild(pLineSeparator); | |
| pRootSeparator->addChild(pLineSeparatorSecondary); | |
| pRootSeparator->addChild(pTextSeparator); | |
| addDisplayMaskMode(pRootSeparator, "Base"); | |
| pRootSeparator->touch(); | |
| pTextSeparator->touch(); | |
| pLineSeparator->touch(); | |
| // Register dragger callback | |
| auto dragger = pDragger; | |
| dragger->addValueChangedCallback(draggerChangedCallback, this); | |
| // Use the label node as the transform handle | |
| SoSearchAction sa; | |
| sa.setInterest(SoSearchAction::FIRST); | |
| sa.setSearchingAll(true); | |
| sa.setNode(pLabel); | |
| sa.apply(pcRoot); | |
| SoPath* labelPath = sa.getPath(); | |
| assert(labelPath); | |
| dragger->setPartAsPath("translator", labelPath); | |
| // Hide the dragger feedback during translation | |
| dragger->setPart("translatorActive", NULL); | |
| dragger->setPart("xAxisFeedback", NULL); | |
| dragger->setPart("yAxisFeedback", NULL); | |
| // end setupSceneGraph | |
| // these touches cause onChanged to run which then updates pLabel and pColor with the initial | |
| // values | |
| TextColor.touch(); | |
| TextBackgroundColor.touch(); | |
| FontSize.touch(); | |
| LineColor.touch(); | |
| fieldFontSize.setValue(FontSize.getValue()); | |
| } | |
| ViewProviderMeasureBase::~ViewProviderMeasureBase() | |
| { | |
| _mVisibilityChangedConnection.disconnect(); | |
| pGlobalSeparator->unref(); | |
| pLabel->unref(); | |
| pColor->unref(); | |
| pDragger->unref(); | |
| pDraggerOrientation->unref(); | |
| pLabelTranslation->unref(); | |
| pTextSeparator->unref(); | |
| pLineSeparator->unref(); | |
| pRootSeparator->unref(); | |
| } | |
| std::vector<std::string> ViewProviderMeasureBase::getDisplayModes() const | |
| { | |
| // add modes | |
| std::vector<std::string> StrList; | |
| StrList.emplace_back("Base"); | |
| return StrList; | |
| } | |
| void ViewProviderMeasureBase::setDisplayMode(const char* ModeName) | |
| { | |
| if (strcmp(ModeName, "Base") == 0) { | |
| setDisplayMaskMode("Base"); | |
| } | |
| ViewProviderDocumentObject::setDisplayMode(ModeName); | |
| } | |
| void ViewProviderMeasureBase::finishRestoring() | |
| { | |
| if (Visibility.getValue() && isSubjectVisible()) { | |
| show(); | |
| } | |
| ViewProviderDocumentObject::finishRestoring(); | |
| } | |
| void ViewProviderMeasureBase::onChanged(const App::Property* prop) | |
| { | |
| if (prop == &TextColor) { | |
| const Base::Color& color = TextColor.getValue(); | |
| pLabel->textColor.setValue(color.r, color.g, color.b); | |
| updateIcon(); | |
| } | |
| else if (prop == &TextBackgroundColor) { | |
| const Base::Color& color = TextBackgroundColor.getValue(); | |
| pLabel->backgroundColor.setValue(color.r, color.g, color.b); | |
| } | |
| else if (prop == &LineColor) { | |
| const Base::Color& color = LineColor.getValue(); | |
| pColor->rgb.setValue(color.r, color.g, color.b); | |
| } | |
| else if (prop == &FontSize) { | |
| pLabel->size = FontSize.getValue(); | |
| fieldFontSize.setValue(FontSize.getValue()); | |
| } | |
| ViewProviderDocumentObject::onChanged(prop); | |
| } | |
| void ViewProviderMeasureBase::draggerChangedCallback(void* data, SoDragger*) | |
| { | |
| auto me = static_cast<ViewProviderMeasureBase*>(data); | |
| me->onLabelMoved(); | |
| } | |
| void ViewProviderMeasureBase::setLabelValue(const Base::Quantity& value) | |
| { | |
| pLabel->string.setValue(value.getUserString().c_str()); | |
| } | |
| void ViewProviderMeasureBase::setLabelValue(const QString& value) | |
| { | |
| auto lines = value.split(QStringLiteral("\n")); | |
| int i = 0; | |
| for (auto& it : lines) { | |
| pLabel->string.set1Value(i, it.toUtf8().constData()); | |
| i++; | |
| } | |
| } | |
| void ViewProviderMeasureBase::setLabelTranslation(const SbVec3f& position) | |
| { | |
| // Set the dragger translation to keep it in sync with pLabelTranslation | |
| pDragger->translation.setValue(position); | |
| } | |
| SoPickStyle* ViewProviderMeasureBase::getSoPickStyle() | |
| { | |
| auto ps = new SoPickStyle(); | |
| ps->style = SoPickStyle::UNPICKABLE; | |
| return ps; | |
| } | |
| SoDrawStyle* ViewProviderMeasureBase::getSoLineStylePrimary() | |
| { | |
| auto style = new SoDrawStyle(); | |
| style->lineWidth = 2.0f; | |
| return style; | |
| } | |
| SoDrawStyle* ViewProviderMeasureBase::getSoLineStyleSecondary() | |
| { | |
| auto style = new SoDrawStyle(); | |
| style->lineWidth = 1.0f; | |
| return style; | |
| } | |
| SoSeparator* ViewProviderMeasureBase::getSoSeparatorText() | |
| { | |
| return pTextSeparator; | |
| } | |
| void ViewProviderMeasureBase::positionAnno(const Measure::MeasureBase* measureObject) | |
| { | |
| (void)measureObject; | |
| } | |
| void ViewProviderMeasureBase::updateIcon() | |
| { | |
| // This assumes the icons main color is black | |
| Gui::ColorMap colorMap { | |
| {0x000000, TextColor.getValue().getPackedRGB() >> 8}, | |
| }; | |
| pLabel->setIcon(Gui::BitmapFactory().pixmapFromSvg(sPixmap, QSize(20, 20), colorMap)); | |
| } | |
| void ViewProviderMeasureBase::attach(App::DocumentObject* pcObj) | |
| { | |
| ViewProviderDocumentObject::attach(pcObj); | |
| updateIcon(); | |
| } | |
| //! handle changes to the feature's properties | |
| void ViewProviderMeasureBase::updateData(const App::Property* prop) | |
| { | |
| bool doUpdate = false; | |
| auto obj = getMeasureObject(); | |
| if (!obj) { | |
| return; | |
| } | |
| if (strcmp(prop->getName(), "Label") == 0) { | |
| doUpdate = true; | |
| } | |
| // Check if one of the input properties has been changed | |
| auto inputProps = obj->getInputProps(); | |
| if (std::ranges::find(inputProps, std::string(prop->getName())) != inputProps.end()) { | |
| doUpdate = true; | |
| // Add connections to be notified when the measured objects are changed | |
| connectToSubject(obj->getSubject()); | |
| } | |
| // Check if the result prop has been changed | |
| auto resultProp = obj->getResultProp(); | |
| if (resultProp && prop == resultProp) { | |
| doUpdate = true; | |
| } | |
| if (doUpdate) { | |
| redrawAnnotation(); | |
| // Update label | |
| std::string userLabel(obj->Label.getValue()); | |
| std::string name = userLabel.substr(0, userLabel.find(":")); | |
| obj->Label.setValue((name + ": ") + obj->getResultString().toStdString()); | |
| } | |
| ViewProviderDocumentObject::updateData(prop); | |
| } | |
| // TODO: should this be pure virtual? | |
| void ViewProviderMeasureBase::redrawAnnotation() | |
| { | |
| // Base::Console().message("VPMB::redrawAnnotation()\n"); | |
| } | |
| //! connect to the subject to receive visibility updates | |
| void ViewProviderMeasureBase::connectToSubject(App::DocumentObject* subject) | |
| { | |
| if (!subject) { | |
| return; | |
| } | |
| // disconnect any existing connection | |
| if (_mVisibilityChangedConnection.connected()) { | |
| _mVisibilityChangedConnection.disconnect(); | |
| } | |
| // NOLINTBEGIN | |
| auto bndVisibility = std::bind( | |
| &ViewProviderMeasureBase::onSubjectVisibilityChanged, | |
| this, | |
| std::placeholders::_1, | |
| std::placeholders::_2 | |
| ); | |
| // NOLINTEND | |
| _mVisibilityChangedConnection = subject->signalChanged.connect(bndVisibility); | |
| } | |
| //! connect to the subject to receive visibility updates | |
| void ViewProviderMeasureBase::connectToSubject(std::vector<App::DocumentObject*> subject) | |
| { | |
| if (subject.empty()) { | |
| return; | |
| } | |
| // TODO: should we connect to all the subject objects when there is >1? | |
| auto proxy = subject.front(); | |
| connectToSubject(proxy); | |
| } | |
| //! retrieve the feature | |
| Measure::MeasureBase* ViewProviderMeasureBase::getMeasureObject() | |
| { | |
| // Note: Cast to MeasurePropertyBase once we use it to provide the needed values e.g. | |
| // basePosition textPosition etc. | |
| auto feature = dynamic_cast<Measure::MeasureBase*>(pcObject); | |
| if (!feature) { | |
| throw Base::RuntimeError("Feature not found for ViewProviderMeasureBase"); | |
| } | |
| return feature; | |
| } | |
| //! calculate a good direction from the elements being measured to the annotation text based on the | |
| //! layout of the elements and relationship with the cardinal axes and the view direction. | |
| //! elementDirection is expected to be a normalized vector. an example of an elementDirection would | |
| //! be the vector from the start of a line to the end. | |
| Base::Vector3d ViewProviderMeasureBase::getTextDirection(Base::Vector3d elementDirection, double tolerance) | |
| { | |
| // TODO: this can fail if the active view is not a 3d view (spreadsheet, techdraw page) and | |
| // something causes a measure to try to update we need to search through the mdi views for a 3d | |
| // view and take the direction from it (or decide that if the active view is not 3d, assume we | |
| // are looking from the front). | |
| Base::Vector3d viewDirection; | |
| Base::Vector3d upDirection; | |
| Gui::View3DInventor* view = nullptr; | |
| try { | |
| view = dynamic_cast<Gui::View3DInventor*>(this->getActiveView()); | |
| } | |
| catch (const Base::RuntimeError&) { | |
| Base::Console().log("ViewProviderMeasureBase::getTextDirection: Could not get active view\n"); | |
| } | |
| if (view) { | |
| Gui::View3DInventorViewer* viewer = view->getViewer(); | |
| viewDirection = toVector3d(viewer->getViewDirection()).Normalize(); | |
| upDirection = toVector3d(viewer->getUpDirection()).Normalize(); | |
| // Measure doesn't work with this kind of active view. Might be dependency graph, might be | |
| // TechDraw, or ???? | |
| // throw Base::RuntimeError("Measure doesn't work with this kind of active view."); | |
| } | |
| else { | |
| viewDirection = Base::Vector3d(0.0, 1.0, 0.0); | |
| upDirection = Base::Vector3d(0.0, 0.0, 1.0); | |
| } | |
| Base::Vector3d textDirection = elementDirection.Cross(viewDirection); | |
| if (textDirection.Length() < tolerance) { | |
| // either elementDirection and viewDirection are parallel or one of them is null. | |
| textDirection = elementDirection.Cross(upDirection); | |
| } | |
| return textDirection.Normalize(); | |
| } | |
| //! true if the subject of this measurement is visible. For Measures that have multiple object | |
| //! subject, all of the subjects must be visible. | |
| bool ViewProviderMeasureBase::isSubjectVisible() | |
| { | |
| Gui::Document* guiDoc = nullptr; | |
| try { | |
| guiDoc = this->getDocument(); | |
| } | |
| catch (const Base::RuntimeError&) { | |
| Base::Console().log("ViewProviderMeasureBase::isSubjectVisible: Could not get document\n"); | |
| return false; | |
| } | |
| // we need these things to proceed | |
| if (!getMeasureObject() || !guiDoc) { | |
| return false; | |
| } | |
| // Show the measurement if it doesn't track any subjects | |
| if (getMeasureObject()->getSubject().empty()) { | |
| return true; | |
| } | |
| for (auto& obj : getMeasureObject()->getSubject()) { | |
| Gui::ViewProvider* vp = guiDoc->getViewProvider(obj); | |
| if (!vp || !vp->isVisible()) { | |
| return false; | |
| } | |
| } | |
| // all of the subject objects are visible | |
| return true; | |
| } | |
| //! gets called when the subject object issues a signalChanged (ie a property change). We are only | |
| //! interested in the subject's Visibility property | |
| void ViewProviderMeasureBase::onSubjectVisibilityChanged( | |
| const App::DocumentObject& docObj, | |
| const App::Property& prop | |
| ) | |
| { | |
| if (docObj.isRemoving()) { | |
| return; | |
| } | |
| std::string propName = prop.getName(); | |
| if (propName == "Visibility") { | |
| if (!docObj.Visibility.getValue()) { | |
| // show ourselves only if subject is visible | |
| setVisible(false); | |
| } | |
| else { | |
| // here, we don't know if we should be visible or not, so we have to check the whole | |
| // subject | |
| setVisible(isSubjectVisible() && Visibility.getValue()); | |
| } | |
| } | |
| } | |
| float ViewProviderMeasureBase::getViewScale() | |
| { | |
| float scale = 1.0; | |
| Gui::View3DInventor* view = dynamic_cast<Gui::View3DInventor*>(this->getActiveView()); | |
| if (!view) { | |
| Base::Console().log("ViewProviderMeasureBase::getViewScale: Could not get active view\n"); | |
| return scale; | |
| } | |
| Gui::View3DInventorViewer* viewer = view->getViewer(); | |
| SoCamera* const camera = viewer->getSoRenderManager()->getCamera(); | |
| if (!camera) { | |
| return false; | |
| } | |
| SbViewVolume volume(camera->getViewVolume()); | |
| SbVec3f center(volume.getSightPoint(camera->focalDistance.getValue())); | |
| scale = volume.getWorldToScreenScale(center, 1.0); | |
| return scale; | |
| } | |
| // NOLINTBEGIN | |
| PROPERTY_SOURCE(MeasureGui::ViewProviderMeasure, MeasureGui::ViewProviderMeasureBase) | |
| // NOLINTEND | |
| //! the general purpose view provider. handles area, length, etc - any measure without a | |
| //! specialized VP | |
| ViewProviderMeasure::ViewProviderMeasure() | |
| { | |
| sPixmap = "umf-measurement"; | |
| // setupSceneGraph for leader? | |
| const size_t lineCount(3); | |
| // indexes used to create the edges | |
| // this makes a line from verts[0] to verts[1] | |
| static const int32_t lines[lineCount] = {0, 1, -1}; | |
| pCoords = new SoCoordinate3(); | |
| pCoords->ref(); | |
| // Combine coordinates from baseTranslation and labelTranslation | |
| auto engineCat = new SoConcatenate(SoMFVec3f::getClassTypeId()); | |
| auto origin = new SoSFVec3f(); | |
| origin->setValue(0, 0, 0); | |
| engineCat->input[0]->connectFrom(origin); | |
| engineCat->input[1]->connectFrom(&pLabelTranslation->translation); | |
| pCoords->point.setNum(engineCat->output->getNumConnections()); | |
| pCoords->point.connectFrom(engineCat->output); | |
| pLines = new SoIndexedLineSet(); | |
| pLines->ref(); | |
| pLines->coordIndex.setNum(lineCount); | |
| pLines->coordIndex.setValues(0, lineCount, lines); | |
| auto lineSep = pLineSeparator; | |
| lineSep->addChild(pCoords); | |
| lineSep->addChild(pLines); | |
| auto points = new SoMarkerSet(); | |
| points->markerIndex = Gui::Inventor::MarkerBitmaps::getMarkerIndex( | |
| "CROSS", | |
| Gui::ViewParams::instance()->getMarkerSize() | |
| ); | |
| points->numPoints = 1; | |
| lineSep->addChild(points); | |
| // Connect dragger local orientation to view orientation | |
| Gui::View3DInventor* view = nullptr; | |
| try { | |
| view = dynamic_cast<Gui::View3DInventor*>(this->getActiveView()); | |
| } | |
| catch (const Base::RuntimeError&) { | |
| Base::Console().log("ViewProviderMeasure::ViewProviderMeasure: Could not get active view\n"); | |
| } | |
| if (view) { | |
| Gui::View3DInventorViewer* viewer = view->getViewer(); | |
| auto renderManager = viewer->getSoRenderManager(); | |
| auto cam = renderManager->getCamera(); | |
| pDraggerOrientation->rotation.connectFrom(&cam->orientation); | |
| } | |
| } | |
| ViewProviderMeasure::~ViewProviderMeasure() | |
| { | |
| pCoords->unref(); | |
| pLines->unref(); | |
| } | |
| void ViewProviderMeasure::positionAnno(const Measure::MeasureBase* measureObject) | |
| { | |
| (void)measureObject; | |
| // Initialize the text position | |
| Base::Vector3d textPos = getTextPosition(); | |
| auto srcVec = SbVec3f(textPos.x, textPos.y, textPos.z); | |
| // Translate the position by the local dragger matrix (pDraggerOrientation) | |
| Gui::View3DInventor* view = nullptr; | |
| try { | |
| view = dynamic_cast<Gui::View3DInventor*>(this->getActiveView()); | |
| } | |
| catch (const Base::RuntimeError&) { | |
| Base::Console().log("ViewProviderMeasure::positionAnno: Could not get active view\n"); | |
| } | |
| if (!view) { | |
| return; | |
| } | |
| Gui::View3DInventorViewer* viewer = view->getViewer(); | |
| auto gma = SoGetMatrixAction(viewer->getSoRenderManager()->getViewportRegion()); | |
| gma.apply(pDraggerOrientation); | |
| auto mat = gma.getMatrix(); | |
| SbVec3f destVec(0, 0, 0); | |
| mat.multVecMatrix(srcVec, destVec); | |
| setLabelTranslation(destVec); | |
| updateView(); | |
| } | |
| void ViewProviderMeasure::onChanged(const App::Property* prop) | |
| { | |
| if (pcObject == nullptr) { | |
| return; | |
| } | |
| ViewProviderMeasureBase::onChanged(prop); | |
| } | |
| //! repaint the annotation | |
| void ViewProviderMeasure::redrawAnnotation() | |
| { | |
| // point on element | |
| Base::Vector3d basePos = getBasePosition(); | |
| pcTransform->translation.setValue(SbVec3f(basePos.x, basePos.y, basePos.z)); | |
| setLabelValue(getMeasureObject()->getResultString()); | |
| ViewProviderMeasureBase::redrawAnnotation(); | |
| ViewProviderDocumentObject::updateView(); | |
| } | |
| Base::Vector3d ViewProviderMeasure::getBasePosition() | |
| { | |
| auto measureObject = getMeasureObject(); | |
| Base::Placement placement = measureObject->getPlacement(); | |
| return placement.getPosition(); | |
| } | |
| Base::Vector3d ViewProviderMeasure::getTextPosition() | |
| { | |
| // Return the initial position relative to the base position | |
| auto basePoint = getBasePosition(); | |
| Gui::View3DInventor* view = dynamic_cast<Gui::View3DInventor*>(this->getActiveView()); | |
| if (!view) { | |
| Base::Console().log("ViewProviderMeasureBase::getTextPosition: Could not get active view\n"); | |
| return Base::Vector3d(); | |
| } | |
| Gui::View3DInventorViewer* viewer = view->getViewer(); | |
| // Convert to screenspace, offset and convert back to world space | |
| SbVec2s screenPos = viewer->getPointOnViewport(SbVec3f(basePoint.x, basePoint.y, basePoint.z)); | |
| SbVec3f vec = viewer->getPointOnFocalPlane(screenPos + SbVec2s(30.0, 30.0)); | |
| Base::Vector3d textPos(vec[0], vec[1], vec[2]); | |
| return textPos - basePoint; | |
| } | |
| //! called by the system when it is time to display this measure | |
| void ViewProviderMeasureBase::show() | |
| { | |
| if (isSubjectVisible()) { | |
| // only show the annotation if the subject is visible. | |
| // this avoids disconnected annotations floating in space. | |
| ViewProviderDocumentObject::show(); | |
| } | |
| } | |
| PROPERTY_SOURCE(MeasureGui::ViewProviderMeasureArea, MeasureGui::ViewProviderMeasure) | |
| PROPERTY_SOURCE(MeasureGui::ViewProviderMeasureLength, MeasureGui::ViewProviderMeasure) | |
| PROPERTY_SOURCE(MeasureGui::ViewProviderMeasurePosition, MeasureGui::ViewProviderMeasure) | |
| PROPERTY_SOURCE(MeasureGui::ViewProviderMeasureRadius, MeasureGui::ViewProviderMeasure) | |
| PROPERTY_SOURCE(MeasureGui::ViewProviderMeasureDiameter, MeasureGui::ViewProviderMeasure) | |
| PROPERTY_SOURCE(MeasureGui::ViewProviderMeasureCOM, MeasureGui::ViewProviderMeasure) | |