[Std_Measure] Add diameter measurement (#24853)

* Add diameter measurement support

* change author name and change icon

* correct svg size to 64x64

* Update src/Mod/Measure/App/MeasureDiameter.cpp

Co-authored-by: Kacper Donat <kadet1090@gmail.com>

* somehow to icon color is undefine in inkscape, change to black

* Revert "somehow to icon color is undefine in inkscape, change to black"

This reverts commit 2277c1b9f4a7ab7519856986e2d6aec6e37ebf3e.

	modified:   src/Mod/Measure/Gui/Resources/icons/Measurement-Diameter.svg

* fix black color icon

---------

Co-authored-by: Kacper Donat <kadet1090@gmail.com>
This commit is contained in:
Kavin Teenakul
2026-01-07 15:16:24 +07:00
committed by GitHub
parent a67d776ac7
commit 4aa80c1890
9 changed files with 310 additions and 0 deletions

View File

@@ -43,6 +43,7 @@
#include "MeasurePosition.h"
#include "MeasureLength.h"
#include "MeasureArea.h"
#include "MeasureDiameter.h"
#include "MeasureRadius.h"
namespace Measure
@@ -106,6 +107,7 @@ PyMOD_INIT_FUNC(Measure)
Measure::MeasurePosition ::init();
Measure::MeasureLength ::init();
Measure::MeasureArea ::init();
Measure::MeasureDiameter ::init();
Measure::MeasureRadius ::init();
// Add fundamental umf Measure Types
@@ -158,6 +160,14 @@ PyMOD_INIT_FUNC(Measure)
nullptr
);
App::MeasureManager::addMeasureType(
"DIAMETER",
"Diameter",
"Measure::MeasureDiameter",
MeasureDiameter::isValidSelection,
MeasureDiameter::isPrioritizedSelection
);
App::MeasureManager::addMeasureType(
"RADIUS",
QT_TRANSLATE_NOOP("TaskMeasure", "Radius"),

View File

@@ -38,6 +38,8 @@ SET(MeasureModule_SRCS
MeasureLength.h
MeasureArea.cpp
MeasureArea.h
MeasureDiameter.cpp
MeasureDiameter.h
MeasureRadius.cpp
MeasureRadius.h

View File

@@ -0,0 +1,163 @@
/***************************************************************************
* Copyright (c) 2025 Kavin Teenakul <andythe_great@protonmail.com> *
* *
* 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/>. *
* *
***************************************************************************/
#include <TopExp_Explorer.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Edge.hxx>
#include <TopoDS_Wire.hxx>
#include <BRepAdaptor_Curve.hxx>
#include <BRepLProp_CLProps.hxx>
#include <App/Application.h>
#include <App/Document.h>
#include <App/MeasureManager.h>
#include <Mod/Part/App/PartFeature.h>
#include "MeasureDiameter.h"
using namespace Measure;
PROPERTY_SOURCE(Measure::MeasureDiameter, Measure::MeasureBase)
MeasureDiameter::MeasureDiameter()
{
ADD_PROPERTY_TYPE(Element, (nullptr), "Measurement", App::Prop_None, "Element to get the diameter from");
Element.setScope(App::LinkScope::Global);
Element.setAllowExternal(true);
ADD_PROPERTY_TYPE(
Diameter,
(0.0),
"Measurement",
App::PropertyType(App::Prop_ReadOnly | App::Prop_Output),
"Diameter of selection"
);
}
MeasureDiameter::~MeasureDiameter() = default;
bool MeasureDiameter::isValidSelection(const App::MeasureSelection& selection)
{
if (selection.empty() || selection.size() > 1) {
return false;
}
auto element = selection.front();
auto type = App::MeasureManager::getMeasureElementType(element);
if (type == App::MeasureElementType::INVALID) {
return false;
}
if (type != App::MeasureElementType::CIRCLE && type != App::MeasureElementType::ARC) {
return false;
}
return true;
}
bool MeasureDiameter::isPrioritizedSelection(const App::MeasureSelection& selection)
{
if (selection.size() != 1) {
return false;
}
auto element = selection.front();
auto type = App::MeasureManager::getMeasureElementType(element);
if (type == App::MeasureElementType::CIRCLE || type == App::MeasureElementType::ARC) {
return true;
}
return false;
}
void MeasureDiameter::parseSelection(const App::MeasureSelection& selection)
{
auto element = selection.front();
auto objT = element.object;
std::vector<std::string> subElementList {objT.getSubName()};
Element.setValue(objT.getObject(), subElementList);
}
App::DocumentObjectExecReturn* MeasureDiameter::execute()
{
auto info = getMeasureInfoFirst();
if (!info || !info->valid) {
return new App::DocumentObjectExecReturn("Cannot calculate diameter");
}
Diameter.setValue(info->radius * 2.0);
return DocumentObject::StdReturn;
}
void MeasureDiameter::onChanged(const App::Property* prop)
{
if (isRestoring() || isRemoving()) {
return;
}
if (prop == &Element) {
auto ret = recompute();
delete ret;
}
MeasureBase::onChanged(prop);
}
Base::Placement MeasureDiameter::getPlacement()
{
auto loc = getMeasureInfoFirst()->pointOnCurve;
auto p = Base::Placement();
p.setPosition(loc);
return p;
}
Base::Vector3d MeasureDiameter::getPointOnCurve() const
{
return getMeasureInfoFirst()->pointOnCurve;
}
Part::MeasureRadiusInfoPtr MeasureDiameter::getMeasureInfoFirst() const
{
const App::DocumentObject* object = Element.getValue();
const std::vector<std::string>& subElements = Element.getSubValues();
if (!object || subElements.empty()) {
return std::make_shared<Part::MeasureRadiusInfo>();
}
App::SubObjectT subject {object, subElements.front().c_str()};
auto info = getMeasureInfo(subject);
if (!info || !info->valid) {
return std::make_shared<Part::MeasureRadiusInfo>();
}
return std::dynamic_pointer_cast<Part::MeasureRadiusInfo>(info);
}
std::vector<App::DocumentObject*> MeasureDiameter::getSubject() const
{
return {Element.getValue()};
}

View File

@@ -0,0 +1,83 @@
/***************************************************************************
* Copyright (c) 2024 Kavin Teenakul <andythe_great@protonmail.com> *
* *
* 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/>. *
* *
***************************************************************************/
#ifndef MEASURE_MEASUREDIAMETER_H
#define MEASURE_MEASUREDIAMETER_H
#include <Mod/Measure/MeasureGlobal.h>
#include <App/Application.h>
#include <App/GeoFeature.h>
#include <App/PropertyLinks.h>
#include <App/PropertyUnits.h>
#include <Base/Placement.h>
#include <Mod/Part/App/MeasureInfo.h>
#include "MeasureBase.h"
namespace Measure
{
class MeasureExport MeasureDiameter: public Measure::MeasureBaseExtendable<Part::MeasureRadiusInfo>
{
PROPERTY_HEADER_WITH_OVERRIDE(Measure::MeasureDiameter);
public:
MeasureDiameter();
~MeasureDiameter() override;
App::PropertyLinkSub Element;
App::PropertyDistance Diameter;
App::DocumentObjectExecReturn* execute() override;
const char* getViewProviderName() const override
{
return "MeasureGui::ViewProviderMeasureDiameter";
}
static bool isValidSelection(const App::MeasureSelection& selection);
static bool isPrioritizedSelection(const App::MeasureSelection& selection);
void parseSelection(const App::MeasureSelection& selection) override;
std::vector<std::string> getInputProps() override
{
return {"Element"};
}
App::Property* getResultProp() override
{
return &this->Diameter;
}
Base::Placement getPlacement() override;
Base::Vector3d getPointOnCurve() const;
std::vector<App::DocumentObject*> getSubject() const override;
private:
void onChanged(const App::Property* prop) override;
Part::MeasureRadiusInfoPtr getMeasureInfoFirst() const;
};
} // namespace Measure
#endif // MEASURE_MEASUREDIAMETER_H

View File

@@ -101,6 +101,7 @@ PyMOD_INIT_FUNC(MeasureGui)
MeasureGui::ViewProviderMeasureLength ::init();
MeasureGui::ViewProviderMeasurePosition ::init();
MeasureGui::ViewProviderMeasureRadius ::init();
MeasureGui::ViewProviderMeasureDiameter ::init();
MeasureGui::ViewProviderMeasureCOM ::init();
// clang-format on

View File

@@ -9,6 +9,7 @@
<file>icons/Measurement-Group.svg</file>
<file>icons/Measurement-Inertia.svg</file>
<file>icons/Measurement-Position.svg</file>
<file>icons/Measurement-Diameter.svg</file>
<file>icons/Measurement-Radius.svg</file>
<file>icons/Measurement-Volume.svg</file>
</qresource>

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@@ -742,4 +742,5 @@ PROPERTY_SOURCE(MeasureGui::ViewProviderMeasureArea, MeasureGui::ViewProviderMea
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)

View File

@@ -245,6 +245,17 @@ public:
}
};
class ViewProviderMeasureDiameter: public ViewProviderMeasure
{
PROPERTY_HEADER(MeasureGui::ViewProviderMeasureDiameter);
public:
ViewProviderMeasureDiameter()
{
sPixmap = "Measurement-Diameter";
}
};
class ViewProviderMeasureCOM: public ViewProviderMeasure
{
PROPERTY_HEADER(MeasureGui::ViewProviderMeasureCOM);