-
Notifications
You must be signed in to change notification settings - Fork 10
Expand file tree
/
Copy pathGeometryPropertyBuilder.h
More file actions
176 lines (160 loc) · 6.65 KB
/
GeometryPropertyBuilder.h
File metadata and controls
176 lines (160 loc) · 6.65 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
#pragma once
#include "GeometryProcessor.h"
#include "GeometryTypes.h"
#include "OccUtils.h"
#pragma once
namespace Geom
{
using namespace PPP;
/// \ingroup Geom
/**
* generate geometrical properties for meta data writting, for downstream processors
*/
class GeometryPropertyBuilder : public GeometryProcessor
{
TYPESYSTEM_HEADER();
private:
VectorType<GeometryProperty> myGeometryProperties;
VectorType<ItemIndexType> myGeometryUniqueIds;
double myMininumVolumeThreshold;
// thread_local ItemIndexType myCurrentIndex;
public:
GeometryPropertyBuilder()
{
// The parent's default ctor be called automatically (implicitely)
myCharacteristics["producedProperties"] = {"myGeometryProperties", "myGeometryUniqueIds"};
// std::cout << myCharacteristics;
}
/**
* for builders, it is essential to reserve itemCount to avoid resize
* in order to achieve lockfree parallel writing into std::vector
*/
virtual void prepareInput() override
{
GeometryProcessor::prepareInput();
myGeometryProperties.resize(myInputData->itemCount());
myGeometryUniqueIds.resize(myInputData->itemCount());
myMininumVolumeThreshold = 1; // todo: length unit mm, a part with volume of 1 cubic mm is an error
}
virtual void prepareOutput() override
{
// volumeCheck();
// dump(dataStoragePath("gproperties_dump.json")); // debug dump
// report, save and display erroneous shape
if (myConfig.contains("output"))
{
auto file_name = dataStoragePath(parameter<std::string>("output"));
writeMetaData(file_name);
}
else
{
LOG_F(WARNING, "user must provided output filename for meta data");
}
myOutputData->emplace("myGeometryProperties", std::move(myGeometryProperties));
myOutputData->emplace("myGeometryUniqueIds", std::move(myGeometryUniqueIds));
}
virtual void processItem(const std::size_t index) override
{
const TopoDS_Shape& aShape = item(index);
myGeometryProperties[index] = OccUtils::geometryProperty(aShape); // no way for std::move, but obj is small
itemPropertyCheck(index);
myGeometryUniqueIds[index] = OccUtils::uniqueId(myGeometryProperties[index]);
}
protected:
void volumeCheck()
{
// max and min volume check!
double max_volume = 0;
double min_volume = 1e100; // unit is mm^3
double max_volume_threshold = 1e16; // todo: get from config parameter
for (size_t i = 0; i < myInputData->itemCount(); i++)
{
const auto& p = myGeometryProperties[i];
if (p.volume > max_volume and p.volume < max_volume_threshold)
max_volume = p.volume;
if (p.volume < min_volume and p.volume > myMininumVolumeThreshold)
min_volume = p.volume;
if (p.volume > max_volume_threshold)
LOG_F(ERROR, "maximum volume in solids surpass the threshold %f", max_volume_threshold);
}
}
/// suppress and dump solid if the volume is too small
void itemPropertyCheck(const std::size_t i)
{
const GeometryProperty& p = myGeometryProperties[i];
if (p.volume < myMininumVolumeThreshold)
{
if (not itemSuppressed(i)) // this can be run as a second time
{
LOG_F(ERROR, "item volume %f < threshold %f mm^3, so suppress item %lu", p.volume,
myMininumVolumeThreshold, i);
suppressItem(i, ShapeErrorType::VolumeTooSmall);
auto df = generateDumpName("dump_smallVolume", {i}) + ".brep";
OccUtils::saveShape({item(i)}, df);
}
}
}
/// this dump only geometry properties for debugging
void dump(const std::string file_name) const
{
std::ofstream o(file_name);
o << '[' << std::endl;
for (auto& p : myGeometryProperties)
{
o << std::setw(4);
json j = p;
o << j << ',' << std::endl;
}
o << ']';
// auto save and close the file
}
/// write meta data in json for solids extracted from input file
/// suppressed Item will not have meta data write out
/// if there is no name information, it is empty string or just sequence
/// if there is no coloar or material, write `null` in json file
void writeMetaData(const std::string file_name) const
{
std::ofstream o(file_name);
o << '[' << std::endl;
Quantity_Color defaultColor;
json jm, jc; // this will write null value in json file
for (ItemIndexType i = 0; i < itemCount(); i++)
{
if (not itemSuppressed(i))
{
const auto c = itemColor(i);
if (c)
{
jc = c.value();
// Quantity_Color qc = c.value();
// to_json(jc, qc); // why = operator does not work?
}
const auto m = itemMaterial(i);
if (m)
{
jm = m.value();
}
else
{
jm = "unknown"; // if no material information from input geometry
}
json j{{"property", myGeometryProperties[i]},
{"uniqueId", myGeometryUniqueIds[i]},
{"sequenceId", i}, // writing sequence, to check if this sequence keep in readback
{"color", jc},
{"material", jm},
{"name", itemName(i)},
{"suppressed", itemSuppressed(i)},
{"shapeError", itemError(i)}};
o << std::setw(4);
o << j;
if (i < itemCount() - 1)
o << ','; // python json module does not accept comma without further data after it
o << std::endl;
}
}
o << ']';
// auto save and close the file
}
};
} // namespace Geom