Commit graph cad-editor/src/scene/tessellate.rs
Author SHA1 Message Date
Hakan Seven
048bb41aef feat(render): solid fill for PolyfaceMesh and PolygonMesh entities
PolyfaceMesh and PolygonMesh were wireframe-only. They now render with
the same flat-color solid fill as Face3D entities.

- Add fill_tris: Vec<[f32;3]> to TruckEntity and WireModel
- PolyfaceMesh: fan-triangulate each face into fill_tris
- PolygonMesh: triangulate each grid quad into fill_tris
- tessellate.rs Lines branch: apply world_offset to fill_tris
- Face3DGpu::from_wires: collect fill_tris from all wires in addition
  to Face3D key_vertices quads
- upload_face3d: pass all_wires so fill_tris are batched into one draw call
2026-05-06 23:24:26 +03:00
Hakan Seven
b83c982bc2 fix(scene): hatch pattern scale and per-entity annotative check
- Hatch pattern_scale multiplied by annotation_scale in model space so
  pattern density stays consistent when CANNOSCALE changes
- Annotative check now uses AcAnnoPO xdata (R2007+ marker) instead of
  relying solely on group-code-293 flag; falls back to is_annotative
  for files with no xdata (old DXF backward compat)
- acadrust patched to local path for is_annotative field

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-06 22:19:28 +03:00
Hakan
0e5dec0948 feat: annotation scale system (CANNOSCALE, PSLTSCALE, MultiLeader, Leader)
- Scale popup dropdown replaces cycle behavior; paper-space viewport scale
  editable when a viewport is active/selected
- CANNOSCALE persisted via DXF $USERR1 (read on open, write on save)
- PSLTSCALE: linetype dash lengths scaled by viewport anno_scale so dashes
  appear uniform physical size in paper space
- MultiLeader: arrow size, dogleg length, and text height scale with
  anno_scale; leader line paths (world coords) stay fixed
- Leader: arrow size and hookline length scale with anno_scale; also
  corrects world_offset subtraction that was previously deferred to the
  TruckObject::Lines path

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-06 17:50:46 +03:00
Hakan
534e4ff26b feat: implement Grippable and PropertyEditable traits for Solid3D, Region, and Body; add snap points and geometry properties 2026-05-06 10:00:37 +03:00
Hakan Seven
899b3f4796 feat: GPU scissor rect for paper-space viewport wires
Viewport-projected wires now clip at pixel level to their viewport boundary.

- WireModel.vp_scissor: Option<[f32; 4]> — paper-space bbox set on projection
- WireGpu.vp_scissor carries it through to the draw loop
- Pipeline.compute_wire_scissors() converts paper→NDC→pixel each frame
- render() calls set_scissor_rect() per wire, reset after viewport group
- INTEGRATION_GAPS.md: Viewport ⚠️ → ✅, all 51 gaps resolved

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-06 07:12:05 +03:00
Hakan Seven
27aca41dd1 feat: plinegen + SAB parsing for Solid3D/Region/Body
LwPolyline PLINEGEN=0 (DXF default): emit SegmentedLines with NaN
separators between vertex-to-vertex segments; wire_gpu resets
arc-length to 0 after each NaN so linetype pattern restarts per vertex.
PLINEGEN=1: existing Contour path unchanged (continuous pattern).
WireModel gains plinegen field propagated through tessellate pipeline.

Solid3D/Region/Body: call SabReader::read() when parse_sat() returns
None due to binary SAB format (DWG files / newer AutoCAD exports).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-06 06:55:28 +03:00
Hakan Seven
603d07412e refactor: replace angle calculations with radians for consistency 2026-05-03 21:58:38 +03:00
Hakan Seven
9b29db61d4 feat: apply OCS→WCS transform to Hatch wire outline boundary edges
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-02 20:24:38 +03:00
Hakan Seven
5a7ebbbb38 feat: add Node snap points to dimension defpoints
Dimension measurement origin points (first_point, second_point,
definition_point, angle_vertex, etc.) are now emitted as Node snap
hints so OSNAP Node mode can locate them precisely without relying on
the tessellated geometry wire alone.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-02 17:15:41 +03:00
Hakan Seven
000f74f951 feat: render CircularArc and EllipticArc hatch boundary edges
Hatch boundaries with arc or ellipse edges were silently dropped from
the wire outline, leaving gaps in the hatch contour. CircularArc and
EllipticArc boundary edges are now tessellated as polyline segments and
their centers are emitted as Center snap hints.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-02 17:15:02 +03:00
Hakan Seven
1a19a841e6 fix: correct polyline arc direction, text precision, Face3D edge color, buffer chunking
- fix: polyline arc center sign was inverted (- → +) causing arcs to render on the
  wrong side in LwPolyline and Polyline2D
- fix: store glyph strokes in local space with f64 origin so world_offset subtraction
  uses f64 precision; prevents blocky text at large UTM coordinates
- fix: Face3D fill darkened to 45% so edge wires are visually distinct from fill
- fix: wire batch vertex buffer chunked to 256 MB GPU limit (was panic on large files)
- fix: gpu_face3d_edges changed from Option<WireGpu> to Vec<WireGpu> to support chunks

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-29 20:58:44 +03:00
Hakan Seven
e191315713 fix: restore visibility for large-coordinate DXF files after world_offset regression
Three root causes caused all geometry and UCS arrows to disappear:

1. TruckObject::Lines and TruckObject::Text variants returned world-space
   f32 coordinates without applying world_offset, so fit_all() computed
   bounds spanning from local space to UTM world space (~4 M m), placing
   the camera impossibly far from all visible geometry.

2. Ray/XLine entities with unnormalized direction vectors (common in some
   DXF exporters) produced astronomically large far-point coordinates
   (up to 1e28) that overwhelmed the camera fit even after the offset fix.
   Fixed by normalizing the direction vector before multiplying by
   DISPLAY_EXTENT.

3. Origin-stuck corrupted entities (coordinates ≈ 0 in world space become
   ≈ -world_offset in local space) pulled the fit_all() bounds far from
   the actual drawing. Fixed by computing local_extent_max from EXTMIN/EXTMAX
   (10× safety margin) and skipping points outside that range in fit_all().

Additional hardening: wire_gpu.rs now skips ±inf segments (not just NaN),
and snap_pts/key_vertices in all TruckObject variants are offset-corrected.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-27 18:04:35 +03:00
Hakan Seven
a2fb334966 fix: world_offset precision fix for large-coordinate DXF files (e.g. Turkish UTM)
Subtracts the DXF header extents centroid (world_offset) from all coordinates
in f64 BEFORE casting to f32. This eliminates the ~0.5 m ULP error that occurs
at 4,000,000 m UTM coordinates and caused geometry to disappear on zoom-out.

- Scene: adds world_offset field + compute_and_set_world_offset() method
- tessellate.rs: threads world_offset through all f64→f32 conversions
  (legacy_geometry, dimension_geometry, solid_wire_fallback, multileader)
- truck_tess.rs: to_local() helper already in place from prior session
- mod.rs: tessellate_entity() and entity_aabb() apply world_offset
- update.rs: compute_and_set_world_offset() called after doc load
- cmd_result.rs / solid3d_cmds.rs: pass correct offset to truck tessellators

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-27 07:41:38 +03:00
Hakan Seven
7bae75f5d6 feat: dimension extension lines respect DIMEXO offset and DIMEXE overshoot
Extension lines for linear and aligned dimensions now start at
DIMEXO × DIMSCALE distance from the definition point (instead of at the
point itself) and extend DIMEXE × DIMSCALE units past the dimension
line, matching AutoCAD rendering. Both values fall back to 0 when the
dimstyle is not found.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-27 02:30:56 +03:00
Hakan Seven
debc4b87a8 feat: dimension arrow size from DIMASZ×DIMSCALE in dimstyle
Arrow size for all dimension types (linear, aligned, radius, diameter,
angular) is now read from the associated DimStyle's dimasz field scaled
by dimscale, instead of being hardcoded at 0.12. Falls back to 0.12
when the style isn't found in the document's dim_styles table.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-27 02:28:48 +03:00
Hakan Seven
464bb8905f fix: INSERT Insertion snap point and Hatch boundary snap points
INSERT entities now expose their insertion point as a SnapHint::Insertion
pre-baked snap candidate, enabling OSNAP Insertion to locate block
reference origins. The cross marker is also positioned at the actual
insertion point instead of the origin.

Hatch entities now populate key_vertices from Polyline and Line boundary
edges (with correct elevation Z), enabling Endpoint and Midpoint snapping
to hatch boundary geometry.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-26 22:04:53 +03:00
Hakan Seven
db653c5a07 fix: derive dimension text rotation from axis geometry
acadrust's DXF reader does not parse group code 53 (text rotation),
so DimensionBase.text_rotation is always zero for DXF-loaded files.
Fall back to the natural axis-aligned rotation computed from geometry:
Linear dimensions use d.rotation (radians), Aligned dimensions use
atan2 of the second-first vector.  Normalize to (-π/2, π/2] so text
never appears upside-down.  Explicit non-zero overrides stored by the
DWG reader are preserved.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-26 17:08:12 +03:00
Hakan Seven
19bb846c50 fix: dimension line geometry and DXF rotation unit mismatch
append_linear_dimension() applied the same perp offset to both d1 and d2,
but only d2 is guaranteed to be at the definition_point level; d1 must be
projected independently onto the dimension line, otherwise non-collinear
first/second points produce a parallelogram instead of a rectangle.

Fix: compute dim_line_pos = def.dot(perp) and project each endpoint
separately so the dimension line is always parallel to axis.

Additionally, the acadrust DXF reader stores LinearDimension.rotation from
group code 50 (degrees) without converting to radians, while DWG and our
own annotation commands store it in radians.  Add a post-load fixup in
load_file() that converts the rotation to radians for DXF files so
tessellation can call cos/sin uniformly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-26 16:57:23 +03:00
Hakan Seven
bfd8d0411a perf: AABB snap pre-rejection via acadrust bounding_box() (Option K upgrade)
Add `aabb: [f32; 4]` field to WireModel (world-space 2-D bounding box).
In tessellate_entity() set each wire's AABB from e.as_entity().bounding_box()
via new entity_aabb() helper; Insert sub-entities each get their own AABB.
Preview/interim wires and any entity returning a zero-extent default box get
UNBOUNDED_AABB so they are never pre-rejected.

Replace the chord-sphere heuristic in Snapper::wire_in_range() with a proper
AABB vs snap-circle overlap test.  The new check is four scalar comparisons and
correctly handles closed curves (circles, arcs) which the chord-sphere approach
had to special-case.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-26 12:21:51 +03:00
Hakan Seven
28f5c84b09 feat: Solid3D wire fallback render + Ole2Frame placeholder
- When SAT tessellation yields no mesh (binary SAB or unsupported ACIS
  geometry), render the pre-computed edge-wire polylines stored in
  Solid3D / Region / Body entities as a visible line fallback.
- Ole2Frame entities now render a bounding rectangle with diagonal X
  instead of an invisible stub — marks embedded OLE objects in the
  viewport.

Closes ROADMAP 2.13 (partial), 3.2 (Ole2Frame).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-08 22:16:58 +03:00
Hakan Seven
1db3ad6a33 Feat: implement CTB/STB plot style table with PDF export integration
- src/io/plot_style.rs: PlotStyleTable and PlotStyleEntry data structures;
  CTB reader (deflate/zlib decompressed text format) with ACI→RGB and
  ACI→lineweight lookup; CTB writer (zlib compressed); LW_TABLE constant
- src/io/pdf_export.rs: accept optional PlotStyleTable; apply ACI color
  and lineweight overrides during PDF rendering
- src/scene/wire_model.rs: add `aci: u8` field to carry ACI index
- src/scene/render.rs: render_style() now returns ACI alongside RGBA
- src/scene/mod.rs + tessellate.rs: propagate aci through wire building
- app: PlotStyleLoad/Loaded/Clear messages and handlers;
  PLOTSTYLE LOAD | CLEAR | STATUS command; active_plot_style state on H7CAD
- flate2 added as dependency

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 14:37:23 +03:00
Hakan Seven
d2fdac7f1e first commit 2026-03-22 14:56:27 +03:00