1
/***************************************************************************
2
* Copyright (c) 2023 WandererFan <wandererfan@gmail.com> *
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
***************************************************************************/
23
#include "PreCompiled.h"
25
#include <BRepBuilderAPI_Copy.hxx>
27
#include <Base/Console.h>
28
#include <Base/Reader.h>
29
#include <Base/Writer.h>
31
#include "TopoShapePy.h"
33
#include "PropertyTopoShapeList.h"
41
//**************************************************************************
42
// PropertyTopoShapeList
43
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
45
TYPESYSTEM_SOURCE(Part::PropertyTopoShapeList, App::PropertyLists)
47
//**************************************************************************
48
// Construction/Destruction
50
PropertyTopoShapeList::PropertyTopoShapeList() = default;
52
PropertyTopoShapeList::~PropertyTopoShapeList() = default;
54
void PropertyTopoShapeList::setSize(int newSize)
56
_lValueList.resize(newSize);
59
int PropertyTopoShapeList::getSize() const
61
return static_cast<int>(_lValueList.size());
64
// this version of setValue is for the ADD_PROPERTY_TYPE macro to use when creating a
65
// new PropertyTopoShapeList. In other list properties that use pointers (instead of
66
// references) a nullptr is passed to setValue to initialize the empty list, but we can
67
// not do that with references.
68
void PropertyTopoShapeList::setValue()
70
// aboutToSetValue() and hasSetValue() are called in clear() so don't need
75
void PropertyTopoShapeList::setValue(const TopoShape &ts)
78
_lValueList.resize(1);
83
void PropertyTopoShapeList::setValues(const std::vector<TopoShape>& lValue)
86
_lValueList.resize(lValue.size());
87
for (unsigned int i = 0; i < lValue.size(); i++) {
88
_lValueList[i] = lValue[i];
94
void PropertyTopoShapeList::clear()
98
_lValueList.resize(0);
103
// populate the lists with the TopoShapes that have now finished restoring
104
void PropertyTopoShapeList::afterRestore()
108
for (auto& entry : m_restorePointers) {
109
_lValueList.push_back(*entry);
113
m_restorePointers.clear();
114
App::PropertyLists::afterRestore();
117
PyObject *PropertyTopoShapeList::getPyObject()
120
for (int i = 0; i < getSize(); i++) {
121
list.append(Py::asObject(_lValueList[i].getPyObject()));
123
return Py::new_reference_to(list);
126
void PropertyTopoShapeList::setPyObject(PyObject *value)
128
if (PySequence_Check(value)) {
129
Py::Sequence sequence(value);
130
Py_ssize_t nSize = sequence.size();
131
std::vector<TopoShape> values;
132
values.resize(nSize);
134
for (Py_ssize_t i=0; i < nSize; ++i) {
135
Py::Object item = sequence.getItem(i);
136
if (!PyObject_TypeCheck(item.ptr(), &(TopoShapePy::Type))) {
137
std::string error = std::string("types in list must be 'Shape', not ");
138
error += item.ptr()->ob_type->tp_name;
139
throw Base::TypeError(error);
142
values[i] = *static_cast<TopoShapePy*>(item.ptr())->getTopoShapePtr();
146
else if (PyObject_TypeCheck(value, &(TopoShapePy::Type))) {
147
TopoShapePy *pcObject = static_cast<TopoShapePy*>(value);
148
setValue(*pcObject->getTopoShapePtr());
151
std::string error = std::string("type must be 'Shape' or list of 'Shape', not ");
152
error += value->ob_type->tp_name;
153
throw Base::TypeError(error);
157
void PropertyTopoShapeList::Save(Writer& writer) const
159
writer.Stream() << writer.ind() << "<ShapeList count=\"" << getSize() << "\">" << endl;
161
for (int i = 0; i < getSize(); i++) {
162
bool binary = writer.getMode("BinaryBrep");
163
writer.Stream() << writer.ind() << "<TopoShape";
164
if (!writer.isForceXML()) {
165
// See SaveDocFile(), RestoreDocFile()
166
// add a filename to the writer's list. Each file on the list is eventually
167
// processed by SaveDocFile().
168
std::string ext(".");
169
ext += std::to_string(i);
176
writer.Stream() << writer.ind() << " file=\""
177
<< writer.addFile(getFileName(ext.c_str()).c_str(), this) << "\"/>\n";
180
writer.Stream() << " binary=\"1\">\n";
181
_lValueList[i].exportBinary(writer.beginCharStream());
182
writer.endCharStream() << writer.ind() << "</TopoShape>\n";
185
writer.Stream() << " brep=\"1\">\n";
186
_lValueList[i].exportBrep(writer.beginCharStream() << '\n');
187
writer.endCharStream() << '\n' << writer.ind() << "</TopoShape>\n";
191
writer.Stream() << writer.ind() << "</ShapeList>" << endl;
194
void PropertyTopoShapeList::SaveDocFile(Base::Writer& writer) const
196
Base::FileInfo finfo(writer.ObjectName);
197
bool binary = finfo.hasExtension("bin");
198
int index = atoi(Base::FileInfo(finfo.fileNamePure()).extension().c_str());
199
if (index < 0 || index >= static_cast<int>(_lValueList.size())) {
203
const TopoShape& shape = _lValueList[index];
205
shape.exportBinary(writer.Stream());
208
shape.exportBrep(writer.Stream());
212
void PropertyTopoShapeList::Restore(Base::XMLReader& reader)
214
reader.readElement("ShapeList");
215
int count = reader.getAttributeAsInteger("count");
216
m_restorePointers.clear(); // just in case
217
m_restorePointers.reserve(count);
218
for (int i = 0; i < count; i++) {
219
auto newShape = std::make_shared<TopoShape>();
220
reader.readElement("TopoShape");
221
std::string file(reader.getAttribute("file"));
223
reader.addFile(file.c_str(), this);
225
else if (reader.hasAttribute("binary") && reader.getAttributeAsInteger("binary")) {
226
newShape->importBinary(reader.beginCharStream());
228
else if (reader.hasAttribute("brep") && reader.getAttributeAsInteger("brep")) {
229
newShape->importBrep(reader.beginCharStream());
231
m_restorePointers.push_back(newShape);
233
reader.readEndElement("ShapeList");
236
void PropertyTopoShapeList::RestoreDocFile(Base::Reader& reader)
238
Base::FileInfo finfo(reader.getFileName());
239
bool binary = finfo.hasExtension("bin");
240
int index = atoi(Base::FileInfo(finfo.fileNamePure()).extension().c_str());
241
if (index < 0 || index >= static_cast<int>(m_restorePointers.size())) {
245
m_restorePointers[index]->importBinary(reader);
248
m_restorePointers[index]->importBrep(reader);
252
App::Property *PropertyTopoShapeList::Copy() const
254
PropertyTopoShapeList *p = new PropertyTopoShapeList();
255
std::vector<TopoShape> copiedShapes;
256
for (auto& shape : _lValueList) {
257
BRepBuilderAPI_Copy copy(shape.getShape());
258
copiedShapes.emplace_back(copy.Shape());
260
p->setValues(copiedShapes);
264
void PropertyTopoShapeList::Paste(const Property &from)
266
const PropertyTopoShapeList& FromList = dynamic_cast<const PropertyTopoShapeList&>(from);
267
setValues(FromList._lValueList);
270
unsigned int PropertyTopoShapeList::getMemSize() const
272
int size = sizeof(PropertyTopoShapeList);
273
for (int i = 0; i < getSize(); i++)
274
size += _lValueList[i].getMemSize();