1
/***************************************************************************
2
* Copyright (c) 2002 Jürgen Riegel <juergen.riegel@web.de> *
4
* This file is part of the FreeCAD CAx development system. *
6
* This library is free software; you can redistribute it and/or *
7
* modify it under the terms of the GNU Library General Public *
8
* License as published by the Free Software Foundation; either *
9
* version 2 of the License, or (at your option) any later version. *
11
* This library is distributed in the hope that it will be useful, *
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14
* GNU Library General Public License for more details. *
16
* You should have received a copy of the GNU Library General Public *
17
* License along with this library; see the file COPYING.LIB. If not, *
18
* write to the Free Software Foundation, Inc., 59 Temple Place, *
19
* Suite 330, Boston, MA 02111-1307, USA *
21
***************************************************************************/
24
#include "PreCompiled.h"
26
#include <Base/MatrixPy.h>
27
#include <Base/PlacementPy.h>
28
#include <Base/Reader.h>
30
#include <Base/Quantity.h>
31
#include <Base/QuantityPy.h>
32
#include <Base/Rotation.h>
33
#include <Base/RotationPy.h>
34
#include <Base/Stream.h>
35
#include <Base/Tools.h>
36
#include <Base/VectorPy.h>
37
#include <Base/Writer.h>
39
#include "ComplexGeoData.h"
41
#include "PropertyGeo.h"
43
#include "ObjectIdentifier.h"
53
//**************************************************************************
54
//**************************************************************************
56
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
58
TYPESYSTEM_SOURCE(App::PropertyVector , App::Property)
60
//**************************************************************************
61
// Construction/Destruction
64
PropertyVector::PropertyVector() = default;
67
PropertyVector::~PropertyVector() = default;
69
//**************************************************************************
70
// Base class implementer
73
void PropertyVector::setValue(const Base::Vector3d &vec)
80
void PropertyVector::setValue(double x, double y, double z)
87
const Base::Vector3d & PropertyVector::getValue()const
92
PyObject *PropertyVector::getPyObject()
94
return new Base::VectorPy(_cVec);
97
void PropertyVector::setPyObject(PyObject *value)
99
if (PyObject_TypeCheck(value, &(Base::VectorPy::Type))) {
100
Base::VectorPy *pcObject = static_cast<Base::VectorPy*>(value);
101
Base::Vector3d* val = pcObject->getVectorPtr();
104
else if (PyTuple_Check(value)&&PyTuple_Size(value)==3) {
108
item = PyTuple_GetItem(value,0);
109
if (PyFloat_Check(item))
110
cVec.x = PyFloat_AsDouble(item);
111
else if (PyLong_Check(item))
112
cVec.x = (double)PyLong_AsLong(item);
114
throw Base::TypeError("Not allowed type used in tuple (float expected)...");
116
item = PyTuple_GetItem(value,1);
117
if (PyFloat_Check(item))
118
cVec.y = PyFloat_AsDouble(item);
119
else if (PyLong_Check(item))
120
cVec.y = (double)PyLong_AsLong(item);
122
throw Base::TypeError("Not allowed type used in tuple (float expected)...");
124
item = PyTuple_GetItem(value,2);
125
if (PyFloat_Check(item))
126
cVec.z = PyFloat_AsDouble(item);
127
else if (PyLong_Check(item))
128
cVec.z = (double)PyLong_AsLong(item);
130
throw Base::TypeError("Not allowed type used in tuple (float expected)...");
134
std::string error = std::string("type must be 'Vector' or tuple of three floats, not ");
135
error += value->ob_type->tp_name;
136
throw Base::TypeError(error);
140
void PropertyVector::Save (Base::Writer &writer) const
142
writer.Stream() << writer.ind() << "<PropertyVector valueX=\"" << _cVec.x << "\" valueY=\"" << _cVec.y << "\" valueZ=\"" << _cVec.z <<"\"/>" << endl;
145
void PropertyVector::Restore(Base::XMLReader &reader)
148
reader.readElement("PropertyVector");
149
// get the value of my Attribute
151
_cVec.x = reader.getAttributeAsFloat("valueX");
152
_cVec.y = reader.getAttributeAsFloat("valueY");
153
_cVec.z = reader.getAttributeAsFloat("valueZ");
158
Property *PropertyVector::Copy() const
160
PropertyVector *p= new PropertyVector();
165
void PropertyVector::Paste(const Property &from)
168
_cVec = dynamic_cast<const PropertyVector&>(from)._cVec;
172
void PropertyVector::getPaths(std::vector<ObjectIdentifier> &paths) const
174
paths.push_back(ObjectIdentifier(*this)
175
<< ObjectIdentifier::SimpleComponent(ObjectIdentifier::String("x")));
176
paths.push_back(ObjectIdentifier(*this)
177
<< ObjectIdentifier::SimpleComponent(ObjectIdentifier::String("y")));
178
paths.push_back(ObjectIdentifier(*this)
179
<< ObjectIdentifier::SimpleComponent(ObjectIdentifier::String("z")));
182
const boost::any PropertyVector::getPathValue(const ObjectIdentifier &path) const
184
Base::Unit unit = getUnit();
185
if(!unit.isEmpty()) {
186
std::string p = path.getSubPathStr();
187
if (p == ".x" || p == ".y" || p == ".z") {
188
// Convert double to quantity
189
return Base::Quantity(boost::any_cast<double>(Property::getPathValue(path)), unit);
192
return Property::getPathValue(path);
195
bool PropertyVector::getPyPathValue(const ObjectIdentifier &path, Py::Object &res) const
197
Base::Unit unit = getUnit();
201
std::string p = path.getSubPathStr();
203
res = Py::asObject(new QuantityPy(new Quantity(getValue().x,unit)));
204
} else if(p == ".y") {
205
res = Py::asObject(new QuantityPy(new Quantity(getValue().y,unit)));
206
} else if(p == ".z") {
207
res = Py::asObject(new QuantityPy(new Quantity(getValue().z,unit)));
214
//**************************************************************************
215
// PropertyVectorDistance
216
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
218
TYPESYSTEM_SOURCE(App::PropertyVectorDistance , App::PropertyVector)
220
//**************************************************************************
221
// Construction/Destruction
224
PropertyVectorDistance::PropertyVectorDistance() = default;
226
PropertyVectorDistance::~PropertyVectorDistance() = default;
228
//**************************************************************************
230
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
232
TYPESYSTEM_SOURCE(App::PropertyPosition , App::PropertyVector)
234
//**************************************************************************
235
// Construction/Destruction
238
PropertyPosition::PropertyPosition() = default;
240
PropertyPosition::~PropertyPosition() = default;
242
//**************************************************************************
244
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
246
TYPESYSTEM_SOURCE(App::PropertyDirection , App::PropertyVector)
248
//**************************************************************************
249
// Construction/Destruction
252
PropertyDirection::PropertyDirection() = default;
254
PropertyDirection::~PropertyDirection() = default;
256
//**************************************************************************
258
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
260
TYPESYSTEM_SOURCE(App::PropertyVectorList , App::PropertyLists)
262
//**************************************************************************
263
// Construction/Destruction
265
PropertyVectorList::PropertyVectorList() = default;
267
PropertyVectorList::~PropertyVectorList() = default;
269
//**************************************************************************
270
// Base class implementer
272
void PropertyVectorList::setValue(double x, double y, double z)
274
setValue(Base::Vector3d(x,y,z));
277
PyObject *PropertyVectorList::getPyObject()
279
PyObject* list = PyList_New(getSize());
281
for (int i = 0;i < getSize(); i++)
282
PyList_SetItem(list, i, new VectorPy(_lValueList[i]));
287
Base::Vector3d PropertyVectorList::getPyValue(PyObject *item) const {
289
val.setPyObject( item );
290
return val.getValue();
293
void PropertyVectorList::Save (Base::Writer &writer) const
295
if (!writer.isForceXML()) {
296
writer.Stream() << writer.ind() << "<VectorList file=\"" << writer.addFile(getName(), this) << "\"/>" << std::endl;
300
void PropertyVectorList::Restore(Base::XMLReader &reader)
302
reader.readElement("VectorList");
303
std::string file (reader.getAttribute("file") );
306
// initiate a file read
307
reader.addFile(file.c_str(),this);
311
void PropertyVectorList::SaveDocFile (Base::Writer &writer) const
313
Base::OutputStream str(writer.Stream());
314
uint32_t uCt = (uint32_t)getSize();
316
if (!isSinglePrecision()) {
317
for (const auto & it : _lValueList) {
318
str << it.x << it.y << it.z;
322
for (const auto & it : _lValueList) {
323
float x = (float)it.x;
324
float y = (float)it.y;
325
float z = (float)it.z;
331
void PropertyVectorList::RestoreDocFile(Base::Reader &reader)
333
Base::InputStream str(reader);
336
std::vector<Base::Vector3d> values(uCt);
337
if (!isSinglePrecision()) {
338
for (auto & it : values) {
339
str >> it.x >> it.y >> it.z;
344
for (auto & it : values) {
352
Property *PropertyVectorList::Copy() const
354
PropertyVectorList *p= new PropertyVectorList();
355
p->_lValueList = _lValueList;
359
void PropertyVectorList::Paste(const Property &from)
361
setValues(dynamic_cast<const PropertyVectorList&>(from)._lValueList);
364
unsigned int PropertyVectorList::getMemSize () const
366
return static_cast<unsigned int>(_lValueList.size() * sizeof(Base::Vector3d));
369
//**************************************************************************
370
//**************************************************************************
372
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
374
TYPESYSTEM_SOURCE(App::PropertyMatrix , App::Property)
376
//**************************************************************************
377
// Construction/Destruction
380
PropertyMatrix::PropertyMatrix() = default;
383
PropertyMatrix::~PropertyMatrix() = default;
385
//**************************************************************************
386
// Base class implementer
389
void PropertyMatrix::setValue(const Base::Matrix4D &mat)
397
const Base::Matrix4D & PropertyMatrix::getValue()const
402
PyObject *PropertyMatrix::getPyObject()
404
return new Base::MatrixPy(_cMat);
407
void PropertyMatrix::setPyObject(PyObject *value)
409
if (PyObject_TypeCheck(value, &(Base::MatrixPy::Type))) {
410
Base::MatrixPy *pcObject = static_cast<Base::MatrixPy*>(value);
411
setValue( pcObject->value() );
413
else if (PyTuple_Check(value)&&PyTuple_Size(value)==16) {
415
Base::Matrix4D cMatrix;
417
for (int x=0; x<4;x++) {
418
for (int y=0; y<4;y++) {
419
item = PyTuple_GetItem(value,x+y*4);
420
if (PyFloat_Check(item))
421
cMatrix[x][y] = PyFloat_AsDouble(item);
422
else if (PyLong_Check(item))
423
cMatrix[x][y] = (double)PyLong_AsLong(item);
425
throw Base::TypeError("Not allowed type used in matrix tuple (a number expected)...");
432
std::string error = std::string("type must be 'Matrix' or tuple of 16 float or int, not ");
433
error += value->ob_type->tp_name;
434
throw Base::TypeError(error);
438
void PropertyMatrix::Save (Base::Writer &writer) const
440
writer.Stream() << writer.ind() << "<PropertyMatrix";
441
writer.Stream() << " a11=\"" << _cMat[0][0] << "\" a12=\"" << _cMat[0][1] << "\" a13=\"" << _cMat[0][2] << "\" a14=\"" << _cMat[0][3] << "\"";
442
writer.Stream() << " a21=\"" << _cMat[1][0] << "\" a22=\"" << _cMat[1][1] << "\" a23=\"" << _cMat[1][2] << "\" a24=\"" << _cMat[1][3] << "\"";
443
writer.Stream() << " a31=\"" << _cMat[2][0] << "\" a32=\"" << _cMat[2][1] << "\" a33=\"" << _cMat[2][2] << "\" a34=\"" << _cMat[2][3] << "\"";
444
writer.Stream() << " a41=\"" << _cMat[3][0] << "\" a42=\"" << _cMat[3][1] << "\" a43=\"" << _cMat[3][2] << "\" a44=\"" << _cMat[3][3] << "\"";
445
writer.Stream() <<"/>" << endl;
448
void PropertyMatrix::Restore(Base::XMLReader &reader)
451
reader.readElement("PropertyMatrix");
452
// get the value of my Attribute
454
_cMat[0][0] = reader.getAttributeAsFloat("a11");
455
_cMat[0][1] = reader.getAttributeAsFloat("a12");
456
_cMat[0][2] = reader.getAttributeAsFloat("a13");
457
_cMat[0][3] = reader.getAttributeAsFloat("a14");
459
_cMat[1][0] = reader.getAttributeAsFloat("a21");
460
_cMat[1][1] = reader.getAttributeAsFloat("a22");
461
_cMat[1][2] = reader.getAttributeAsFloat("a23");
462
_cMat[1][3] = reader.getAttributeAsFloat("a24");
464
_cMat[2][0] = reader.getAttributeAsFloat("a31");
465
_cMat[2][1] = reader.getAttributeAsFloat("a32");
466
_cMat[2][2] = reader.getAttributeAsFloat("a33");
467
_cMat[2][3] = reader.getAttributeAsFloat("a34");
469
_cMat[3][0] = reader.getAttributeAsFloat("a41");
470
_cMat[3][1] = reader.getAttributeAsFloat("a42");
471
_cMat[3][2] = reader.getAttributeAsFloat("a43");
472
_cMat[3][3] = reader.getAttributeAsFloat("a44");
477
Property *PropertyMatrix::Copy() const
479
PropertyMatrix *p= new PropertyMatrix();
484
void PropertyMatrix::Paste(const Property &from)
487
_cMat = dynamic_cast<const PropertyMatrix&>(from)._cMat;
491
//**************************************************************************
492
//**************************************************************************
494
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
496
TYPESYSTEM_SOURCE(App::PropertyPlacement , App::Property)
498
//**************************************************************************
499
// Construction/Destruction
502
PropertyPlacement::PropertyPlacement() = default;
505
PropertyPlacement::~PropertyPlacement() = default;
507
//**************************************************************************
508
// Base class implementer
511
void PropertyPlacement::setValue(const Base::Placement &pos)
518
bool PropertyPlacement::setValueIfChanged(const Base::Placement &pos,double tol,double atol)
520
if(_cPos.getPosition().IsEqual(pos.getPosition(),tol)
521
&& _cPos.getRotation().isSame(pos.getRotation(),atol))
530
const Base::Placement & PropertyPlacement::getValue()const
535
void PropertyPlacement::getPaths(std::vector<ObjectIdentifier> &paths) const
537
paths.push_back(ObjectIdentifier(*this)
538
<< ObjectIdentifier::SimpleComponent(ObjectIdentifier::String("Base"))
539
<< ObjectIdentifier::SimpleComponent(ObjectIdentifier::String("x")));
540
paths.push_back(ObjectIdentifier(*this)
541
<< ObjectIdentifier::SimpleComponent(ObjectIdentifier::String("Base"))
542
<< ObjectIdentifier::SimpleComponent(ObjectIdentifier::String("y")));
543
paths.push_back(ObjectIdentifier(*this)
544
<< ObjectIdentifier::SimpleComponent(ObjectIdentifier::String("Base"))
545
<< ObjectIdentifier::SimpleComponent(ObjectIdentifier::String("z")));
546
paths.push_back(ObjectIdentifier(*this)
547
<< ObjectIdentifier::SimpleComponent(ObjectIdentifier::String("Rotation"))
548
<< ObjectIdentifier::SimpleComponent(ObjectIdentifier::String("Angle")));
549
paths.push_back(ObjectIdentifier(*this)
550
<< ObjectIdentifier::SimpleComponent(ObjectIdentifier::String("Rotation"))
551
<< ObjectIdentifier::SimpleComponent(ObjectIdentifier::String("Axis"))
552
<< ObjectIdentifier::SimpleComponent(ObjectIdentifier::String("x")));
553
paths.push_back(ObjectIdentifier(*this)
554
<< ObjectIdentifier::SimpleComponent(ObjectIdentifier::String("Rotation"))
555
<< ObjectIdentifier::SimpleComponent(ObjectIdentifier::String("Axis"))
556
<< ObjectIdentifier::SimpleComponent(ObjectIdentifier::String("y")));
557
paths.push_back(ObjectIdentifier(*this)
558
<< ObjectIdentifier::SimpleComponent(ObjectIdentifier::String("Rotation"))
559
<< ObjectIdentifier::SimpleComponent(ObjectIdentifier::String("Axis"))
560
<< ObjectIdentifier::SimpleComponent(ObjectIdentifier::String("z")));
564
double toDouble(const boost::any &value)
568
if (value.type() == typeid(Base::Quantity))
569
avalue = boost::any_cast<Base::Quantity>(value).getValue();
570
else if (value.type() == typeid(double))
571
avalue = boost::any_cast<double>(value);
572
else if (value.type() == typeid(int))
573
avalue = boost::any_cast<int>(value);
574
else if (value.type() == typeid(unsigned int))
575
avalue = boost::any_cast<unsigned int >(value);
576
else if (value.type() == typeid(short))
577
avalue = boost::any_cast<short>(value);
578
else if (value.type() == typeid(unsigned short))
579
avalue = boost::any_cast<unsigned short>(value);
580
else if (value.type() == typeid(long))
581
avalue = boost::any_cast<long>(value);
582
else if (value.type() == typeid(unsigned long))
583
avalue = boost::any_cast<unsigned long>(value);
585
throw std::bad_cast();
590
void PropertyPlacement::setPathValue(const ObjectIdentifier &path, const boost::any &value)
592
auto updateAxis = [=](int index, double coord) {
595
Base::Vector3d base = _cPos.getPosition();
596
Base::Rotation rot = _cPos.getRotation();
597
rot.getRawValue(axis, angle);
599
rot.setValue(axis, angle);
600
Base::Placement plm(base, rot);
604
auto updateYawPitchRoll = [=](int index, double angle) {
605
Base::Vector3d base = _cPos.getPosition();
606
Base::Rotation rot = _cPos.getRotation();
607
double yaw, pitch, roll;
608
rot.getYawPitchRoll(yaw, pitch, roll);
610
if (angle < -180.0 || angle > 180.0)
611
throw Base::ValueError("Yaw angle is out of range [-180, +180]");
614
else if (index == 1) {
615
if (angle < -90.0 || angle > 90.0)
616
throw Base::ValueError("Pitch angle is out of range [-90, +90]");
619
else if (index == 2) {
620
if (angle < -180.0 || angle > 180.0)
621
throw Base::ValueError("Roll angle is out of range [-180, +180]");
624
rot.setYawPitchRoll(yaw, pitch, roll);
625
Base::Placement plm(base, rot);
629
std::string subpath = path.getSubPathStr();
630
if (subpath == ".Rotation.Angle") {
631
double avalue = toDouble(value);
632
Property::setPathValue(path, Base::toRadians(avalue));
634
else if (subpath == ".Rotation.Axis.x") {
635
updateAxis(0, toDouble(value));
637
else if (subpath == ".Rotation.Axis.y") {
638
updateAxis(1, toDouble(value));
640
else if (subpath == ".Rotation.Axis.z") {
641
updateAxis(2, toDouble(value));
643
else if (subpath == ".Rotation.Yaw") {
644
updateYawPitchRoll(0, toDouble(value));
646
else if (subpath == ".Rotation.Pitch") {
647
updateYawPitchRoll(1, toDouble(value));
649
else if (subpath == ".Rotation.Roll") {
650
updateYawPitchRoll(2, toDouble(value));
653
Property::setPathValue(path, value);
657
const boost::any PropertyPlacement::getPathValue(const ObjectIdentifier &path) const
659
auto getAxis = [](const Base::Placement& plm) {
662
const Base::Rotation& rot = plm.getRotation();
663
rot.getRawValue(axis, angle);
667
auto getYawPitchRoll = [](const Base::Placement& plm) {
669
const Base::Rotation& rot = plm.getRotation();
670
rot.getYawPitchRoll(ypr.x, ypr.y, ypr.z);
674
std::string p = path.getSubPathStr();
676
if (p == ".Rotation.Angle") {
677
// Convert angle to degrees
678
return Base::Quantity(Base::toDegrees(boost::any_cast<double>(Property::getPathValue(path))), Unit::Angle);
680
else if (p == ".Base.x" || p == ".Base.y" || p == ".Base.z") {
681
// Convert double to quantity
682
return Base::Quantity(boost::any_cast<double>(Property::getPathValue(path)), Unit::Length);
684
else if (p == ".Rotation.Axis.x") {
685
return getAxis(_cPos).x;
687
else if (p == ".Rotation.Axis.y") {
688
return getAxis(_cPos).y;
690
else if (p == ".Rotation.Axis.z") {
691
return getAxis(_cPos).z;
693
else if (p == ".Rotation.Yaw") {
694
return getYawPitchRoll(_cPos).x;
696
else if (p == ".Rotation.Pitch") {
697
return getYawPitchRoll(_cPos).y;
699
else if (p == ".Rotation.Roll") {
700
return getYawPitchRoll(_cPos).z;
703
return Property::getPathValue(path);
707
bool PropertyPlacement::getPyPathValue(const ObjectIdentifier &path, Py::Object &res) const
709
auto getAxis = [](const Base::Placement& plm) {
712
const Base::Rotation& rot = plm.getRotation();
713
rot.getRawValue(axis, angle);
717
auto getYawPitchRoll = [](const Base::Placement& plm) {
719
const Base::Rotation& rot = plm.getRotation();
720
rot.getYawPitchRoll(ypr.x, ypr.y, ypr.z);
724
std::string p = path.getSubPathStr();
725
if (p == ".Rotation.Angle") {
726
Base::Vector3d axis; double angle;
727
_cPos.getRotation().getValue(axis,angle);
728
res = Py::asObject(new QuantityPy(new Quantity(Base::toDegrees(angle),Unit::Angle)));
731
else if (p == ".Base.x") {
732
res = Py::asObject(new QuantityPy(new Quantity(_cPos.getPosition().x,Unit::Length)));
735
else if (p == ".Base.y") {
736
res = Py::asObject(new QuantityPy(new Quantity(_cPos.getPosition().y,Unit::Length)));
739
else if (p == ".Base.z") {
740
res = Py::asObject(new QuantityPy(new Quantity(_cPos.getPosition().z,Unit::Length)));
743
else if (p == ".Rotation.Axis.x") {
744
res = Py::Float(getAxis(_cPos).x);
747
else if (p == ".Rotation.Axis.y") {
748
res = Py::Float(getAxis(_cPos).y);
751
else if (p == ".Rotation.Axis.z") {
752
res = Py::Float(getAxis(_cPos).z);
755
else if (p == ".Rotation.Yaw") {
756
res = Py::Float(getYawPitchRoll(_cPos).x);
759
else if (p == ".Rotation.Pitch") {
760
res = Py::Float(getYawPitchRoll(_cPos).y);
763
else if (p == ".Rotation.Roll") {
764
res = Py::Float(getYawPitchRoll(_cPos).z);
771
PyObject *PropertyPlacement::getPyObject()
773
return new Base::PlacementPy(new Base::Placement(_cPos));
776
void PropertyPlacement::setPyObject(PyObject *value)
778
if (PyObject_TypeCheck(value, &(Base::MatrixPy::Type))) {
779
Base::MatrixPy *pcObject = static_cast<Base::MatrixPy*>(value);
780
Base::Matrix4D mat = pcObject->value();
785
else if (PyObject_TypeCheck(value, &(Base::PlacementPy::Type))) {
786
setValue(*static_cast<Base::PlacementPy*>(value)->getPlacementPtr());
789
std::string error = std::string("type must be 'Matrix' or 'Placement', not ");
790
error += value->ob_type->tp_name;
791
throw Base::TypeError(error);
795
void PropertyPlacement::Save (Base::Writer &writer) const
797
writer.Stream() << writer.ind() << "<PropertyPlacement";
798
writer.Stream() << " Px=\"" << _cPos.getPosition().x
799
<< "\" Py=\"" << _cPos.getPosition().y
800
<< "\" Pz=\"" << _cPos.getPosition().z << "\"";
802
writer.Stream() << " Q0=\"" << _cPos.getRotation()[0]
803
<< "\" Q1=\"" << _cPos.getRotation()[1]
804
<< "\" Q2=\"" << _cPos.getRotation()[2]
805
<< "\" Q3=\"" << _cPos.getRotation()[3] << "\"";
808
_cPos.getRotation().getRawValue(axis, rfAngle);
809
writer.Stream() << " A=\"" << rfAngle
810
<< "\" Ox=\"" << axis.x
811
<< "\" Oy=\"" << axis.y
812
<< "\" Oz=\"" << axis.z << "\"";
813
writer.Stream() <<"/>" << endl;
816
void PropertyPlacement::Restore(Base::XMLReader &reader)
819
reader.readElement("PropertyPlacement");
820
// get the value of my Attribute
823
if (reader.hasAttribute("A")) {
824
_cPos = Base::Placement(Vector3d(reader.getAttributeAsFloat("Px"),
825
reader.getAttributeAsFloat("Py"),
826
reader.getAttributeAsFloat("Pz")),
827
Rotation(Vector3d(reader.getAttributeAsFloat("Ox"),
828
reader.getAttributeAsFloat("Oy"),
829
reader.getAttributeAsFloat("Oz")),
830
reader.getAttributeAsFloat("A")));
833
_cPos = Base::Placement(Vector3d(reader.getAttributeAsFloat("Px"),
834
reader.getAttributeAsFloat("Py"),
835
reader.getAttributeAsFloat("Pz")),
836
Rotation(reader.getAttributeAsFloat("Q0"),
837
reader.getAttributeAsFloat("Q1"),
838
reader.getAttributeAsFloat("Q2"),
839
reader.getAttributeAsFloat("Q3")));
846
Property *PropertyPlacement::Copy() const
848
PropertyPlacement *p= new PropertyPlacement();
853
void PropertyPlacement::Paste(const Property &from)
856
_cPos = dynamic_cast<const PropertyPlacement&>(from)._cPos;
861
//**************************************************************************
862
// PropertyPlacementList
863
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
865
TYPESYSTEM_SOURCE(App::PropertyPlacementList , App::PropertyLists)
867
//**************************************************************************
868
// Construction/Destruction
870
PropertyPlacementList::PropertyPlacementList() = default;
872
PropertyPlacementList::~PropertyPlacementList() = default;
874
//**************************************************************************
875
// Base class implementer
877
PyObject *PropertyPlacementList::getPyObject()
879
PyObject* list = PyList_New( getSize() );
881
for (int i = 0;i<getSize(); i++)
882
PyList_SetItem( list, i, new Base::PlacementPy(new Base::Placement(_lValueList[i])));
887
Base::Placement PropertyPlacementList::getPyValue(PyObject *item) const {
888
PropertyPlacement val;
889
val.setPyObject( item );
890
return val.getValue();
893
void PropertyPlacementList::Save (Base::Writer &writer) const
895
if (!writer.isForceXML()) {
896
writer.Stream() << writer.ind() << "<PlacementList file=\"" << writer.addFile(getName(), this) << "\"/>" << std::endl;
900
void PropertyPlacementList::Restore(Base::XMLReader &reader)
902
reader.readElement("PlacementList");
903
std::string file (reader.getAttribute("file") );
906
// initiate a file read
907
reader.addFile(file.c_str(),this);
911
void PropertyPlacementList::SaveDocFile (Base::Writer &writer) const
913
Base::OutputStream str(writer.Stream());
914
uint32_t uCt = (uint32_t)getSize();
916
if (!isSinglePrecision()) {
917
for (const auto & it : _lValueList) {
918
str << it.getPosition().x << it.getPosition().y << it.getPosition().z
919
<< it.getRotation()[0] << it.getRotation()[1] << it.getRotation()[2] << it.getRotation()[3] ;
923
for (const auto & it : _lValueList) {
924
float x = (float)it.getPosition().x;
925
float y = (float)it.getPosition().y;
926
float z = (float)it.getPosition().z;
927
float q0 = (float)it.getRotation()[0];
928
float q1 = (float)it.getRotation()[1];
929
float q2 = (float)it.getRotation()[2];
930
float q3 = (float)it.getRotation()[3];
931
str << x << y << z << q0 << q1 << q2 << q3;
936
void PropertyPlacementList::RestoreDocFile(Base::Reader &reader)
938
Base::InputStream str(reader);
941
std::vector<Base::Placement> values(uCt);
942
if (!isSinglePrecision()) {
943
for (auto & it : values) {
945
double q0, q1, q2, q3;
946
str >> pos.x >> pos.y >> pos.z >> q0 >> q1 >> q2 >> q3;
947
Base::Rotation rot(q0,q1,q2,q3);
953
float x,y,z,q0,q1,q2,q3;
954
for (auto & it : values) {
955
str >> x >> y >> z >> q0 >> q1 >> q2 >> q3;
956
Base::Vector3d pos(x, y, z);
957
Base::Rotation rot(q0,q1,q2,q3);
965
Property *PropertyPlacementList::Copy() const
967
PropertyPlacementList *p= new PropertyPlacementList();
968
p->_lValueList = _lValueList;
972
void PropertyPlacementList::Paste(const Property &from)
974
setValues(dynamic_cast<const PropertyPlacementList&>(from)._lValueList);
977
unsigned int PropertyPlacementList::getMemSize () const
979
return static_cast<unsigned int>(_lValueList.size() * sizeof(Base::Vector3d));
985
//**************************************************************************
986
//**************************************************************************
988
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
990
TYPESYSTEM_SOURCE(App::PropertyPlacementLink , App::PropertyLink)
992
//**************************************************************************
993
// Construction/Destruction
996
PropertyPlacementLink::PropertyPlacementLink() = default;
999
PropertyPlacementLink::~PropertyPlacementLink() = default;
1001
App::Placement * PropertyPlacementLink::getPlacementObject() const
1003
if (_pcLink->isDerivedFrom<App::Placement>())
1004
return dynamic_cast<App::Placement*>(_pcLink);
1010
//**************************************************************************
1011
// Base class implementer
1013
Property *PropertyPlacementLink::Copy() const
1015
PropertyPlacementLink *p= new PropertyPlacementLink();
1016
p->_pcLink = _pcLink;
1020
void PropertyPlacementLink::Paste(const Property &from)
1023
_pcLink = dynamic_cast<const PropertyPlacementLink&>(from)._pcLink;
1027
//**************************************************************************
1028
//**************************************************************************
1030
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1032
TYPESYSTEM_SOURCE(App::PropertyRotation , App::Property)
1034
PropertyRotation::PropertyRotation() = default;
1037
PropertyRotation::~PropertyRotation() = default;
1039
void PropertyRotation::setValue(const Base::Rotation &rot)
1046
bool PropertyRotation::setValueIfChanged(const Base::Rotation &rot, double atol)
1048
if (_rot.isSame(rot, atol)) {
1057
const Base::Rotation & PropertyRotation::getValue() const
1062
void PropertyRotation::getPaths(std::vector<ObjectIdentifier> &paths) const
1064
paths.push_back(ObjectIdentifier(*this)
1065
<< ObjectIdentifier::SimpleComponent(ObjectIdentifier::String("Angle")));
1066
paths.push_back(ObjectIdentifier(*this)
1067
<< ObjectIdentifier::SimpleComponent(ObjectIdentifier::String("Axis"))
1068
<< ObjectIdentifier::SimpleComponent(ObjectIdentifier::String("x")));
1069
paths.push_back(ObjectIdentifier(*this)
1070
<< ObjectIdentifier::SimpleComponent(ObjectIdentifier::String("Axis"))
1071
<< ObjectIdentifier::SimpleComponent(ObjectIdentifier::String("y")));
1072
paths.push_back(ObjectIdentifier(*this)
1073
<< ObjectIdentifier::SimpleComponent(ObjectIdentifier::String("Axis"))
1074
<< ObjectIdentifier::SimpleComponent(ObjectIdentifier::String("z")));
1077
void PropertyRotation::setPathValue(const ObjectIdentifier &path, const boost::any &value)
1079
auto updateAxis = [=](int index, double coord) {
1080
Base::Vector3d axis;
1082
_rot.getRawValue(axis, angle);
1084
axis[index] = coord;
1085
setValue(Base::Rotation{axis, angle});
1088
std::string subpath = path.getSubPathStr();
1089
if (subpath == ".Angle") {
1090
double avalue = toDouble(value);
1091
Property::setPathValue(path, Base::toRadians(avalue));
1093
else if (subpath == ".Axis.x") {
1094
updateAxis(0, toDouble(value));
1096
else if (subpath == ".Axis.y") {
1097
updateAxis(1, toDouble(value));
1099
else if (subpath == ".Axis.z") {
1100
updateAxis(2, toDouble(value));
1103
Property::setPathValue(path, value);
1107
const boost::any PropertyRotation::getPathValue(const ObjectIdentifier &path) const
1109
auto getAxis = [](const Base::Rotation& rot) {
1110
Base::Vector3d axis;
1112
rot.getRawValue(axis, angle);
1115
std::string p = path.getSubPathStr();
1117
if (p == ".Angle") {
1118
// Convert angle to degrees
1119
return Base::Quantity(Base::toDegrees(boost::any_cast<double>(Property::getPathValue(path))), Unit::Angle);
1121
else if (p == ".Axis.x") {
1122
return getAxis(_rot).x;
1124
else if (p == ".Axis.y") {
1125
return getAxis(_rot).y;
1127
else if (p == ".Axis.z") {
1128
return getAxis(_rot).z;
1131
return Property::getPathValue(path);
1135
bool PropertyRotation::getPyPathValue(const ObjectIdentifier &path, Py::Object &res) const
1137
auto getAxis = [](const Base::Rotation& rot) {
1138
Base::Vector3d axis;
1140
rot.getRawValue(axis, angle);
1144
std::string p = path.getSubPathStr();
1145
if (p == ".Angle") {
1146
Base::Vector3d axis; double angle;
1147
_rot.getValue(axis,angle);
1148
res = Py::asObject(new QuantityPy(new Quantity(Base::toDegrees(angle),Unit::Angle)));
1151
else if (p == ".Axis.x") {
1152
res = Py::Float(getAxis(_rot).x);
1155
else if (p == ".Axis.y") {
1156
res = Py::Float(getAxis(_rot).y);
1159
else if (p == ".Axis.z") {
1160
res = Py::Float(getAxis(_rot).z);
1167
PyObject *PropertyRotation::getPyObject()
1169
return new Base::RotationPy(new Base::Rotation(_rot));
1172
void PropertyRotation::setPyObject(PyObject *value)
1174
if (PyObject_TypeCheck(value, &(Base::MatrixPy::Type))) {
1175
Base::MatrixPy *object = static_cast<Base::MatrixPy*>(value);
1176
Base::Matrix4D mat = object->value();
1181
else if (PyObject_TypeCheck(value, &(Base::RotationPy::Type))) {
1182
setValue(*static_cast<Base::RotationPy*>(value)->getRotationPtr());
1185
std::string error = std::string("type must be 'Matrix' or 'Rotation', not ");
1186
error += value->ob_type->tp_name;
1187
throw Base::TypeError(error);
1191
void PropertyRotation::Save (Base::Writer &writer) const
1195
_rot.getRawValue(axis, rfAngle);
1197
writer.Stream() << writer.ind() << "<PropertyRotation";
1198
writer.Stream() << " A=\"" << rfAngle << "\""
1199
<< " Ox=\"" << axis.x << "\""
1200
<< " Oy=\"" << axis.y << "\""
1201
<< " Oz=\"" << axis.z << "\""
1205
void PropertyRotation::Restore(Base::XMLReader &reader)
1207
reader.readElement("PropertyRotation");
1210
_rot = Rotation(Vector3d(reader.getAttributeAsFloat("Ox"),
1211
reader.getAttributeAsFloat("Oy"),
1212
reader.getAttributeAsFloat("Oz")),
1213
reader.getAttributeAsFloat("A"));
1217
Property *PropertyRotation::Copy() const
1219
PropertyRotation *p = new PropertyRotation();
1224
void PropertyRotation::Paste(const Property &from)
1227
_rot = dynamic_cast<const PropertyRotation&>(from)._rot;
1231
// ------------------------------------------------------------
1233
TYPESYSTEM_SOURCE_ABSTRACT(App::PropertyGeometry , App::Property)
1235
PropertyGeometry::PropertyGeometry() = default;
1237
PropertyGeometry::~PropertyGeometry() = default;
1239
// ------------------------------------------------------------
1241
TYPESYSTEM_SOURCE_ABSTRACT(App::PropertyComplexGeoData , App::PropertyGeometry)
1243
PropertyComplexGeoData::PropertyComplexGeoData() = default;
1245
PropertyComplexGeoData::~PropertyComplexGeoData() = default;
1247
std::string PropertyComplexGeoData::getElementMapVersion(bool) const {
1248
auto data = getComplexData();
1250
return std::string();
1251
auto owner = Base::freecad_dynamic_cast<DocumentObject>(getContainer());
1252
std::ostringstream ss;
1253
if(owner && owner->getDocument()
1254
&& owner->getDocument()->getStringHasher()==data->Hasher)
1258
ss << data->getElementMapVersion();
1262
bool PropertyComplexGeoData::checkElementMapVersion(const char * ver) const
1264
auto data = getComplexData();
1267
auto owner = Base::freecad_dynamic_cast<DocumentObject>(getContainer());
1268
std::ostringstream ss;
1270
if(owner && owner->getDocument()
1271
&& owner->getDocument()->getStringHasher() == data->Hasher)
1275
if (!boost::starts_with(ver, prefix))
1277
return data->checkElementMapVersion(ver+2);
1281
void PropertyComplexGeoData::afterRestore()
1283
auto data = getComplexData();
1284
if (data && data->isRestoreFailed()) {
1285
data->resetRestoreFailure();
1286
auto owner = Base::freecad_dynamic_cast<DocumentObject>(getContainer());
1288
owner->getDocument() &&
1289
!owner->getDocument()->testStatus(App::Document::PartialDoc)) {
1290
owner->getDocument()->addRecomputeObject(owner);
1293
PropertyGeometry::afterRestore();