Commit Graph

20542 Commits

Author SHA1 Message Date
Ryan Schultz 7e7394a933 Add opt-in join coplanar surfaces toggle with offset-wall guard
Adds a "Join Coplanar Surfaces" bool property (default off) nested
under "Generate Material Layers" in BIM_PT_camera. When enabled,
remove_coplanar_boundary_lines runs after linework generation to
suppress shared boundary lines between adjacent coplanar elements
of the same material.

Fixes a false-positive where back-to-back walls at adjacent face
planes (e.g. two thin walls touching at Y=1.185) were incorrectly
joined. The bilateral segment matching now only removes a shared
line segment when it covers the full running-direction extent of at
least one element's union — offset partial overlaps are skipped.
A companion flag suppresses the unilateral bbox fallback when
bilateral already found explicit segments on that line, preventing
the fallback from removing the same boundary the bilateral pass
correctly rejected.

Generated with the assistance of an AI coding tool.
2026-04-12 08:55:43 -05:00
Ryan Schultz 2b7bcb1b40 Add opt-in toggle to join coplanar surface boundaries in drawings
Introduces a "Join Coplanar Surfaces" boolean property (default off)
nested under the "Generate Material Layers" option in BIM_PT_camera.
When enabled, remove_coplanar_boundary_lines runs after linework
generation to suppress shared boundary lines between adjacent coplanar
elements of the same material.

Generated with the assistance of an AI coding tool.
2026-04-12 08:09:12 -05:00
Ryan Schultz 6c993ba919 Fix depth check to use camera direction instead of face normal
The same-plane check projected vertices onto the dominant face
normal (n_a) to determine if two elements span the same depth
range. This correctly rejected slabs stacked along their normal
axis but broke for elements whose largest face is perpendicular
to the camera (e.g. X-normal boxes in plan view) — projection
onto X produces zero overlap for legitimate side-by-side pairs.

Replace n_a projection with projection onto _cam_look. Elements
at the same camera depth produce overlapping ranges and are joined;
elements separated in camera depth produce disjoint ranges and are
correctly rejected regardless of the orientation of their faces.

Generated with the assistance of an AI coding tool.
2026-04-07 13:28:08 -05:00
Ryan Schultz 16d2ec64b4 Use object local stacking axis for camera-face layer detection
Replace the camera_looks_up flag (plan vs RCP) and dominant-face-
normal heuristic with a unified local-axis projection for all
LayerSetDirections:
  AXIS3 (slabs/roofs) → object local Z (col[2])
  AXIS2 (walls)       → object local Y (col[1])
  AXIS1 (rare walls)  → object local X (col[0])

The camera look vector is projected onto the object's world-space
stacking axis; a negative dot product means the camera is on the
positive (exterior) side of the layer sequence, a positive dot
means it is on the negative (interior) side.

This correctly handles sloped AXIS3 slabs viewed by two plan-type
cameras from opposite sides — the tilted local Z produces different
dot products for each camera direction, where the old camera_looks_up
flag returned the same result for both.

Generated with the assistance of an AI coding tool.
2026-04-07 13:12:27 -05:00
Ryan Schultz 29dc58fb61 Restrict mat_keys_match to remove boundary-ends fallback
The generic boundary-ends check (any end layer of a matches any
end layer of b) was too permissive for AXIS2 walls in plan view.
Because the full cross-section is visible in section, two walls
with different assemblies that merely share an interior or exterior
layer were incorrectly joined.

For AXIS3 slabs/roofs the camera-face layer check already handles
cases where only the visible face layer matters. The boundary-ends
fallback is no longer needed and has been removed. AXIS1/AXIS2
walls now only join via exact, reversed, prefix, or suffix layer
sequence matches.

Generated with the assistance of an AI coding tool.
2026-04-07 12:21:28 -05:00
Ryan Schultz 2d5f8d50a0 Fix depth-stacked elements incorrectly joining in projection
The same-plane check in are_coplanar_and_adjacent tested whether
any vertex of element A shared a depth value (projected onto n_a)
with any vertex of element B. This falsely passed for elements
stacked end-to-end along the normal axis, because they touch at
a single interface point that appears in both vertex sets.

Replace the point-match with a range-overlap test: project each
element's full vertex set onto n_a to get a 1-D depth interval,
then require the two intervals to overlap by more than tol. Side-
by-side coplanar elements overlap across their full shared face
thickness; end-to-end stacked elements only touch at a zero-width
boundary, so their overlap is 0 and the join is correctly rejected.

Generated with the assistance of an AI coding tool.
2026-04-07 12:00:55 -05:00
Ryan Schultz 32c2ec3966 decrease the co-planer tolerance a little more. 2026-04-06 12:20:17 -05:00
Ryan Schultz 6616713cfd Match coplanar joins by camera-facing layer
Two changes to mat_keys_match:

1. Boundary-ends fallback: when exact/reversed/prefix/suffix checks
   all fail, allow a join if any end layer (first or last) of each
   assembly shares a material ID. This handles adjacent elements
   with different inner layers but the same face material at the
   shared interface (e.g. two-layer roofs that share only their
   visible surface material).

2. Camera-directional face check: for IfcMaterialLayerSetUsage
   elements with AXIS3 (vertical) layer direction (slabs, roofs),
   compute the actual camera-facing layer — top layer for plan
   views (camera looks down), bottom layer for RCPs (camera looks
   up) — using DirectionSense to resolve which end is up. When
   both elements provide a face layer ID, only those are compared,
   preventing incorrect joins in RCPs where elements expose
   different bottom materials even though they share a top material.

   Walls (AXIS1/AXIS2) are unaffected and continue to use the
   generic ends-intersection fallback.

Generated with the assistance of an AI coding tool.
2026-04-06 11:26:55 -05:00
Ryan Schultz 9041b2e249 Add partial edge splitting for coplanar boundary removal
When two coplanar same-material elements share only part of an
edge (e.g. an L-shaped element abutting a rectangle along a
notch), the previous bilateral match removed whole segments and
left gaps or over-removed lines.

The new approach groups all segments per element by their
axis-aligned line, merges them into interval unions, computes the
shared intersection, removes all original segments on that line,
and re-adds the non-shared remainders as new path elements. This
correctly handles any number of sub-segments on the same line.

Generated with the assistance of an AI coding tool.
2026-04-06 07:56:59 -05:00
Ryan Schultz e6235d0cb6 Fix unilateral boundary detection for notched elements
When an L-shaped element wraps around a smaller coplanar element,
the shared face is interior to the larger element's bounding box.
The previous seg_on_boundary_of check required the shared face to
lie on the larger element's own bbox edge (outer abutment only),
so it missed these cases entirely.

The new logic checks whether the segment lies on the *smaller*
element's own bbox edge and whether the other element extends past
that edge on the adjacent side — correctly handling both simple
side-by-side abutment and notch/wrap configurations.

Generated with the assistance of an AI coding tool.
2026-04-05 22:05:15 -05:00
Ryan Schultz a818693a15 See #3742: Extend coplanar SVG line deduplication
Handle additional adjacency cases in the plan/section SVG
projection line deduplication introduced for #3742:

- Use IfcMaterialLayerSetUsage layer sequence instead of a
  flat material set for material comparison. Prefix/suffix
  matching allows elements whose assemblies share the same
  layers at the interface (one having extra finish layers)
  to be correctly merged.

- Add a unilateral bbox-edge fallback for pairs where one
  element's shared boundary is implicit (not drawn as an
  explicit SVG path segment). Segments from the other
  element that lie on the boundary of the first element's
  SVG bounding box are removed even without a bilateral
  match.

Generated with the assistance of an AI coding tool.
2026-04-05 19:57:29 -05:00
Ryan Schultz efa26ad6f4 See #3742: Handle unilateral shared-edge detection for implicit boundaries
Some adjacent same-material elements don't explicitly draw their shared
boundary in both SVG projection groups — one element's edge is implicit
(absorbed into its parent path or omitted because the other element
"owns" it). In these cases the bilateral lines_match check finds zero
hits even though the elements are correctly identified as adjacent and
coplanar.

Add a unilateral bbox-edge fallback: after the bilateral pass finds
nothing, compute the SVG bounding box of each element's parsed segments
and check whether any segment from one element lies on a face of the
other element's bbox with meaningful overlap. Segments that pass are on
the shared interface and are removed even without a mirror segment in the
opposite group.

The overlap check (> TOL) prevents false positives from segments that
merely touch a bbox corner without sharing real extent.

Generated with the assistance of an AI coding tool.
2026-04-05 18:30:36 -05:00
Ryan Schultz 363f65ff2c Fix #3742: Improve coplanar boundary removal for complex wall configurations
Extends the SVG projection line deduplication introduced earlier with
several new cases:

**Containment adjacency (inner element inside outer)**
- The original shared-vertex check failed when an inner element's corners
  lie on edges of the outer element rather than at corner vertices.
- Added vertex-to-edge proximity check using point-to-segment distance.
- When one AABB is fully contained within another, skip the dominant-face
  normal check: a short/flat inner element's largest polygon is its
  top/bottom face, giving a spurious perpendicular normal.

**Anti-parallel normals (mirrored wall faces)**
- Two adjacent wall sections can have opposite face normals (+Y vs -Y)
  while still being on the same plane. The original `abs(dot)` check
  correctly identifies them as parallel, but projecting onto each
  object's own normal produced mirrored plane-position values that never
  matched.
- Fixed by projecting both objects' vertices onto the same reference
  normal (n_a) when computing face-plane positions.

**Parallel offset walls (false positive rejection)**
- Two walls with identical orientations but on different parallel planes
  (e.g., offset walls meeting at a corner) were incorrectly accepted by
  the normal-direction check alone.
- Added face-plane position check: after confirming normals are parallel,
  verify at least one face-plane position of A (projected onto the shared
  normal) matches one of B within tolerance.

**L-shaped wall split segments (collinear overlap)**
- An L-shaped wall's boundary at a shared interface can be split into
  multiple sub-segments (one per notch side), while the adjacent simple
  wall has a single full-length segment covering the same edge.
- Exact endpoint matching always failed in this case.
- Extended `lines_match` with a collinear-overlap check: axis-aligned
  segments on the same line with overlapping extents (beyond a trivial
  point touch) are now treated as the same physical edge.

Fix #3742: Improve coplanar boundary removal for complex wall configurations

Extends the SVG projection line deduplication introduced earlier with
several new cases:

**Containment adjacency (inner element inside outer)**
- The original shared-vertex check failed when an inner element's corners
  lie on edges of the outer element rather than at corner vertices.
- Added vertex-to-edge proximity check using point-to-segment distance.
- When one AABB is fully contained within another, skip the dominant-face
  normal check: a short/flat inner element's largest polygon is its
  top/bottom face, giving a spurious perpendicular normal.

**Anti-parallel normals (mirrored wall faces)**
- Two adjacent wall sections can have opposite face normals (+Y vs -Y)
  while still being on the same plane. The original `abs(dot)` check
  correctly identifies them as parallel, but projecting onto each
  object's own normal produced mirrored plane-position values that never
  matched.
- Fixed by projecting both objects' vertices onto the same reference
  normal (n_a) when computing face-plane positions.

**Parallel offset walls (false positive rejection)**
- Two walls with identical orientations but on different parallel planes
  (e.g., offset walls meeting at a corner) were incorrectly accepted by
  the normal-direction check alone.
- Added face-plane position check: after confirming normals are parallel,
  verify at least one face-plane position of A (projected onto the shared
  normal) matches one of B within tolerance.

**L-shaped wall split segments (collinear overlap)**
- An L-shaped wall's boundary at a shared interface can be split into
  multiple sub-segments (one per notch side), while the adjacent simple
  wall has a single full-length segment covering the same edge.
- Exact endpoint matching always failed in this case.
- Extended `lines_match` with a collinear-overlap check: axis-aligned
  segments on the same line with overlapping extents (beyond a trivial
  point touch) are now treated as the same physical edge.

Generated with the assistance of an AI coding tool.
2026-04-05 09:37:39 -05:00
Ryan Schultz 39905fb6b5 * Fix #3742: Remove coplanar boundary lines between adjacent same-material elements in Bonsai SVG drawings
Adds `remove_coplanar_boundary_lines()` to operator.py (Bonsai uses this
path, not draw.py's main()). After `merge_linework_and_add_metadata()`
assigns material CSS classes, this post-processes the SVG to delete
projection line segments that appear in two or more adjacent, coplanar
elements with the same material and presentation style.

Key design decisions:
- Material identity: compared via sorted IFC material ID tuples from
  `get_materials()`, not CSS class names — avoids false matches between
  unrelated `material-null` elements.
- Presentation style identity: compared via IFC IfcPresentationStyle IDs
  from `StyledByItem` on geometry representation items — handles elements
  with no material but distinct visual styles.
- Physical adjacency: confirmed by a 3D shared-vertex test (tol=0.01 m)
  after a quick AABB guard, rejecting elements whose 2D projections
  overlap but sit at different depths.
- Coplanarity: determined by the dominant (largest-area) face normal of
  each Blender mesh object — area-weighted averages are unreliable for
  slabs whose equal top/bottom faces cancel out. Folded walls sharing an
  edge but meeting at an angle are correctly rejected (normal dot ≪ 1.0).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-04 13:59:52 -05:00
Bruno Perdigão 97ee4eaef0 See #7888 - Fix snap when object changes during modal operator.
Handle cases where the snapped target is modified while a modal operator
is active (e.g., adding a door or window that alters the wall geometry).
bonsai-0.8.5-alpha2604041731
2026-04-04 14:30:59 -03:00
Thomas Krijnen 30517770e0 Revert default tool output truncation 2026-04-04 13:12:47 +02:00
DesertSpringsCivil 5b1ec85f75 feat: Reduce token usage in ifcchat and default to IFC4X3
- Add Anthropic prompt caching (cache_control on system prompt and
  tools) to reduce repeated token costs by ~90%
- Truncate large tool results in conversation history (2000 char cap)
  to prevent context bloat from ifc_tree/ifc_select responses
- Add sliding window (40 messages) on conversation history, trimming
  at user message boundaries to avoid breaking tool-call sequences
- Default "New IFC" button to IFC4X3 schema instead of IFC4
- Constrain ifc_new schema parameter with enum to prevent invalid
  schema strings like "IFC4X3ADD2"

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-04 13:11:14 +02:00
Stephen Boddy 12123baafe Update the pyver as 3.13 is default in 5.1 now bonsai-0.8.5-alpha2604040322 2026-04-04 04:22:12 +01:00
Stephen Boddy 0a1c54cedc Fix the ci-bonsai-daily blender url bonsai-0.8.5-alpha2604040256 2026-04-04 03:56:08 +01:00
Bruno Postle 12144f76d3 Merge branch 'ifcgit-features' into v0.8.0 bonsai-0.8.5-alpha2604032319 2026-04-04 00:10:33 +01:00
Bruno Postle ca6e950496 ifcgit: conflict report panel and dry-run merge preview
Parse ifcmerge JSON output and display a per-conflict breakdown in the
panel when merge fails. Ctrl+click on the Merge button previews
conflicts without committing. Add SelectConflictEntity operator to
select and frame the conflicting object in the 3D viewport.

Generated with the assistance of an AI coding tool.
2026-04-03 13:28:14 +01:00
Thomas Krijnen c478da5257 Remove pro 2026-04-03 11:36:56 +02:00
Thomas Krijnen c28251a1b1 Add CNAME file 2026-04-03 11:30:33 +02:00
Thomas Krijnen 9bc0588d21 Update openai model list 2026-04-03 11:30:23 +02:00
Thomas Krijnen 918cc65a0d Provider selection as tabs bonsai-0.8.5-alpha2604030923 2026-04-03 11:22:43 +02:00
Thomas Krijnen 7350ccd25e Tweak header padding 2026-04-03 11:14:40 +02:00
Thomas Krijnen c1f146966c The end of open source? Just regurgitate some markdown parsing code. 2026-04-03 11:03:44 +02:00
Thomas Krijnen 24acfeaf45 Thinking indicator under chat 2026-04-03 10:59:09 +02:00
Thomas Krijnen 5d748c5b04 Add Gemini option 2026-04-03 10:49:36 +02:00
Thomas Krijnen 5bcf8685ab Merge remote-tracking branch 'origin/feat/ifcchat-claude' into v0.8.0 2026-04-03 10:26:29 +02:00
geronimi73 8f64f75abb add favourite models 2026-04-03 09:46:44 +02:00
geronimi73 434ea74f22 format this mess 2026-04-03 09:46:44 +02:00
geronimi73 fbf2946b69 Update index.html 2026-04-03 09:46:44 +02:00
geronimi73 7af0ec13e5 move model to sidebar 2026-04-03 09:46:44 +02:00
geronimi73 29e5e0fd1a chevrons for tool result expansion 2026-04-03 09:46:44 +02:00
geronimi73 d7de4f8df0 dont freeze UI on error 2026-04-03 09:46:44 +02:00
geronimi73 252bd6f4f6 openai by default 2026-04-03 09:46:44 +02:00
geronimi73 3b28c92414 html too big -> styles into sep. file 2026-04-03 09:46:44 +02:00
geronimi73 fcbec74521 spinner 2026-04-03 09:46:44 +02:00
geronimi73 0f7f960b29 let claude code openrouter compatibility 2026-04-03 09:46:44 +02:00
geronimi73 b7fc5daf82 ui: choose openai/openrouter 2026-04-03 09:46:44 +02:00
geronimi73 1d7a8ca249 separate API calls 2026-04-03 09:46:44 +02:00
Ryan Schultz eaf7950677 Fix TypeError in ray_cast_by_proximity_2d degenerate edge
A degenerate edge (zero-length segment) caused an early `return`
of a tuple instead of continuing the loop, resulting in a
TypeError when snap.py iterated the result and tried to assign
`point["group"]` on a float.

Generated with the assistance of an AI coding tool.
bonsai-0.8.5-alpha2604030224
2026-04-02 23:24:35 -03:00
DesertSpringsCivil 95851ff94c feat: Add Anthropic Claude API support to ifcchat
Add a provider selector (OpenAI / Anthropic) to the ifcchat web UI,
allowing users to use their Anthropic API key with Claude models
instead of only OpenAI.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 18:50:27 -06:00
Bruno Postle 3a6881ca17 ifcgit: add rename branch button next to working branch label
See #7577

Generated with the assistance of an AI coding tool.
2026-04-03 00:20:22 +01:00
Bruno Postle c5210a4f82 ifcgit: sync load_project post-import steps with project operator
See #7578
2026-04-03 00:03:34 +01:00
Bruno Postle e3cadab406 ifcgit: add clone widget to new project wizard (#7579) 2026-04-02 23:42:39 +01:00
Bruno Postle d5b551874d ifcgit: pre-fill branch name when switching to a remote branch tip
When a remote branch tip is checked out (resulting in detached HEAD),
the new-branch name field is now pre-filled with the local equivalent
of the remote branch name (generating a unique suffix if that name is
already taken), so the commit button is immediately usable.

See #7580

Generated with the assistance of an AI coding tool.
2026-04-02 23:16:40 +01:00
Bruno Postle be3aef59fa ifcgit: move action buttons below revision list in a labelled row
Generated with the assistance of an AI coding tool.
2026-04-02 22:45:33 +01:00
Bruno Postle bcc631bf5f ifcgit: improve colourise to find products via geometry and property changes
Generated with the assistance of an AI coding tool.
2026-04-02 22:44:56 +01:00