diff --git a/src/Mod/Measure/Gui/AppMeasureGui.cpp b/src/Mod/Measure/Gui/AppMeasureGui.cpp index 1194fbe3ff..d2e6b69050 100644 --- a/src/Mod/Measure/Gui/AppMeasureGui.cpp +++ b/src/Mod/Measure/Gui/AppMeasureGui.cpp @@ -89,6 +89,8 @@ PyMOD_INIT_FUNC(MeasureGui) // instantiating the commands CreateMeasureCommands(); + MeasureGui::DimensionLinear::initClass(); + MeasureGui::ViewProviderMeasureGroup ::init(); MeasureGui::ViewProviderMeasureBase ::init(); MeasureGui::ViewProviderMeasure ::init(); diff --git a/src/Mod/Measure/Gui/ViewProviderMeasureDistance.cpp b/src/Mod/Measure/Gui/ViewProviderMeasureDistance.cpp index bf2e8edc4f..fb0ed075c2 100644 --- a/src/Mod/Measure/Gui/ViewProviderMeasureDistance.cpp +++ b/src/Mod/Measure/Gui/ViewProviderMeasureDistance.cpp @@ -1,5 +1,6 @@ /*************************************************************************** * Copyright (c) 2023 David Friedli * + * Copyright (c) 2013 Thomas Anderson * * Copyright (c) 2008 Werner Mayer * * * * This file is part of FreeCAD. * @@ -23,20 +24,29 @@ #include "PreCompiled.h" #ifndef _PreComp_ -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #endif #include @@ -60,6 +70,163 @@ using namespace Measure; PROPERTY_SOURCE(MeasureGui::ViewProviderMeasureDistance, MeasureGui::ViewProviderMeasureBase) +SO_KIT_SOURCE(MeasureGui::DimensionLinear) + +void MeasureGui::DimensionLinear::initClass() +{ + SO_KIT_INIT_CLASS(DimensionLinear, SoSeparatorKit, "SeparatorKit"); +} + +MeasureGui::DimensionLinear::DimensionLinear() +{ + SO_KIT_CONSTRUCTOR(MeasureGui::DimensionLinear); + + SO_KIT_ADD_CATALOG_ENTRY(transformation, SoTransform, true, topSeparator, "", true); + SO_KIT_ADD_CATALOG_ENTRY(annotate, SoAnnotation, true, topSeparator, "", true); + SO_KIT_ADD_CATALOG_ENTRY(leftArrow, SoShapeKit, true, topSeparator, "", true); + SO_KIT_ADD_CATALOG_ENTRY(rightArrow, SoShapeKit, true, topSeparator, "", true); + SO_KIT_ADD_CATALOG_ENTRY(line, SoShapeKit, true, annotate, "", true); + SO_KIT_ADD_CATALOG_ENTRY(textSep, SoSeparator, true, annotate, "", true); + + SO_KIT_INIT_INSTANCE(); + + SO_NODE_ADD_FIELD(rotate, (1.0, 0.0, 0.0, 0.0)); // position orientation of the dimension. + SO_NODE_ADD_FIELD(length, (1.0)); // turns into dimension length + SO_NODE_ADD_FIELD(origin, (0.0, 0.0, 0.0)); // static + SO_NODE_ADD_FIELD(text, ("test")); // dimension text + SO_NODE_ADD_FIELD(dColor, (1.0, 0.0, 0.0)); // dimension color. + SO_NODE_ADD_FIELD(showArrows, (false)); // display dimension arrows + SO_NODE_ADD_FIELD(fontSize, (12.0)); // size of the dimension font +} + +MeasureGui::DimensionLinear::~DimensionLinear() +{} + +SbBool MeasureGui::DimensionLinear::affectsState() const +{ + return false; +} + +void MeasureGui::DimensionLinear::setupDimension() +{ + // make unpickable + SoPickStyle* ps = static_cast(getPart("pickStyle", true)); + if (ps) { + ps->style = SoPickStyle::UNPICKABLE; + } + + // transformation + SoTransform* trans = static_cast(getPart("transformation", true)); + trans->translation.connectFrom(&point1); + // build engine for vector subtraction and length. + SoCalculator* hyp = new SoCalculator(); + hyp->A.connectFrom(&point1); + hyp->B.connectFrom(&point2); + hyp->expression.set1Value(0, "oA = B-A"); + hyp->expression.set1Value(1, "oB = normalize(oA)"); + hyp->expression.set1Value(2, "oa = length(oA)"); + length.connectFrom(&hyp->oa); + + // build engine for rotation. + SoComposeRotationFromTo* rotationEngine = new SoComposeRotationFromTo(); + rotationEngine->from.setValue(SbVec3f(1.0, 0.0, 0.0)); + rotationEngine->to.connectFrom(&hyp->oB); + trans->rotation.connectFrom(&rotationEngine->rotation); + + // color + SoMaterial* material = new SoMaterial; + material->diffuseColor.connectFrom(&dColor); + + // dimension arrows + float dimLength = (point2.getValue() - point1.getValue()).length(); + float coneHeight = dimLength * 0.06; + float coneRadius = coneHeight * 0.5; + + SoComposeVec3f* vec = new SoComposeVec3f; + vec->x.connectFrom(&length); + vec->y.setValue(0.0); + vec->z.setValue(0.0); + + // NOTE: showArrows is only respected at setup stage and cannot be changed later + if (showArrows.getValue()) { + SoCone* cone = new SoCone(); + cone->bottomRadius.setValue(coneRadius); + cone->height.setValue(coneHeight); + + char lStr[100]; + char rStr[100]; + snprintf(lStr, sizeof(lStr), "translation %.6f 0.0 0.0", coneHeight * 0.5); + snprintf(rStr, sizeof(rStr), "translation 0.0 -%.6f 0.0", coneHeight * 0.5); + + setPart("leftArrow.shape", cone); + set("leftArrow.transform", "rotation 0.0 0.0 1.0 1.5707963"); + set("leftArrow.transform", lStr); + setPart("rightArrow.shape", cone); + set("rightArrow.transform", "rotation 0.0 0.0 -1.0 1.5707963"); // no constant for PI. + // have use local here to do the offset because the main is wired up to length of dimension. + set("rightArrow.localTransform", rStr); + + SoTransform* transform = static_cast(getPart("rightArrow.transform", false)); + if (!transform) { + return; // what to do here? + } + transform->translation.connectFrom(&vec->vector); + + setPart("leftArrow.material", material); + setPart("rightArrow.material", material); + } + + // line + SoConcatenate* catEngine = new SoConcatenate(SoMFVec3f::getClassTypeId()); + // don't know how to get around having this dummy origin. cat engine wants to connectfrom? + catEngine->input[0]->connectFrom(&origin); + catEngine->input[1]->connectFrom(&vec->vector); + + SoVertexProperty* lineVerts = new SoVertexProperty; + lineVerts->vertex.connectFrom(catEngine->output); + + int lineVertexMap[] = {0, 1}; + int lineVertexMapSize(sizeof(lineVertexMap) / sizeof(int)); + SoIndexedLineSet* line = new SoIndexedLineSet; + line->vertexProperty = lineVerts; + line->coordIndex.setValues(0, lineVertexMapSize, lineVertexMap); + + setPart("line.shape", line); + setPart("line.material", material); + + // text + SoSeparator* textSep = static_cast(getPart("textSep", true)); + if (!textSep) { + return; + } + + textSep->addChild(material); + + SoCalculator* textVecCalc = new SoCalculator(); + textVecCalc->A.connectFrom(&vec->vector); + textVecCalc->B.set1Value(0, 0.0, 0.250, 0.0); + textVecCalc->expression.set1Value(0, "oA = (A / 2) + B"); + + SoTransform* textTransform = new SoTransform(); + textTransform->translation.connectFrom(&textVecCalc->oA); + textSep->addChild(textTransform); + + SoFont* fontNode = new SoFont(); + fontNode->name.setValue("Helvetica : Bold"); + fontNode->size.connectFrom(&fontSize); + textSep->addChild(fontNode); + + SoText2* textNode = new SoText2(); + textNode->justification = SoText2::CENTER; + textNode->string.connectFrom(&text); + textSep->addChild(textNode); + + // this prevents the 2d text from screwing up the bounding box for a viewall + SoResetTransform* rTrans = new SoResetTransform; + rTrans->whatToReset = SoResetTransform::BBOX; + textSep->addChild(rTrans); +} + SbMatrix ViewProviderMeasureDistance::getMatrix() { if (!pcObject) { diff --git a/src/Mod/Measure/Gui/ViewProviderMeasureDistance.h b/src/Mod/Measure/Gui/ViewProviderMeasureDistance.h index 945f6c7f78..51eeb14344 100644 --- a/src/Mod/Measure/Gui/ViewProviderMeasureDistance.h +++ b/src/Mod/Measure/Gui/ViewProviderMeasureDistance.h @@ -1,5 +1,6 @@ /*************************************************************************** * Copyright (c) 2023 David Friedli * + * Copyright (c) 2013 Thomas Anderson * * * * This file is part of FreeCAD. * * * @@ -28,6 +29,17 @@ #include #include "ViewProviderMeasureBase.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + class SoCoordinate3; class SoIndexedLineSet; @@ -35,6 +47,40 @@ class SoIndexedLineSet; namespace MeasureGui { +class DimensionLinear: public SoSeparatorKit +{ + SO_KIT_HEADER(DimensionLinear); + + SO_KIT_CATALOG_ENTRY_HEADER(transformation); + SO_KIT_CATALOG_ENTRY_HEADER(annotate); + SO_KIT_CATALOG_ENTRY_HEADER(leftArrow); + SO_KIT_CATALOG_ENTRY_HEADER(rightArrow); + SO_KIT_CATALOG_ENTRY_HEADER(line); + SO_KIT_CATALOG_ENTRY_HEADER(textSep); + +public: + DimensionLinear(); + static void initClass(); + SbBool affectsState() const override; + void setupDimension(); + + SoSFVec3f point1; + SoSFVec3f point2; + SoSFString text; + SoSFColor dColor; + SoSFBool showArrows; + SoSFFloat fontSize; + +protected: + SoSFRotation rotate; + SoSFFloat length; + SoSFVec3f origin; + +private: + ~DimensionLinear() override; +}; + + class MeasureGuiExport ViewProviderMeasureDistance : public MeasureGui::ViewProviderMeasureBase {