discontinuedPackage jet_cad_floor_plan has been discontinued and replaced by jet_cad_2d_plan.

symbolOf function

List<Generated> symbolOf(
  1. HostFrame f,
  2. OpeningParams o,
  3. Cut? cut,
  4. Transform2 toOwn,
)

Opening o's symbol (spec 08 D10, D11), computed in its host's local space on the host's frame f and taken to the opening's own local space by toOwn, which is toWorld(self)⁻¹ · toWorld(host): host-local → world → own local. Every child is ByLayer, Generated's default.

cut is the opening's cut (D8); the symbol is drawn over [x₁, x₂], the cut's interval. Null means no-fit (D11): the symbol is drawn over the stored interval [c − w/2, c + w/2], never over the band.

  • door (a LINE, then an ARC): the hinge H is the jamb corner on the swing-side face at x₁ (hinge start) or x₂ (hinge end); the leaf runs from H perpendicular to the wall, away from the band, w long; the swing is the quarter arc about H of radius w between the leaf's tip and the shut jamb (the other jamb on the same face), a sweep of +π/2, starting at whichever of the two makes it anticlockwise. A no-fit door is drawn the same way: its symbol lies outside the band already;
  • window (three LINEs, in order): the left face, the midline (lOff + rOff)/2 and the right face, from x₁ to x₂. No-fit, each is translated by the thickness t along the left normal: offsets lOff + t, lOff + t/2 and lOff;
  • gap (one LINE): the threshold line on the centreline (offset 0) from x₁ + m to x₂ − m, m = min(t/4, w/4). No-fit, at offset lOff + t/2.

o must not be degenerate (D6): it generates nothing.

Implementation

List<Generated> symbolOf(
    HostFrame f, OpeningParams o, Cut? cut, Transform2 toOwn) {
  final w = o.width;
  final fits = cut != null;
  final x1 = fits ? cut.a : o.position - w / 2;
  final x2 = fits ? cut.b : o.position + w / 2;
  final t = f.lOff - f.rOff;
  Vector2 own(double u, double off) => toOwn.transformPoint(f.at(u, off));
  Generated line(double u1, double u2, double off) =>
      Generated(EntityKind.line, linePayload(own(u1, off), own(u2, off)));
  switch (o.kind) {
    case OpeningKind.door:
      final (uh, us) = o.hinge == HingeEnd.start ? (x1, x2) : (x2, x1);
      final (face, out) =
          o.swing == SwingSide.left ? (f.lOff, w) : (f.rOff, -w);
      final hinge = own(uh, face);
      final tip = own(uh, face + out);
      final shut = own(us, face);
      final toTip = tip - hinge, toShut = shut - hinge;
      final ccw = toTip.x * toShut.y - toTip.y * toShut.x > 0;
      final from = ccw ? toTip : toShut;
      return [
        Generated(EntityKind.line, linePayload(hinge, tip)),
        Generated(
            EntityKind.arc,
            arcPayload(
                hinge, toTip.length, math.atan2(from.y, from.x), math.pi / 2)),
      ];
    case OpeningKind.window:
      final offsets = fits
          ? [f.lOff, (f.lOff + f.rOff) / 2, f.rOff]
          : [f.lOff + t, f.lOff + t / 2, f.lOff];
      return [for (final off in offsets) line(x1, x2, off)];
    case OpeningKind.gap:
      final m = math.min(t / 4, w / 4);
      return [line(x1 + m, x2 - m, fits ? 0 : f.lOff + t / 2)];
  }
}