mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-17 05:52:33 +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:
@@ -21,6 +21,8 @@
|
||||
#define IFCVIEWER_FULL_MEASUREMENT_H
|
||||
|
||||
#include <cstddef>
|
||||
#include <QString>
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
@@ -105,4 +107,33 @@ private:
|
||||
double total_area_m2_ = 0.0;
|
||||
};
|
||||
|
||||
// Click-to-place length / angle / area measurement. Each pick appends a
|
||||
// world-space point. The readout adapts to the point count:
|
||||
//
|
||||
// 1 point → "click another point"
|
||||
// 2 points → straight-line distance plus axis-aligned ΔX/ΔY/ΔZ
|
||||
// 3 points → angle at the middle vertex plus the triangle's area
|
||||
// 4+ → polygon area: best-fit-plane shoelace if the points are
|
||||
// near-coplanar (RMS plane distance < 1e-3 of the bounding
|
||||
// box), else fan-triangulated from the first point
|
||||
//
|
||||
// Clicked points are pushed to the viewport overlay as small dots and
|
||||
// the connecting polyline; readouts go to the multi-line HUD.
|
||||
class LengthMeasurement {
|
||||
public:
|
||||
LengthMeasurement();
|
||||
|
||||
void onPick(ViewportWindow& vp, int x, int y, bool alt);
|
||||
void removeLastPoint(ViewportWindow& vp);
|
||||
void clear(ViewportWindow& vp);
|
||||
|
||||
size_t pointCount() const { return points_.size(); }
|
||||
|
||||
private:
|
||||
void rebuildOverlay(ViewportWindow& vp);
|
||||
QString formatReadout() const;
|
||||
|
||||
std::vector<std::array<float, 3>> points_;
|
||||
};
|
||||
|
||||
#endif // IFCVIEWER_FULL_MEASUREMENT_H
|
||||
|
||||
Reference in New Issue
Block a user