mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-14 03:14:23 +00:00
ifcviewer-full: length tool (2/3/4+ point distance, angle, polygon area)
ViewportWindow trades the area_tool_active_ bool for an enum ToolMode
{None, Area, Length}; the existing surfacePickedInTool signal carries
both, the app dispatches on toolMode(). Esc exits any active tool;
Backspace/Delete in length mode emits toolBackspacePressed which the
length tool uses to remove the last point.
LengthMeasurement collects clicked world-space points and adapts the
readout: 2pt → distance + axis-aligned ΔX/ΔY/ΔZ, 3pt → angle at the
middle vertex + triangle area, 4+pt → best-fit-plane PCA + shoelace
when planar (RMS plane distance / bbox diag < 1e-3) else fan
triangulation, with the chosen method labelled in the readout. Per-
segment lengths float at each midpoint.
OverlayRenderer grows three new pipelines to support this:
- point sprite shader: gl_PointCoord-based outlined disc with
fwidth-smoothed inner/stroke bands, a single draw call.
- line shader: CPU-expand each segment to 6 verts carrying both
endpoints + (side, along) corner index; vertex shader computes
the screen-space perpendicular and offsets accordingly. Real
outlined lines independent of the driver's glLineWidth clamp.
- screen-space rect shader: HUD + label backgrounds drawn as raw
GL quads in NDC. QPainter::fillRect on QOpenGLPaintDevice was
silently dropping fills across drivers; bypassing it entirely
via this shader makes backgrounds reliable. Cull-face is also
explicitly disabled here — GL_TRIANGLES respects it but the
line/point primitives don't, so this was the one path needing
the fix.
setOverlayLines / setOverlayPoints take an inner color, an outline
color, and an extra-pixels-per-side stroke amount. Lines + points
draw with GL_ALWAYS so measurement annotations stay visible through
geometry; highlight tris stay depth-aware (GL_LEQUAL) so area
shading still tints the surface in place.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -209,20 +209,44 @@ void MainWindow::setupUi() {
|
||||
connect(viewport_, &ViewportWindow::surfacePickedInTool, this,
|
||||
[this](int x, int y, int modifiers) {
|
||||
const bool alt = (modifiers & Qt::AltModifier) != 0;
|
||||
area_measurement_.onPick(*viewport_, x, y, alt);
|
||||
viewport_->setHudText(QString("Area: %1 m² (%2 tris)")
|
||||
.arg(area_measurement_.totalArea(), 0, 'f', 4)
|
||||
.arg(area_measurement_.triangleCount()));
|
||||
switch (viewport_->toolMode()) {
|
||||
case ViewportWindow::ToolMode::Area:
|
||||
area_measurement_.onPick(*viewport_, x, y, alt);
|
||||
viewport_->setHudText(QString("Area: %1 m² (%2 tris)")
|
||||
.arg(area_measurement_.totalArea(), 0, 'f', 4)
|
||||
.arg(area_measurement_.triangleCount()));
|
||||
break;
|
||||
case ViewportWindow::ToolMode::Length:
|
||||
length_measurement_.onPick(*viewport_, x, y, alt);
|
||||
break;
|
||||
case ViewportWindow::ToolMode::None:
|
||||
break;
|
||||
}
|
||||
});
|
||||
connect(viewport_, &ViewportWindow::areaToolToggled, this,
|
||||
[this](bool active) {
|
||||
connect(viewport_, &ViewportWindow::toolModeChanged, this,
|
||||
[this](ViewportWindow::ToolMode mode) {
|
||||
// Always clear both — the previous tool's accumulator/overlay
|
||||
// shouldn't bleed into the next one.
|
||||
area_measurement_.clear(*viewport_);
|
||||
if (active) {
|
||||
length_measurement_.clear(*viewport_);
|
||||
switch (mode) {
|
||||
case ViewportWindow::ToolMode::Area:
|
||||
viewport_->setHudText("Area: 0.0000 m² (0 tris)");
|
||||
status_label_->setText("Area tool: LMB add, Alt+LMB single tri, click again to remove, Esc exits");
|
||||
} else {
|
||||
break;
|
||||
case ViewportWindow::ToolMode::Length:
|
||||
viewport_->setHudText("Length tool: click first point");
|
||||
status_label_->setText("Length tool: LMB add point, Backspace remove last, Esc exits");
|
||||
break;
|
||||
case ViewportWindow::ToolMode::None:
|
||||
viewport_->setHudText(QString());
|
||||
status_label_->setText("Ready");
|
||||
break;
|
||||
}
|
||||
});
|
||||
connect(viewport_, &ViewportWindow::toolBackspacePressed, this, [this]() {
|
||||
if (viewport_->toolMode() == ViewportWindow::ToolMode::Length) {
|
||||
length_measurement_.removeLastPoint(*viewport_);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -305,6 +329,9 @@ void MainWindow::setupMenus() {
|
||||
view_menu->addAction("&Measure Area", this, [this]() {
|
||||
viewport_->toggleAreaTool();
|
||||
}, QKeySequence("Ctrl+Shift+A"));
|
||||
view_menu->addAction("Measure &Length", this, [this]() {
|
||||
viewport_->toggleLengthTool();
|
||||
}, QKeySequence("Ctrl+Shift+L"));
|
||||
view_menu->addSeparator();
|
||||
view_menu->addAction("Set &Home View", this, &MainWindow::onSetHomeView);
|
||||
view_menu->addAction("&Go to Home View", this, &MainWindow::onGoHomeView);
|
||||
|
||||
Reference in New Issue
Block a user