1
/***************************************************************************
2
* Copyright (c) 2015 Stefan Tröger <stefantroeger@gmx.net> *
3
* Copyright (c) 2015 Alexander Golubev (Fat-Zer) <fatzer2@gmail.com> *
5
* This file is part of the FreeCAD CAx development system. *
7
* This library is free software; you can redistribute it and/or *
8
* modify it under the terms of the GNU Library General Public *
9
* License as published by the Free Software Foundation; either *
10
* version 2 of the License, or (at your option) any later version. *
12
* This library is distributed in the hope that it will be useful, *
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15
* GNU Library General Public License for more details. *
17
* You should have received a copy of the GNU Library General Public *
18
* License along with this library; see the file COPYING.LIB. If not, *
19
* write to the Free Software Foundation, Inc., 59 Temple Place, *
20
* Suite 330, Boston, MA 02111-1307, USA *
22
***************************************************************************/
24
#include "PreCompiled.h"
30
#include <App/Document.h>
31
#include <Base/Exception.h>
32
#include <Base/Placement.h>
35
#include "OriginFeature.h"
39
# define M_PI 3.14159265358979323846
45
PROPERTY_SOURCE(App::Origin, App::DocumentObject)
47
Origin::Origin() : extension(this) {
48
ADD_PROPERTY_TYPE ( OriginFeatures, (nullptr), 0, App::Prop_Hidden,
49
"Axis and baseplanes controlled by the origin" );
51
setStatus(App::NoAutoExpand,true);
52
extension.initExtension(this);
56
Origin::~Origin() = default;
58
App::OriginFeature *Origin::getOriginFeature( const char *role) const {
59
const auto & features = OriginFeatures.getValues ();
60
auto featIt = std::find_if (features.begin(), features.end(),
61
[role] (App::DocumentObject *obj) {
62
return obj->isDerivedFrom ( App::OriginFeature::getClassTypeId () ) &&
63
strcmp (static_cast<App::OriginFeature *>(obj)->Role.getValue(), role) == 0;
65
if (featIt != features.end()) {
66
return static_cast<App::OriginFeature *>(*featIt);
69
std::stringstream err;
70
err << "Origin \"" << getFullName () << "\" doesn't contain feature with role \""
72
throw Base::RuntimeError ( err.str().c_str () );
76
App::Line *Origin::getAxis( const char *role ) const {
77
App::OriginFeature *feat = getOriginFeature (role);
78
if ( feat->isDerivedFrom(App::Line::getClassTypeId () ) ) {
79
return static_cast<App::Line *> (feat);
81
std::stringstream err;
82
err << "Origin \"" << getFullName () << "\" contains bad Axis object for role \""
84
throw Base::RuntimeError ( err.str().c_str () );
88
App::Plane *Origin::getPlane( const char *role ) const {
89
App::OriginFeature *feat = getOriginFeature (role);
90
if ( feat->isDerivedFrom(App::Plane::getClassTypeId () ) ) {
91
return static_cast<App::Plane *> (feat);
93
std::stringstream err;
94
err << "Origin \"" << getFullName () << "\" contains bad Plane object for role \""
96
throw Base::RuntimeError ( err.str().c_str () );
100
bool Origin::hasObject (const DocumentObject *obj) const {
101
const auto & features = OriginFeatures.getValues ();
102
return std::find (features.begin(), features.end(), obj) != features.end ();
105
short Origin::mustExecute() const {
106
if (OriginFeatures.isTouched ()) {
109
return DocumentObject::mustExecute();
113
App::DocumentObjectExecReturn *Origin::execute() {
114
try { // try to find all base axis and planes in the origin
115
for (const char* role: AxisRoles) {
116
App::Line *axis = getAxis (role);
120
for (const char* role: PlaneRoles) {
121
App::Plane *plane = getPlane (role);
125
} catch (const Base::Exception &ex) {
127
return new App::DocumentObjectExecReturn ( ex.what () );
130
return DocumentObject::execute ();
133
void Origin::setupObject () {
134
const static struct {
135
const Base::Type type;
142
{App::Line::getClassTypeId(), AxisRoles[0], tr("X-axis"), Base::Rotation()},
143
{App::Line::getClassTypeId(), AxisRoles[1], tr("Y-axis"), Base::Rotation(Base::Vector3d(1,1,1), M_PI*2/3)},
144
{App::Line::getClassTypeId(), AxisRoles[2], tr("Z-axis"), Base::Rotation(Base::Vector3d(1,-1,1), M_PI*2/3)},
145
{App::Plane::getClassTypeId(), PlaneRoles[0], tr("XY-plane"), Base::Rotation()},
146
{App::Plane::getClassTypeId(), PlaneRoles[1], tr("XZ-plane"), Base::Rotation(1.0, 0.0, 0.0, 1.0 )},
147
{App::Plane::getClassTypeId(), PlaneRoles[2], tr("YZ-plane"), Base::Rotation(Base::Vector3d(1,1,1), M_PI*2/3)}
151
App::Document *doc = getDocument ();
153
std::vector<App::DocumentObject *> links;
154
for (auto data: setupData) {
155
std::string objName = doc->getUniqueObjectName ( data.role );
156
App::DocumentObject *featureObj = doc->addObject ( data.type.getName(), objName.c_str () );
158
assert ( featureObj && featureObj->isDerivedFrom ( App::OriginFeature::getClassTypeId () ) );
160
QByteArray byteArray = data.label.toUtf8();
161
featureObj->Label.setValue(byteArray.constData());
163
App::OriginFeature *feature = static_cast <App::OriginFeature *> ( featureObj );
164
feature->Placement.setValue ( Base::Placement ( Base::Vector3d (), data.rot ) );
165
feature->Role.setValue ( data.role );
167
links.push_back (feature);
170
OriginFeatures.setValues (links);
173
void Origin::unsetupObject () {
174
const auto &objsLnk = OriginFeatures.getValues ();
175
// Copy to set to assert we won't call methode more then one time for each object
176
std::set<App::DocumentObject *> objs (objsLnk.begin(), objsLnk.end());
177
// Remove all controlled objects
178
for (auto obj: objs ) {
179
// Check that previous deletes wasn't inderectly removed one of our objects
180
const auto &objsLnk = OriginFeatures.getValues ();
181
if ( std::find(objsLnk.begin(), objsLnk.end(), obj) != objsLnk.end()) {
182
if ( ! obj->isRemoving() ) {
183
obj->getDocument()->removeObject (obj->getNameInDocument());
189
// ----------------------------------------------------------------------------
191
Origin::OriginExtension::OriginExtension(Origin* obj)
194
Group.setStatus(Property::Transient, true);
197
void Origin::OriginExtension::initExtension(ExtensionContainer* obj) {
198
App::GroupExtension::initExtension(obj);
201
bool Origin::OriginExtension::extensionGetSubObject(DocumentObject *&ret, const char *subname,
202
PyObject **pyobj, Base::Matrix4D *mat, bool, int depth) const {
203
if (!subname || subname[0] == '\0') {
207
// mapping of object name to role name
208
std::string name(subname);
209
for (int i=0; i<3; i++) {
210
if (name.rfind(Origin::AxisRoles[i], 0) == 0) {
211
name = Origin::AxisRoles[i];
214
if (name.rfind(Origin::PlaneRoles[i], 0) == 0) {
215
name = Origin::PlaneRoles[i];
221
ret = obj->getOriginFeature(name.c_str());
224
const char *dot = strchr(subname, '.');
229
ret = ret->getSubObject(subname, pyobj, mat, true, depth+1);
232
catch (const Base::Exception& e) {