1
/***************************************************************************
2
* Copyright (c) 2023 David Friedli <david[at]friedli-be.ch> *
4
* This file is part of FreeCAD. *
6
* FreeCAD is free software: you can redistribute it and/or modify it *
7
* under the terms of the GNU Lesser General Public License as *
8
* published by the Free Software Foundation, either version 2.1 of the *
9
* License, or (at your option) any later version. *
11
* FreeCAD is distributed in the hope that it will be useful, but *
12
* WITHOUT ANY WARRANTY; without even the implied warranty of *
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
14
* Lesser General Public License for more details. *
16
* You should have received a copy of the GNU Lesser General Public *
17
* License along with FreeCAD. If not, see *
18
* <https://www.gnu.org/licenses/>. *
20
**************************************************************************/
23
#include "PreCompiled.h"
25
#include <App/Application.h>
26
#include <App/MeasureManager.h>
27
#include <App/Document.h>
29
#include "MeasureArea.h"
32
using namespace Measure;
34
PROPERTY_SOURCE(Measure::MeasureArea, Measure::MeasureBase)
37
MeasureArea::MeasureArea()
39
ADD_PROPERTY_TYPE(Elements,
43
"Element to get the area from");
44
Elements.setScope(App::LinkScope::Global);
45
Elements.setAllowExternal(true);
47
ADD_PROPERTY_TYPE(Area,
50
App::PropertyType(App::Prop_ReadOnly | App::Prop_Output),
54
MeasureArea::~MeasureArea() = default;
57
bool MeasureArea::isValidSelection(const App::MeasureSelection& selection)
60
if (selection.empty()) {
64
for (auto element : selection) {
65
auto type = App::MeasureManager::getMeasureElementType(element);
67
if (type == App::MeasureElementType::INVALID) {
71
// TODO: Also support Cylinder & Volume?
72
if ((type != App::MeasureElementType::PLANE && type != App::MeasureElementType::CYLINDER)) {
79
void MeasureArea::parseSelection(const App::MeasureSelection& selection)
81
// Set properties from selection, method is only invoked when isValid Selection returns true
83
std::vector<App::DocumentObject*> objects;
84
std::vector<std::string> subElements;
86
for (auto element : selection) {
87
auto objT = element.object;
89
objects.push_back(objT.getObject());
90
subElements.push_back(objT.getSubName());
93
Elements.setValues(objects, subElements);
97
App::DocumentObjectExecReturn* MeasureArea::execute()
99
const std::vector<App::DocumentObject*>& objects = Elements.getValues();
100
const std::vector<std::string>& subElements = Elements.getSubValues();
104
// Loop through Elements and call the valid geometry handler
105
for (std::vector<App::DocumentObject*>::size_type i = 0; i < objects.size(); i++) {
106
App::SubObjectT subject {objects.at(i), subElements.at(i).c_str()};
108
auto info = getMeasureInfo(subject);
109
if (!info || !info->valid) {
110
return new App::DocumentObjectExecReturn("Cannot calculate area");
112
auto areaInfo = std::dynamic_pointer_cast<Part::MeasureAreaInfo>(info);
113
result += areaInfo->area;
116
Area.setValue(result);
117
return DocumentObject::StdReturn;
121
void MeasureArea::onChanged(const App::Property* prop)
123
if (isRestoring() || isRemoving()) {
127
if (prop == &Elements) {
128
auto ret = recompute();
132
MeasureBase::onChanged(prop);
136
Base::Placement MeasureArea::getPlacement()
138
const std::vector<App::DocumentObject*>& objects = Elements.getValues();
139
const std::vector<std::string>& subElements = Elements.getSubValues();
141
if (objects.empty() || subElements.empty()) {
142
return Base::Placement();
145
App::SubObjectT subject {objects.front(), subElements.front().c_str()};
147
auto info = getMeasureInfo(subject);
151
auto areaInfo = std::dynamic_pointer_cast<Part::MeasureAreaInfo>(info);
152
return areaInfo->placement;
156
//! Return the object we are measuring
157
//! used by the viewprovider in determining visibility
158
std::vector<App::DocumentObject*> MeasureArea::getSubject() const
160
return Elements.getValues();