package tiny_appkits
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>
Application engines from scratch: a spreadsheet, rich text, paint, draw, CAD, editors and more
Install
dune-project
Dependency
Authors
Maintainers
Sources
0.3.6.tar.gz
md5=7c636383d146d30ac6f2fa234a6253c8
sha512=c79f3823c5f8f57e5038eb640d487c61168b84aa07c61999d6622ef9fd0c890e2b03b4c6a7cdbbe9352a49e25dda00ac7bb14693cee8e3d7beeed251351a2af0
doc/src/tiny_appkits.appkit_cad/Cad_snap.ml.html
Source file Cad_snap.ml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65(* Claude Code * * Copyright (C) 2026 Yoann Padioleau * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public License * (LGPL) as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. *) (* See Cad_snap.mli *) module G = Cad_geom module D = Cad_drawing type kind = Endpoint | Midpoint | Center | Quadrant | Intersection | Perpendicular let name = function | Endpoint -> "Endpoint" | Midpoint -> "Midpoint" | Center -> "Center" | Quadrant -> "Quadrant" | Intersection -> "Intersection" | Perpendicular -> "Perpendicular" (* a piece's own points, of each kind *) let points = function | G.Segment (a, b) -> [ (Endpoint, a); (Endpoint, b); (Midpoint, G.scale 0.5 (G.add a b)) ] | G.Circle (c, r) -> (Center, c) :: List.map (fun a -> (Quadrant, G.polar c r a)) [ 0.; 90.; 180.; 270. ] | G.Arc (c, r, a0, a1) -> let s, e = G.arc_ends c r a0 a1 in let mid = G.polar c r (a0 +. (G.norm_angle (a1 -. a0) /. 2.)) in [ (Endpoint, s); (Endpoint, e); (Midpoint, mid); (Center, c) ] @ List.filter_map (fun a -> if G.within a0 a1 a then Some (Quadrant, G.polar c r a) else None) [ 0.; 90.; 180.; 270. ] let find (t : D.t) ~aperture ?from p = let pieces = List.concat_map (fun (_, (e : D.ent)) -> if (D.layer t e.layer).on then List.map fst (D.pieces t e) else []) t.ents in (* a center is caught from the rim too, as AutoCAD's was *) let near c = G.distance c p <= aperture || match c with G.Circle (c, _) | G.Arc (c, _, _, _) -> G.dist c p <= aperture | _ -> false in let close = List.filter near pieces in let own = List.concat_map points close in let rec pairs = function [] -> [] | c :: cs -> List.map (fun d -> (c, d)) cs @ pairs cs in let crossings = List.concat_map (fun (c, d) -> List.map (fun q -> (Intersection, q)) (G.intersections c d)) (pairs close) in let best cands = List.fold_left (fun acc (k, q) -> let d = G.dist p q in if d > aperture then acc else match acc with Some (_, _, db) when db <= d -> acc | _ -> Some (k, q, d)) None cands |> Option.map (fun (k, q, _) -> (k, q)) in let under = List.filter (fun c -> G.distance c p <= aperture) close in match best (own @ crossings) with | Some s -> Some s | None -> ( (* the cursor on a circle's rim, far from any of its points: its center, as AutoCAD's CENter caught it *) match List.find_map (function G.Circle (c, _) | G.Arc (c, _, _, _) -> Some c | G.Segment _ -> None) under with | Some c -> Some (Center, c) | None -> ( match (from, under) with | Some f, c :: _ -> let q = G.foot c f in if G.on_piece c q then Some (Perpendicular, q) else None | _ -> None))
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>