src/document.cpp

changeset 222
72b456f2f3c2
parent 217
6d95c1a41e6e
child 223
ce81db996275
equal deleted inserted replaced
221:e28f89b8ccdf 222:72b456f2f3c2
68 // Then round the coordinates to integer precision... 68 // Then round the coordinates to integer precision...
69 this->worldPosition = glm::round(*this->worldPosition); 69 this->worldPosition = glm::round(*this->worldPosition);
70 // And finally transform it back to grid coordinates by transforming it with the 70 // And finally transform it back to grid coordinates by transforming it with the
71 // grid matrix. 71 // grid matrix.
72 this->worldPosition = this->gridMatrix * glm::vec4{*this->worldPosition, 1}; 72 this->worldPosition = this->gridMatrix * glm::vec4{*this->worldPosition, 1};
73 } 73 this->polygon.back() = *this->worldPosition;
74 this->updatePreviewPolygon(); 74 }
75 } 75 }
76 76
77 static QVector<QPointF> convertWorldPointsToScreenPoints( 77 static QVector<QPointF> convertWorldPointsToScreenPoints(
78 const std::vector<glm::vec3> &worldPoints, 78 const std::vector<glm::vec3> &worldPoints,
79 const PartRenderer* renderer) 79 const PartRenderer* renderer)
115 QPainter* painter, 115 QPainter* painter,
116 const std::vector<glm::vec3> &points, 116 const std::vector<glm::vec3> &points,
117 const PartRenderer* renderer) 117 const PartRenderer* renderer)
118 { 118 {
119 painter->drawPolygon(QPolygonF{convertWorldPointsToScreenPoints(points, renderer)}); 119 painter->drawPolygon(QPolygonF{convertWorldPointsToScreenPoints(points, renderer)});
120 }
121
122 static opt<std::vector<glm::vec3>> modelActionPoints(const ModelAction& action)
123 {
124 opt<std::vector<glm::vec3>> result;
125 if (const AppendToModel* append = std::get_if<AppendToModel>(&action)) {
126 const ModelElement& newElement = append->newElement;
127 if (const LineSegment* seg = std::get_if<Colored<LineSegment>>(&newElement)) {
128 result = {seg->p1, seg->p2};
129 }
130 else if (const Triangle* tri = std::get_if<Colored<Triangle>>(&newElement)) {
131 result = {tri->p1, tri->p2, tri->p3};
132 }
133 else if (const Quadrilateral* quad = std::get_if<Colored<Quadrilateral>>(&newElement)) {
134 result = {quad->p1, quad->p2, quad->p3, quad->p4};
135 }
136 }
137 return result;
120 } 138 }
121 139
122 void EditTools::overpaint(QPainter* painter) 140 void EditTools::overpaint(QPainter* painter)
123 { 141 {
124 struct Pens 142 struct Pens
149 const Pens& pens = (this->renderer->isDark() ? darkPens : brightPens); 167 const Pens& pens = (this->renderer->isDark() ? darkPens : brightPens);
150 switch(this->mode) { 168 switch(this->mode) {
151 case SelectMode: 169 case SelectMode:
152 break; 170 break;
153 case DrawMode: 171 case DrawMode:
154 { 172 painter->setPen(this->isconcave ? pens.badPolygonPen : pens.polygonPen);
155 painter->setPen(this->isconcave ? pens.badPolygonPen : pens.polygonPen); 173 for (const ModelAction& action : this->actions()) {
156 if (this->previewPolygon.size() > 2 and not this->isconcave) 174 const opt<std::vector<glm::vec3>> points = modelActionPoints(action);
157 { 175 if (points.has_value()) {
158 if (worldPolygonWinding(this->previewPolygon, this->renderer) == Winding::Clockwise) { 176 if (worldPolygonWinding(*points, this->renderer) == Winding::Clockwise) {
159 painter->setBrush(pens.greenPolygonBrush); 177 painter->setBrush(pens.greenPolygonBrush);
160 } 178 }
161 else { 179 else {
162 painter->setBrush(pens.redPolygonBrush); 180 painter->setBrush(pens.redPolygonBrush);
163 } 181 }
164 drawWorldPolygon(painter, this->previewPolygon, this->renderer); 182 drawWorldPolygon(painter, *points, this->renderer);
165 } 183 }
166 else { 184 }
167 drawWorldPolyline(painter, this->previewPolygon, this->renderer); 185 //drawWorldPolyline(painter, this->previewPolygon, this->renderer);
168 } 186 painter->setBrush(pens.pointBrush);
169 painter->setBrush(pens.pointBrush); 187 painter->setPen(pens.pointPen);
170 painter->setPen(pens.pointPen); 188 for (const glm::vec3& point : this->polygon) {
171 for (const glm::vec3& point : this->polygon) { 189 drawWorldPoint(painter, point, this->renderer);
172 drawWorldPoint(painter, point, this->renderer);
173 }
174 } 190 }
175 break; 191 break;
176 } 192 }
177 if (this->worldPosition.has_value()) 193 if (this->worldPosition.has_value())
178 { 194 {
185 } 201 }
186 } 202 }
187 203
188 void EditTools::updatePreviewPolygon() 204 void EditTools::updatePreviewPolygon()
189 { 205 {
190 this->previewPolygon = this->polygon; 206 if (this->polygon.size() > 2) {
191 if (this->worldPosition.has_value()) { 207 this->isconcave = not isConvex(this->polygon);
192 this->previewPolygon.resize(this->polygon.size() + 1);
193 this->previewPolygon.back() = *this->worldPosition;
194 }
195 if (this->previewPolygon.size() > 2)
196 {
197 this->isconcave = not isConvex(this->previewPolygon);
198 } 208 }
199 } 209 }
200 210
201 void EditTools::removeLastPoint() 211 void EditTools::removeLastPoint()
202 { 212 {
203 if (this->polygon.size() > 0) 213 if (this->polygon.size() > 1) {
204 {
205 this->polygon.erase(this->polygon.end() - 1); 214 this->polygon.erase(this->polygon.end() - 1);
206 this->updatePreviewPolygon(); 215 }
207 } 216 }
208 } 217
209 218 template<typename T>
210 bool isCloseToExistingPoints(const std::vector<glm::vec3>& points, const glm::vec3 &pos) 219 bool isCloseToExistingPoints(T begin, T end, const glm::vec3 &pos)
211 { 220 {
212 return any(points, std::bind(isclose, std::placeholders::_1, pos)); 221 return std::any_of(begin, end, [&pos](const glm::vec3& p){
222 return isclose(pos, p);
223 });
213 } 224 }
214 225
215 EditingMode EditTools::currentEditingMode() const 226 EditingMode EditTools::currentEditingMode() const
216 { 227 {
217 return this->mode; 228 return this->mode;
226 Q_EMIT this->select({highlighted}, false); 237 Q_EMIT this->select({highlighted}, false);
227 } 238 }
228 break; 239 break;
229 case DrawMode: 240 case DrawMode:
230 if (event->button() == Qt::LeftButton and this->worldPosition.has_value()) { 241 if (event->button() == Qt::LeftButton and this->worldPosition.has_value()) {
231 if (isCloseToExistingPoints(this->polygon, *this->worldPosition)) { 242 if (isCloseToExistingPoints(this->polygon.begin(), this->polygon.end() - 1, *this->worldPosition)) {
232 this->closeShape(); 243 this->closeShape();
233 } 244 }
234 else { 245 else {
235 this->polygon.push_back(*this->worldPosition); 246 this->polygon.push_back(*this->worldPosition);
236 this->updatePreviewPolygon(); 247 this->updatePreviewPolygon();
237 } 248 }
238 } 249 }
239 else if (true 250 else if (true
240 and event->button() == Qt::RightButton 251 and event->button() == Qt::RightButton
241 and this->polygon.size() > 0 252 and this->polygon.size() > 1
242 ) { 253 ) {
243 this->polygon.erase(this->polygon.end() - 1); 254 this->removeLastPoint();
244 updatePreviewPolygon(); 255 updatePreviewPolygon();
245 } 256 }
246 break; 257 break;
247 } 258 }
248 } 259 }
249 260
250 void EditTools::closeShape() 261 const std::vector<ModelAction> EditTools::actions() const
251 { 262 {
263 std::vector<ModelAction> result;
252 if (this->polygon.size() >= 2 and this->polygon.size() <= 4) { 264 if (this->polygon.size() >= 2 and this->polygon.size() <= 4) {
253 switch (this->polygon.size()) { 265 switch (this->polygon.size()) {
254 case 2: 266 case 2:
255 Q_EMIT this->modelAction(AppendToModel{ 267 result.push_back(AppendToModel{
256 .newElement = Colored<LineSegment>{ 268 .newElement = Colored<LineSegment>{
257 LineSegment{ 269 LineSegment{
258 .p1 = this->polygon[0], 270 .p1 = this->polygon[0],
259 .p2 = this->polygon[1], 271 .p2 = this->polygon[1],
260 }, 272 },
261 EDGE_COLOR, 273 EDGE_COLOR,
262 } 274 }
263 }); 275 });
264 break; 276 break;
265 case 3: 277 case 3:
266 Q_EMIT this->modelAction(AppendToModel{ 278 result.push_back(AppendToModel{
267 .newElement = Colored<Triangle>{ 279 .newElement = Colored<Triangle>{
268 Triangle{ 280 Triangle{
269 .p1 = this->polygon[0], 281 .p1 = this->polygon[0],
270 .p2 = this->polygon[1], 282 .p2 = this->polygon[1],
271 .p3 = this->polygon[2], 283 .p3 = this->polygon[2],
273 MAIN_COLOR, 285 MAIN_COLOR,
274 } 286 }
275 }); 287 });
276 break; 288 break;
277 case 4: 289 case 4:
278 Q_EMIT this->modelAction(AppendToModel{ 290 result.push_back(AppendToModel{
279 .newElement = Colored<Quadrilateral>{ 291 .newElement = Colored<Quadrilateral>{
280 Quadrilateral{ 292 Quadrilateral{
281 .p1 = this->polygon[0], 293 .p1 = this->polygon[0],
282 .p2 = this->polygon[1], 294 .p2 = this->polygon[1],
283 .p3 = this->polygon[2], 295 .p3 = this->polygon[2],
287 } 299 }
288 }); 300 });
289 break; 301 break;
290 } 302 }
291 } 303 }
304 return result;
305 }
306
307 void EditTools::closeShape()
308 {
309 for (const ModelAction& action : this->actions()) {
310 Q_EMIT this->modelAction(action);
311 }
292 this->polygon.clear(); 312 this->polygon.clear();
293 this->updatePreviewPolygon(); 313 this->updatePreviewPolygon();
294 } 314 }

mercurial