PageSourceSearch

https://www.eenetzwerk.de/assets/webcad/auto_base_slab-0aaf63ff.js

js eenetzwerk.de collected 2026-10-08 12:02:27 UTC 2,265 bytes, 45 lines download raw bytes

1// The base slab that comes with a closed run of outer walls: whoever draws
2// the outline of a house on its lowest storey has drawn its ground slab
3// too, and it was one more tool and one more click to remember (Steffen's
4// prototype makes it the same way).
5//
6// Only on the lowest storey of a building part: higher up the floor is the
7// slab of the storey below. Not twice: a base slab already under the run
8// is left alone.
9
10import { pointInPolygon, signedShoelaceArea } from 'webcad/geometry'
11import { earClip } from 'webcad/triangulation'
12import { detectSlabOutlineAt } from 'webcad/space_shapes'
13
14// The outline of the base slab to lay under a closed run, or null when none
15// is wanted. `ring` is the run's axis points; `walls` the storey's walls
16// after the run was saved; `slabs` its slabs.
17export function baseSlabOutline ({ ring, walls, slabs, storey, storeys }) {
18  if (!storey || !isLowestOfPart(storey, storeys)) return null
19  const inside = interiorPoint(ring)
20  if (!inside) return null
21  const covered = (slabs || []).some(slab => slab.predefined_type === 'BASESLAB' && pointInPolygon(inside, slab.boundary_polygon || []))
22  if (covered) return null
23  return detectSlabOutlineAt(walls || [], inside, 'outer')
24}
25
26// Whether no storey of the same building part lies lower.
27export function isLowestOfPart (storey, storeys) {
28  const level = (s) => Number(s.effective_niveau_height ?? s.elevation ?? 0)
29  const part = storey.section || null
30  return !(storeys || []).some(s => s.id !== storey.id && (s.section || null) === part && level(s) < level(storey) - 1e-6)
31}
32
33// A point inside a ring: its centroid when that lies inside (any convex
34// outline), else the centre of one of its triangles — an L's centroid can
35// fall into the notch.
36export function interiorPoint (ring) {
37  const pts = (ring || []).map(p => ({ x: Number(p.x), y: Number(p.y) }))
38  if (pts.length < 3 || Math.abs(signedShoelaceArea(pts)) < 1e-6) return null
39  const c = { x: pts.reduce((s, p) => s + p.x, 0) / pts.length, y: pts.reduce((s, p) => s + p.y, 0) / pts.length }
40  if (pointInPolygon(c, pts)) return c
41  const [tri] = earClip(pts)
42  if (!tri) return null
43  const [a, b, d] = tri.map(i => pts[i])
44  return { x: (a.x + b.x + d.x) / 3, y: (a.y + b.y + d.y) / 3 }
45}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.