123456789101112131415161718192021222324252627282930313233343536373839404142434445464748(* 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 Clip.mli *)typevertex=Vec3.t*(float*float)*Vec3.t(* the point of the edge from [a] to [b] at depth [near] *)letintersect~(near:float)(((ax,ay,az),(au,av),an):vertex)(((bx,by,bz),(bu,bv),bn):vertex):vertex=lett=(near-.az)/.(bz-.az)inletlerpx0x1=x0+.(t*.(x1-.x0))in(* z exactly [near], not what the rounding of lerp az bz would give,
* which could be a hair behind the plane *)((lerpaxbx,lerpayby,near),(lerpaubu,lerpavbv),(* a mix of two unit normals is shorter than 1: renormalize *)Vec3.normalize(Vec3.add(Vec3.scale(1.-.t)an)(Vec3.scaletbn)))letnear_plane~(near:float)(polygon:vertexlist):vertexlist=letin_front((_,_,z),_,_)=z>=nearinmatchpolygonwith|[]->[](* claude: the common case, nothing to cut: the polygon as it is (the
* walk below would give the same vertices, but starting from the
* second one, and the triangle loop's rounding depends on the order) *)|_whenList.for_allin_frontpolygon->polygon|first::_->(* each edge, from [a] to [b], the last one back to the first vertex *)letrecedges=function|a::(b::_asrest)->(a,b)::edgesrest|[last]->[(last,first)]|[]->[]inedgespolygon|>List.concat_map(fun(a,b)->match(in_fronta,in_frontb)with|true,true->[b]|true,false->[intersect~nearab]|false,true->[intersect~nearab;b]|false,false->[])