Ë
    ;TÓjÎ  ã            	       ó–  — d Z ddlZddlZddlZej                  j                  ej                  j                  ej                  j                  ej                  j                  e«      «      «      «      Zej                  j                  dej                  j                  ed«      «       ddlZdZd„ Zd„ Zd„ Zd„ Zd	„ Zdd
„Zd„ Zd„ Zy)ao  Signed axes for spacecraft moving parts, measured from the geometry (17 Oct 2026). Authors write axes without a sign
convention: 105 of 109 guns had Blender's +X as their elevation axis, which makes the kit's `turn(gun, +pitch)` (positive =
up) drive the barrels DOWN into the hull, and a door's +angle may swing it inward. Rules (axes are in the node's own frame,
the kit applies them after the node's rest rotation):
  gun    barrel = the longest horizontal extent of its mesh from the pivot (+-X or +-Z); axis = barrel x up, so +angle raises it
  hinge  keep the author's axis line, sign chosen so +angle moves the part's centre AWAY from the craft's centre (opens)
Everything else keeps its axis (spinners and symmetric parts do not care about the sign).
usage (library side): measured_axes(glb_path, moving) -> {name: axis}; tools/space/fix_axes.py writes new card versions.é    NÚlib)ç        ç      ð?r   c                 óŠ   — | d   |d   z  | d   |d   z  z
  | d   |d   z  | d   |d   z  z
  | d   |d   z  | d   |d   z  z
  fS )Né   é   r   © ©ÚaÚbs     úE/home/claude-agent/forge-build/forge-assets/tools/space/axes_space.pyÚ_crossr      ss   € ˜!˜A™$  1¡™+¨¨!©¨q°©t©Ñ3°Q°q±T¸A¸a¹D±[À1ÀQÁ4È!ÈAÉ$Á;Ñ5NÐPQÐRSÑPTÐWXÐYZÑW[ÑP[Ð^_Ð`aÑ^bÐefÐghÑeiÑ^iÑPiÐjÐjó    c                 ó:   — t        d„ t        | |«      D «       «      S )Nc              3   ó,   K  — | ]  \  }}||z  –— Œ y ­w©Nr	   ©Ú.0ÚxÚys      r   ú	<genexpr>z_dot.<locals>.<genexpr>   s   è ø€ Ò7¡T Q¨˜1˜q�5Ñ7ùó   ‚)ÚsumÚzipr
   s     r   Ú_dotr      s   € ”sÑ7¬S°°A«YÔ7Ó7Ð7r   c                 ó:   — t        d„ t        | |«      D «       «      S )Nc              3   ó,   K  — | ]  \  }}||z
  –— Œ y ­wr   r	   r   s      r   r   z_sub.<locals>.<genexpr>   s   è ø€ Ò9¡t q¨!˜Q �UÑ9ùr   )Útupler   r
   s     r   Ú_subr      s   € ”uÑ9¬s°1°a«yÔ9Ó9Ð9r   c                 óx   ‡— t        j                  t        | | «      «      Š‰dkD  rt        ˆfd„| D «       «      S d S )Ng•Ö&è.>c              3   ó<   •K  — | ]  }t        |‰z  d «      –— Œ y­w)é   N)Úround)r   r   Úns     €r   r   z_unit.<locals>.<genexpr>   s   øè ø€ Ò+GÀ¬E°!°a±%¸¯OÑ+Gùs   ƒ)ÚmathÚsqrtr   r   )Úvr$   s    @r   Ú_unitr(      s3   ø€ Ü�	‰	”$�q˜!“*Ó€AÈ1ÈtÊ8¤eÓ+GÀQÔ+GÓ&GÐ]ÐY]Ð]r   c                 óÂ   ‡ ‡‡— i Šˆ ˆˆfd„Šg d¢g d¢g d¢g d¢g}‰ j                  di g«      ‰ j                  dd«         j                  d	g «      D ]  } ‰||«       Œ ‰S )
z{node index: world 4x4 matrix}c                 óº   •— t        j                  |t        j                  ‰d   |    «      «      }|‰| <   ‰d   |    j                  dg «      D ]  } ‰||«       Œ y )NÚnodesÚchildren)ÚglbÚ_mulÚ_matÚget)ÚiÚparentÚmÚcÚdocÚoutÚwalks       €€€r   r7   z_worlds.<locals>.walk   sT   ø€ Ü�H‰H�VœSŸX™X c¨'¡l°1¡oÓ6Ó7ˆÀ!¸¸Q¹Ø�W‘˜a‘×$Ñ$ Z°Ó4Ò@ˆA±d¸1¸aµjÑ@r   )r   r   r   r   )r   r   r   r   )r   r   r   r   )r   r   r   r   ÚscenesÚscener   r+   )r0   )r5   ÚidentÚsr6   r7   s   `  @@r   Ú_worldsr<      sb   ú€ à
€CöAò š<ª²|ÐD€EØ�W‰W�X ˜tÓ$ S§W¡W¨W°aÓ%8Ñ9×=Ñ=¸gÀrÓJÒZˆÉDÐQRÐTYÍNÐZØ€Jr   c                 óF   ‡ ‡‡— t        ˆ ˆˆfd„t        d«      D «       «      S )Nc              3   ó`   •‡K  — | ]$  Št        ˆˆˆˆfd „t        d«      D «       «      –— Œ& y­w)c              3   óH   •K  — | ]  }‰‰   |   |d k  r‰|   n‰z  –— Œ y­w)é   Nr	   )r   Úkr3   ÚpÚrÚws     €€€€r   r   z#_apply.<locals>.<genexpr>.<genexpr>#   s*   øè ø€ Ò)]Èq¨!¨A©$¨q©'¸QÀºU°Q°q²TÈÕ*JÑ)]ùs   ƒ"r"   N)r   Úrange)r   rC   r3   rB   rD   s    @€€€r   r   z_apply.<locals>.<genexpr>#   s$   ùè ø€ Ò%pÐbc¤cÖ)]ÔTYÐZ[ÓT\Ô)]×&]Ñ%pùs   „*.r@   )r   rE   )r3   rB   rD   s   ```r   Ú_applyrF   #   s   ú€ ¤Õ%pÔglÐmnÓgoÔ%pÓ pÐpr   c                 ó0  ‡— | d   |d      d   D �cg c]  }d|d   v sŒ| d   |d   d      ‘Œ }}t        d«      D �‡cg c]  Št        ˆfd„|D «       «      ‘Œ c}t        d«      D �‡cg c]  Št        ˆfd	„|D «       «      ‘Œ c}fS c c}w c c}w c c}w )
NÚmeshesÚmeshÚ
primitivesÚPOSITIONÚ
attributesÚ	accessorsr@   c              3   ó.   •K  — | ]  }|d    ‰   –— Œ y­w)ÚminNr	   ©r   r   rA   s     €r   r   z_bounds.<locals>.<genexpr>(   s   øè ø€ Ò) ��%‘˜•Ñ)ùó   ƒc              3   ó.   •K  — | ]  }|d    ‰   –— Œ y­w)ÚmaxNr	   rP   s     €r   r   z_bounds.<locals>.<genexpr>(   s   øè ø€ ÒB\ÐSTÀ1ÀUÁ8ÈAÅ;ÑB\ùrQ   )rE   rO   rS   )r5   ÚnodeÚprÚaccrA   s       `r   Ú_boundsrW   &   s¸   ø€ ØDGÈÁMÐRVÐW]ÑR^ÑD_Ð`lÑDmö  Q¸bÐq{ð  @Bð  COñ  @Pò  rPˆ3ˆ{Ñ˜B˜|Ñ,¨ZÑ8Ó9ð  Q€Cð  QÜ38¸³8×<¨aŒCÓ) SÔ)Õ)Ò<ÔfkÐlmÓfn×>oÐab¼sÓB\ÐX[ÔB\Õ?\Ò>oÐoÐoùò QùÚ<ùÒ>os   ’B	ŸB	¿BÁ*Bc                 ó4  ‡‡‡— t        j                  | «      d   }t        |«      }t        |d   «      D ��ci c]  \  }}|j	                  d«      |“Œ }}}t        j
                  | «      d   Št        ˆfd„t        d«      D «       «      }i }|j                  «       D �]p  \  }	}
|j	                  |	«      }|�|d   |   j	                  d«      €Œ2t        ||d   |   «      \  ŠŠ|
d   d	k(  rN‰d   ‰d    ‰d
   ‰d
    dœ}t        ||j                  ¬«      }t        t        |t        «      «      d|› �f||	<   Œ�|
d   dk(  sŒ¦t        |
d   «      }t        ˆˆfd„t        d«      D «       «      }||   }t        ||«      }t        |d«      }t        ||d«      }t        |t        ||«      «      }t        ||«      }t!        ||«      }t#        |«      ddt!        ||«      z   z  kD  s�ŒJt        |dkD  r|nt        d„ |D «       «      «      df||	<   �Œs |S c c}}w )zmmoving = card nodes.moving {name: {kind, axis}} -> {name: (axis, how)} for the parts whose axis this measuresr   r+   ÚnameÚboundsc              3   óF   •K  — | ]  }‰d    |   ‰d   |   z   dz  –— Œ y­w)rO   rS   r   Nr	   )r   rA   r3   s     €r   r   z measured_axes.<locals>.<genexpr>/   s-   øè ø€ Ò3fÐXY°Q°u±X¸a±[À1ÀUÁ8ÈAÁ;Ñ5NÐRSÕ4SÑ3fùs   ƒ!r@   rI   ÚkindÚgunr   ))r   r   r   )éÿÿÿÿr   r   )r   r   r   )r   r   r^   )Úkeyzbarrel ÚhingeÚaxisc              3   ó:   •K  — | ]  }‰|   ‰|   z   d z  –— Œ y­w)r   Nr	   )r   rA   ÚhiÚlos     €€r   r   z measured_axes.<locals>.<genexpr>:   s"   øè ø€ Ò2YÈ1°B°q±E¸B¸q¹E±MÀQÕ3FÑ2Yùs   ƒ)r   r   r   r   g�íµ ÷Æ°>r   c              3   ó"   K  — | ]  }| –— Œ	 y ­wr   r	   )r   r   s     r   r   z measured_axes.<locals>.<genexpr>?   s   è ø€ ºÀ¸!¼¹ùs   ‚zopens away from the hull)r-   Úreadr<   Ú	enumerater0   Úmeasurer   rE   ÚitemsrW   rS   r(   r   ÚUPrF   r   r   Úabs)ÚpathÚmovingr5   ÚWr1   r$   ÚidxÚcentrer6   rY   ÚinfoÚreachÚbarrelr   Úc_locÚMwÚCwÚPwÚAwÚmoveÚawayÚdrc   rd   r3   s                         @@@r   Úmeasured_axesr|   +   s  ú€ ä
�(‰(�4‹.˜Ñ
€C¤¨£˜QÜ(1°#°g±,Ó(?×
@¡  1ˆ1�5‰5�‹=˜!ÑÐ
@€CÑ
@Ü�‰�DÓ˜(Ñ#€A¬eÓ3fÔ]bÐcdÓ]eÔ3fÓ.f VØ
€CØ—l‘l“nó f‰
ˆˆdØ�G‰G�D‹MˆØˆ9˜˜G™ Q™×+Ñ+¨FÓ3Ð;¸XÜ˜˜c '™l¨1™oÓ.‰ˆˆBØ�‰<˜5Ò Ø " 1¡°B°q±E°6ÀbÈÁeÐZ\Ð]^ÑZ_ÐY_Ñ`ˆEÜ˜ E§I¡IÔ.ˆFÜœv f¬bÓ1Ó2°g¸f¸XÐ4FÐGˆC�ŠIØ�&‰\˜WÓ$Ü�d˜6‘lÓ#ˆA¬UÔ2YÔPUÐVWÓPXÔ2YÓ-Y UØ�1‘ˆBœF 2 uÓ-�r´F¸2¸yÓ4I¨rÔPVÐWYÐ[\Ð^aÓPbÈ2Ü˜"œd 2 r›lÓ+ˆD´D¸¸VÓ4D¨TÜ�T˜4Ó ˆAÜ�1‹v˜ ¤D¨¨tÓ$4Ñ 4Ñ5Ô5Ü"¨¨Aª¡1´5¹ÀQ¼Ó3GÓHÐJdÐe��D“	ðfð €Jùó% As   ¸H)r   )Ú__doc__r%   ÚosÚsysrl   ÚdirnameÚabspathÚ__file__ÚROOTÚinsertÚjoinr-   rj   r   r   r   r(   r<   rF   rW   r|   r	   r   r   ú<module>r†      s�   ðñ|÷ Ó Ø	‡w�w‡��r—w‘w—‘ r§w¡w§¡°r·w±w·±ÀxÓ7PÓ'QÓRÓS€Ø ‡�‡���2—7‘7—<‘<  eÓ,Ô -Û 
à€ò kÚ 7Ú 9ò^òó qòpó
r   