295 else { |
295 else { |
296 return glm::vec2{s2.x(), s2.y()}; |
296 return glm::vec2{s2.x(), s2.y()}; |
297 } |
297 } |
298 }; |
298 }; |
299 const glm::vec3 zvec = this->gridMatrix[2]; |
299 const glm::vec3 zvec = this->gridMatrix[2]; |
300 const glm::vec2 p1 = extremity(this->polygon[0] + zvec); |
300 { |
301 const glm::vec2 p2 = extremity(this->polygon[0] - zvec); |
301 const glm::vec2 p1 = extremity(this->polygon[0] + zvec); |
302 const glm::vec2 lateral = glm::normalize(glm::mat2{{0, 1}, {-1, 0}} * (p2 - p1)); |
302 const glm::vec2 p2 = extremity(this->polygon[0] - zvec); |
303 painter->setPen(QPen{Qt::white, 3}); |
303 const glm::vec2 lateral = glm::normalize(glm::mat2{{0, 1}, {-1, 0}} * (p2 - p1)); |
304 painter->drawLine(vecToQPoint(p1), vecToQPoint(p2)); |
304 painter->setPen(QPen{Qt::white, 3}); |
305 constexpr float notchsize = 40.0f; |
305 painter->drawLine(vecToQPoint(p1), vecToQPoint(p2)); |
306 for (int a = -30; a <= 30; ++a) { |
306 constexpr float notchsize = 40.0f; |
307 const glm::vec3 notch = this->polygon[0] + static_cast<float>(a) * zvec; |
307 for (int a = -30; a <= 30; ++a) { |
308 const QPointF s_notchcenter = this->renderer->modelToScreenCoordinates(notch); |
308 const glm::vec3 notch = this->polygon[0] + static_cast<float>(a) * zvec; |
309 const QPointF notch_s1 = s_notchcenter + notchsize * 0.5f * vecToQPoint(lateral); |
309 const QPointF s_notchcenter = this->renderer->modelToScreenCoordinates(notch); |
310 const QPointF notch_s2 = s_notchcenter - notchsize * 0.5f * vecToQPoint(lateral); |
310 const QPointF notch_s1 = s_notchcenter + notchsize * 0.5f * vecToQPoint(lateral); |
311 painter->drawLine(notch_s1, notch_s2); |
311 const QPointF notch_s2 = s_notchcenter - notchsize * 0.5f * vecToQPoint(lateral); |
|
312 painter->drawLine(notch_s1, notch_s2); |
|
313 } |
|
314 } |
|
315 if (this->polygon.size() >= 3) { |
|
316 const opt<float> height = this->cylinderHeight(); |
|
317 if (height.has_value()) { |
|
318 const glm::vec3 heightvec = height.value_or(0) * zvec; |
|
319 const glm::vec3 p = this->polygon[1] + 0.5f * heightvec; |
|
320 QFont font{}; |
|
321 font.setBold(true); |
|
322 drawBorderedText(painter, this->renderer->modelToScreenCoordinates(p), font, QString::number(*height)); |
|
323 } |
312 } |
324 } |
313 } |
325 } |
314 } |
326 } |
315 |
327 |
316 void EditTools::removeLastPoint() |
328 void EditTools::removeLastPoint() |
339 std::size_t result = this->polygon.size(); |
351 std::size_t result = this->polygon.size(); |
340 if (this->isCloseToExistingPoints()) { |
352 if (this->isCloseToExistingPoints()) { |
341 result -= 1; |
353 result -= 1; |
342 } |
354 } |
343 return result; |
355 return result; |
|
356 } |
|
357 |
|
358 opt<float> EditTools::cylinderHeight() const |
|
359 { |
|
360 if (this->polygon.size() < 3) { |
|
361 return {}; |
|
362 } |
|
363 else { |
|
364 const Plane plane{ |
|
365 .normal = glm::normalize(this->renderer->cameraVector(this->localPosition)), |
|
366 .anchor = this->polygon[0], |
|
367 }; |
|
368 const opt<glm::vec3> p = this->renderer->screenToModelCoordinates(this->localPosition, plane); |
|
369 if (p.has_value()) { |
|
370 const glm::vec3 heightvec = glm::normalize(glm::vec3{gridMatrix[2]}); |
|
371 return std::round(glm::dot(*p - polygon[0], heightvec)); |
|
372 } |
|
373 else { |
|
374 return {}; |
|
375 } |
|
376 } |
344 } |
377 } |
345 |
378 |
346 EditingMode EditTools::currentEditingMode() const |
379 EditingMode EditTools::currentEditingMode() const |
347 { |
380 { |
348 return this->mode; |
381 return this->mode; |
447 |
480 |
448 |
481 |
449 const std::vector<ModelAction> EditTools::circleModeActions() const |
482 const std::vector<ModelAction> EditTools::circleModeActions() const |
450 { |
483 { |
451 std::vector<ModelAction> result; |
484 std::vector<ModelAction> result; |
452 if (this->numpoints == 3) { |
485 if (this->numpoints >= 2) { |
453 const glm::vec3 x = polygon[1] - polygon[0]; |
486 const glm::vec3 x = polygon[1] - polygon[0]; |
454 const opt<float> cyliheight = [&]() -> opt<float> { |
487 const opt<float> cyliheight = this->cylinderHeight().value_or(1); |
455 const Plane plane{ |
488 glm::mat4 transform{ |
456 .normal = glm::normalize(this->renderer->cameraVector(this->localPosition)), |
489 glm::vec4{x, 0}, |
457 .anchor = this->polygon[0], |
490 *cyliheight * this->gridMatrix[2], |
458 }; |
491 glm::vec4{glm::cross(glm::vec3{-this->gridMatrix[2]}, x), 0}, |
459 const opt<glm::vec3> p = this->renderer->screenToModelCoordinates(this->localPosition, plane); |
492 glm::vec4{this->polygon[0], 1}, |
460 if (p.has_value()) { |
493 }; |
461 const glm::vec3 heightvec = glm::normalize(glm::vec3{gridMatrix[2]}); |
494 Colored<CircularPrimitive> circ{ |
462 return std::round(glm::dot(*p - polygon[0], heightvec)); |
495 CircularPrimitive{ |
463 } |
496 .type = this->circleToolOptions.type, |
464 else { |
497 .fraction = this->circleToolOptions.fraction, |
465 return {}; |
498 .transformation = transform, |
466 } |
499 }, |
467 }(); |
500 MAIN_COLOR |
468 if (cyliheight.has_value()) { |
501 }; |
469 glm::mat4 transform{ |
502 result.push_back(AppendToModel{.newElement = circ}); |
470 glm::vec4{x, 0}, |
|
471 *cyliheight * this->gridMatrix[2], |
|
472 glm::vec4{glm::cross(glm::vec3{-this->gridMatrix[2]}, x), 0}, |
|
473 glm::vec4{this->polygon[0], 1}, |
|
474 }; |
|
475 Colored<CircularPrimitive> circ{ |
|
476 CircularPrimitive{ |
|
477 .type = this->circleToolOptions.type, |
|
478 .fraction = this->circleToolOptions.fraction, |
|
479 .transformation = transform, |
|
480 }, |
|
481 MAIN_COLOR |
|
482 }; |
|
483 result.push_back(AppendToModel{.newElement = circ}); |
|
484 } |
|
485 } |
503 } |
486 return result; |
504 return result; |
487 } |
505 } |
488 |
506 |
489 const std::vector<ModelAction> EditTools::drawModeActions() const |
507 const std::vector<ModelAction> EditTools::drawModeActions() const |