src/polygoncache.cpp

changeset 333
07e65a4c6611
parent 318
216f02b50b0a
child 338
719b909a7d2b
equal deleted inserted replaced
332:ae7f7fbb9cda 333:07e65a4c6611
1 #include "src/circularprimitive.h" 1 #include "src/circularprimitive.h"
2 #include "src/documentmanager.h" 2 #include "src/documentmanager.h"
3 #include "src/invert.h" 3 #include "src/invert.h"
4 #include "src/polygoncache.h" 4 #include "src/polygoncache.h"
5 #include "src/parser.h"
5 6
6 Model* resolve(const QString& name, const ModelId callingModelId, DocumentManager* documents) 7 Model* resolve(const QString& name, const ModelId callingModelId, DocumentManager* documents)
7 { 8 {
8 return documents->findDependencyByName(callingModelId, name); 9 return documents->findDependencyByName(callingModelId, name);
9 } 10 }
38 constexpr bool n_xor(bool a, Args&&... rest) 39 constexpr bool n_xor(bool a, Args&&... rest)
39 { 40 {
40 return a xor n_xor(rest...); 41 return a xor n_xor(rest...);
41 } 42 }
42 43
44 namespace {
45 struct GetPolygonsContext
46 {
47 bool invertnext = false;
48 ModelId modelId;
49 class DocumentManager* documents;
50 };
51 }
52
43 template<typename Fn, typename Fn2> 53 template<typename Fn, typename Fn2>
44 static void inlineSubfileReference( 54 static void inlineSubfileReference(
45 const PolygonCache::vector_type& polygons, 55 const PolygonCache::vector_type& polygons,
46 const Colored<SubfileReference>& ref, 56 const Colored<SubfileReference>& ref,
57 GetPolygonsContext* context,
47 Fn&& add, 58 Fn&& add,
48 Fn2&& reserve) 59 Fn2&& reserve)
49 { 60 {
50 const bool needInverting = 0 61 const bool needInverting = 0
51 ^ (glm::determinant(ref.transformation) < 0) 62 ^ (glm::determinant(ref.transformation) < 0)
52 ^ (ref.inverted); 63 ^ (context->invertnext);
53 reserve(polygons.size()); 64 reserve(polygons.size());
54 for (const PolygonElement& cacheElement : polygons) { 65 for (const PolygonElement& cacheElement : polygons) {
55 PolygonElement polygon = transformed(cacheElement, ref.transformation); 66 PolygonElement polygon = transformed(cacheElement, ref.transformation);
56 if (needInverting) { 67 if (needInverting) {
57 gl::invert(polygon); 68 gl::invert(polygon);
61 } 72 }
62 add(polygon); 73 add(polygon);
63 } 74 }
64 } 75 }
65 76
66 Model* findDependency(const SubfileReference& ref, GetPolygonsContext* context) 77 static Model* findDependency(const SubfileReference& ref, GetPolygonsContext* context)
67 { 78 {
68 return context->documents->findDependencyByName(context->modelId, ref.name); 79 return context->documents->findDependencyByName(context->modelId, ref.name);
69 } 80 }
70 81
71 template<typename Fn, typename Fn2> 82 template<typename Fn, typename Fn2>
72 static void collectPolygons( 83 static void collectPolygons(
73 const ModelElement& element, 84 const ParsedLine& element,
74 Winding& winding, 85 Winding& winding,
75 GetPolygonsContext* context, 86 GetPolygonsContext* context,
76 Fn&& add, 87 Fn&& add,
77 Fn2&& reserve) 88 Fn2&& reserve)
78 { 89 {
90 bool foundinvertnext = false;
79 std::visit<void>(overloaded{ 91 std::visit<void>(overloaded{
80 [&](const Colored<LineSegment>& edge) { 92 [&](const LineType0& line0) {
81 add({edge, edge.color}); 93 const QString text = line0.value.text.simplified();
94 if (text == QStringLiteral("BFC INVERTNEXT")) {
95 context->invertnext = true;
96 foundinvertnext = true;
97 }
98 else if (text == QStringLiteral("BFC CERTIFY CW")) {
99 winding = Clockwise;
100 }
101 else if (text == QStringLiteral("BFC CERTIFY CCW")) {
102 winding = Anticlockwise;
103 }
104 else if (text == QStringLiteral("BFC NOCERTIFY")) {
105 winding = NoWinding;
106 }
82 }, 107 },
83 [&](const Colored<Triangle>& triangle) { 108 [&](const LineType2& line2) {
84 add({triangle, triangle.color}); 109 add({line2.value, line2.value.color});
85 }, 110 },
86 [&](const Colored<Quadrilateral>& quad) { 111 [&](const LineType3& line3) {
87 add({quad, quad.color}); 112 add({line3.value, line3.value.color});
88 }, 113 },
89 [&](const Colored<ConditionalEdge>& cedge) { 114 [&](const LineType4& line4) {
90 add({cedge, cedge.color}); 115 add({line4.value, line4.value.color});
91 }, 116 },
92 [&add, context, &reserve](const Colored<SubfileReference>& ref) { 117 [&](const LineType5& line5) {
93 Model* const dependency = findDependency(ref, context); 118 add({line5.value, line5.value.color});
119 },
120 [&add, context, &reserve](const LineType1& line1) {
121 Model* const dependency = findDependency(line1.value, context);
94 if (PolygonCache* cache = (dependency != nullptr) 122 if (PolygonCache* cache = (dependency != nullptr)
95 ? findPolygonCacheForModel(dependency, context->documents) 123 ? findPolygonCacheForModel(dependency, context->documents)
96 : nullptr 124 : nullptr
97 ) { 125 ) {
98 recacheIfNeeded(cache, dependency, context->documents); 126 recacheIfNeeded(cache, dependency, context->documents);
99 inlineSubfileReference(cache->polygons, ref, add, reserve); 127 inlineSubfileReference(cache->polygons, line1.value, context, add, reserve);
100 } 128 }
101 }, 129 },
130 #if 0
102 [&add](const Colored<CircularPrimitive>& circ) { 131 [&add](const Colored<CircularPrimitive>& circ) {
103 rasterize(circ, [&](const PlainPolygonElement& polygon, ColorIndex color){ 132 rasterize(circ, [&](const PlainPolygonElement& polygon, ColorIndex color){
104 if (color == MAIN_COLOR) { 133 if (color == MAIN_COLOR) {
105 color = circ.color; 134 color = circ.color;
106 } 135 }
107 add(PolygonElement{polygon, color}); 136 add(PolygonElement{polygon, color});
108 }); 137 });
109 }, 138 },
110 [&winding](const Comment& comment) { 139 #endif
111 if (comment.text == QStringLiteral("BFC CERTIFY CW")) {
112 winding = Clockwise;
113 }
114 else if (comment.text == QStringLiteral("BFC CERTIFY CCW")) {
115 winding = Anticlockwise;
116 }
117 else if (comment.text == QStringLiteral("BFC NOCERTIFY")) {
118 winding = NoWinding;
119 }
120 },
121 [](const ModelElement&) {}
122 }, element); 140 }, element);
141 if (not foundinvertnext) {
142 context->invertnext = false;
143 }
123 } 144 }
124 145
125 static std::vector<WithId<PolygonElement>> inlinePolygons( 146 static std::vector<WithId<PolygonElement>> inlinePolygons(
126 const Model* model, 147 const Model* model,
127 GetPolygonsContext* context) 148 GetPolygonsContext* context)
128 { 149 {
129 Winding winding = NoWinding; 150 Winding winding = NoWinding;
130 std::vector<WithId<PolygonElement>> result; 151 std::vector<WithId<PolygonElement>> result;
131 for (std::size_t i = 0; i < model->size(); i += 1) 152 int i = 0;
132 { 153 const auto add = [&result, winding, i](const PolygonElement& poly){
133 const ModelElement& element = (*model)[i]; 154 result.push_back({poly, i});
134 const ElementId id = model->idAt(i); 155 if (winding == Winding::Clockwise) {
135 collectPolygons(element, winding, context, 156 gl::invert(result.back());
136 [&result, winding, id](const PolygonElement& poly){ 157 }
137 result.push_back({poly, id}); 158 };
138 if (winding == Winding::Clockwise) { 159 const auto reserve = [&result](std::size_t incomingsize){
139 gl::invert(result.back()); 160 reserveMore(result, incomingsize);
140 } 161 };
141 }, [&result](std::size_t incomingsize){ 162 for (const QString& line : model->toPlainText().split("\n")) {
142 reserveMore(result, incomingsize); 163 const opt<ParsedLine> parsedline = parse(line);
143 }); 164 if (parsedline.has_value()) {
165 collectPolygons(*parsedline, winding, context, add, reserve);
166 }
167 ++i;
144 } 168 }
145 return result; 169 return result;
146 } 170 }
147 171
148 void recacheIfNeeded(PolygonCache *cache, Model *model, DocumentManager *documents) 172 void recacheIfNeeded(PolygonCache *cache, Model *model, DocumentManager *documents)
151 { 175 {
152 cache->polygons.clear(); 176 cache->polygons.clear();
153 const std::optional<ModelId> modelId = documents->findIdForModel(model); 177 const std::optional<ModelId> modelId = documents->findIdForModel(model);
154 if (modelId.has_value()) 178 if (modelId.has_value())
155 { 179 {
156 GetPolygonsContext context{modelId.value(), documents}; 180 GetPolygonsContext context{
181 .invertnext = false,
182 .modelId = *modelId,
183 .documents = documents,
184 };
157 cache->polygons = inlinePolygons(model, &context); 185 cache->polygons = inlinePolygons(model, &context);
158 } 186 }
159 cache->needRecache = false; 187 cache->needRecache = false;
160 } 188 }
161 } 189 }

mercurial