
    h7L                    "   % S SK Jr  S SKJrJrJrJrJrJrJ	r	J
r
  S SKJrJr  S SKrS SKrS SKJrJr  S SKJrJr  S SKJrJr  SS	KJr  SS
KJrJrJrJr  SSK J!r!  SSK"J#r#  SS/r$Sr% " S S\5      r&Sr'Sr(Sr)Sr*Sr+ " S S\&5      r,\S%S&S jj5       r-\\.\/\./\\.\4   4   r0S\1S'   \\/\
\/\/4   4   r2S\1S'   \	\
\/\/4      r3S\1S'   \	\3   r4S\1S'   S'S jr5S(S jr6S)S*S  jjr7 " S! S\&5      r8S+S" jr9          S,S# jr:        S-S$ jr;g).    )annotations)IterableSequenceno_type_checkAnyCallableDictListTuple)	TypeAliasoverrideN)Vec2world_mercator_to_gps)Commandnesting)orient_pathssingle_paths   )Color)BackendInterfaceBkPath2d
BkPoints2d	ImageData)Configuration)BackendPropertiesCustomJSONBackendGeoJSONBackenda~  
JSON content = [entity, entity, ...]

entity = {
    "type": point | lines | path | filled-paths | filled-polygon,
    "properties": {
        "color": "#RRGGBBAA",
        "stroke-width": 0.25, # in mm
        "layer": "name"
    },
    "geometry": depends on "type"
}
DXF linetypes (DASH, DOT, ...) are resolved into solid lines.

A single point:
point = {
    "type": "point",
    "properties": {...},
    "geometry": [x, y]
}

Multiple lines with common properties:
lines = {
    "type": "lines",
    "properties": {...},
    "geometry": [
        (x0, y0, x1, y1),  # 1. line
        (x0, y0, x1, y1),  # 2. line
        ....
    ]
}
Lines can contain points where x0 == x1 and y0 == y1!

A single linear path without filling:
path = {
    "type": "path",
    "properties": {...},
    "geometry": [path-command, ...]
}

SVG-like path structure:
- The first path-command is always an absolute move to "M"
- The "M" command does not appear inside a path, each path is a continuouse geometry 
  (no multi-paths).

path-command = 
    ("M", x, y) = absolute move to
    ("L", x, y) = absolute line to
    ("Q", x0, y0, x1, y1) = absolute quadratice Bezier curve to
    - (x0, y0) = control point
    - (x1, y1) = end point
    ("C", x0, y0, x1, y1, x2, y2) = absolute cubic Bezier curve to
    - (x0, y0) = control point 1
    - (x1, y1) = control point 2
    - (x2, y2) = end point
    ("Z",) = close path

Multiple filled paths:

Exterior paths and holes are mixed and NOT oriented by default (clockwise or 
counter-clockwise) - PyQt and SVG have no problem with that structure but matplotlib 
requires oriented paths.  When oriented paths are required the CustomJSONBackend can 
orient the paths on demand.

filled-paths = {
    "type": "filled-paths",
    "properties": {...},
    "geometry": [
        [path-command, ...],  # 1. path
        [path-command, ...],  # 2. path  
        ...
    ]
}

A single filled polygon:
A polygon is explicitly closed, so first vertex == last vertex is guaranteed.
filled-polygon = {
    "type": "filled-polygon",
    "properties": {...},
    "geometry": [
        (x0, y0),
        (x1, y1),
        (x2, y2),
        ...
    ]
}

c                      \ rS rSrSS jr\R                  SS j5       rSS.SS jjr\	SS j5       r
\	SS j5       r\	SS	 j5       r\	SS
 j5       r\	SS j5       r\	SS j5       r\	SS j5       rSrg)_JSONBackendo   c                J    / U l         SU l        SU l        SU l        SU l        g )Ng{Gz?皙?g      ?        )	_entitiesmax_sagittamin_lineweightlineweight_scalingfixed_lineweightselfs    K/var/www/html/env/lib/python3.13/site-packages/ezdxf/addons/drawing/json.py__init___JSONBackend.__init__p   s+    /1""% !$    c                    g N r)   s    r+   get_json_data_JSONBackend.get_json_dataz   s    $'r.      indentc               H    [         R                  " U R                  5       US9$ )z$Returns the result as a JSON string.r5   )jsondumpsr2   )r*   r6   s     r+   
get_string_JSONBackend.get_string|   s    zz$,,.v>>r.   c                    UR                   (       a#  UR                   S-  S-  n[        SU5      U l         UR                  U l        U R                  S:X  a  U R                   U l        UR                  U l        g )Ngffffff9@i,  r"   r#   )r&   maxr'   r(   max_flattening_distancer%   )r*   configmin_lineweight_mms      r+   	configure_JSONBackend.configure   si       & 5 5 <s B"%d,=">D"(";";""c)$($7$7D!!99r.   c                8    U R                   R                  5         g r0   )r$   clearr)   s    r+   rD   _JSONBackend.clear   s    r.   c                    g r0   r1   )r*   
image_data
propertiess      r+   
draw_image_JSONBackend.draw_image       r.   c                    g r0   r1   )r*   colors     r+   set_background_JSONBackend.set_background   rK   r.   c                    g r0   r1   r)   s    r+   finalize_JSONBackend.finalize   rK   r.   c                    g r0   r1   )r*   entityrH   s      r+   enter_entity_JSONBackend.enter_entity   rK   r.   c                    g r0   r1   )r*   rT   s     r+   exit_entity_JSONBackend.exit_entity   rK   r.   )r$   r(   r'   r%   r&   NreturnNone)r[   r   )r6   z	int | strr[   str)r?   r   r[   r\   )rG   r   rH   r   r[   r\   )rM   r   r[   r\   )__name__
__module____qualname____firstlineno__r,   abcabstractmethodr2   r:   r   rA   rD   rI   rN   rQ   rU   rX   __static_attributes__r1   r.   r+   r   r   o   s    $ 	' '01 ? 	: 	:            r.   r   MLQCZc                    ^  \ rS rSrSrSSU 4S jjjr\SS j5       r      SS jrSS jr	\SS j5       r
\SS j5       r\      SS	 j5       r\SS
 j5       r\      SS j5       r\      SS j5       rSrU =r$ )r      a~  Creates a JSON-like output with a custom JSON scheme.  This scheme supports
curved shapes by a SVG-path like structure and coordinates are not limited in
any way.  This backend can be used to send geometries from a web-backend to a
frontend.

The JSON scheme is documented in the source code:

https://github.com/mozman/ezdxf/blob/master/src/ezdxf/addons/drawing/json.py

Args:
    orient_paths: orient exterior and hole paths on demand, exterior paths have
        counter-clockwise orientation and holes have clockwise orientation.

**Class Methods**

.. automethod:: get_json_data

.. automethod:: get_string

.. versionadded:: 1.3.0

c                .   > [         TU ]  5         Xl        g r0   )superr,   r   )r*   r   	__class__s     r+   r,   CustomJSONBackend.__init__   s    (r.   c                    U R                   $ )z1Returns the result as a JSON-like data structure.)r$   r)   s    r+   r2   CustomJSONBackend.get_json_data   s     ~~r.   c                p    U(       d  g U R                   R                  UU R                  U5      US.5        g )NtyperH   geometry)r$   appendmake_properties_dict)r*   entity_typeru   rH   s       r+   
add_entityCustomJSONBackend.add_entity   s5     #"77
C$	
r.   c                    U R                   (       a  U R                   nO-[        U R                  UR                  U R                  -  5      nUR
                  [        US5      UR                  S.$ )Nr4   rM   zstroke-widthlayerr(   r=   r&   
lineweightr'   rM   roundr}   r*   rH   stroke_widths      r+   rw   &CustomJSONBackend.make_properties_dict   sd      00L##Z%:%:T=T=T%TL  %%!,2%%
 	
r.   c                V    U R                  SUR                  UR                  /U5        g )Npointry   xyr*   posrH   s      r+   
draw_pointCustomJSONBackend.draw_point   s    #%%<r.   c                    U R                  SUR                  UR                  UR                  UR                  4/U5        g )Nlinesr   )r*   startendrH   s       r+   	draw_lineCustomJSONBackend.draw_line   s.    577EGGSUUCEE"B!CZPr.   c                    [        U5      n[        U5      S:X  a  g U R                  SU VVs/ s H3  u  p4UR                  UR                  UR                  UR                  4PM5     snnU5        g s  snnf )Nr   r   )listlenry   r   r   )r*   r   rH   ses        r+   draw_solid_lines"CustomJSONBackend.draw_solid_lines   sX     Uu:?5!I541133QSS!##"65!I:V!Is   :A1c                <    U R                  S[        U5      U5        g )Npath)ry   make_json_path)r*   r   rH   s      r+   	draw_pathCustomJSONBackend.draw_path   s    t 4jAr.   c                *   [        U5      n[        U5      S:X  a  g U R                  (       a  [        U5      nO[        U5      n/ nU H.  n[        U5      (       d  M  UR	                  [        USS95        M0     U(       a  U R                  SX25        g g )Nr   T)closezfilled-paths)r   r   r   r   rv   r   ry   )r*   pathsrH   
json_pathsr   s        r+   draw_filled_paths#CustomJSONBackend.draw_filled_paths   s     Uu:? 'E !'E "
D4yy!!.T"BC  OONJC r.   c                    UR                  5       n[        U5      S:  a  g US   R                  US   5      (       d  UR                  US   5        U R	                  SU Vs/ s H  oDR
                  UR                  4PM     snU5        g s  snf )N   r   zfilled-polygon)verticesr   iscloserv   ry   r   r   )r*   pointsrH   r   vs        r+   draw_filled_polygon%CustomJSONBackend.draw_filled_polygon  su      &0x=1{""8B<00OOHQK((x*Hx!CC:x*H*U*Hs   !!B
)r   FrZ   )r[   zlist[dict[str, Any]])rx   r]   ru   zSequence[Any]rH   r   )rH   r   r[   dict[str, Any]r   r   rH   r   r[   r\   r   r   r   r   rH   r   r[   r\   r   zIterable[tuple[Vec2, Vec2]]rH   r   r[   r\   r   r   rH   r   r[   r\   r   zIterable[BkPath2d]rH   r   r[   r\   r   r   rH   r   r[   r\   )r^   r_   r`   ra   __doc__r,   r   r2   ry   rw   r   r   r   r   r   r   rd   __classcell__rn   s   @r+   r   r      s   .) )  

*7
EV

 = = Q Q W0W>OW	W W B B D'D5FD	D D$ V V.?V	V Vr.   c           
     .   [        U 5      S:X  a  / $ U R                  n[        UR                  UR                  4/nU R                  5        GH  nUR                  nUR                  [        R                  :X  a.  UR                  [        UR                  UR                  45        M\  UR                  [        R                  :X  a.  UR                  [        UR                  UR                  45        M  UR                  [        R                  :X  aQ  UR                  nUR                  [        UR                  UR                  UR                  UR                  45        GM  UR                  [        R                   :X  d  GM8  UR"                  nUR$                  nUR                  [&        UR                  UR                  UR                  UR                  UR                  UR                  45        GM     U(       a  UR                  [(        5        U$ )Nr   )r   r   MOVE_TO_ABSr   r   commandsr   rt   r   MOVE_TOrv   LINE_TOLINE_TO_ABS	CURVE3_TOctrlQUAD_TO_ABS	CURVE4_TOctrl1ctrl2CUBIC_TO_ABS
CLOSE_PATH)r   r   r   r   cmdc1c2s          r+   r   r     sP   
4yA~	

C"CEE35512H}}gg88w&OO[#%%78XX(OO[#%%78XX***BOO["$$ceeSUUCDXX***BBOO\244rttRTT355#%%PQ  
#Or.   r   PropertiesMakerTransformFuncRingGeoJsonPolygonc                "    U [        US5      US.$ )zReturns the property dict::

    {
        "color": color,
        "stroke-width": stroke_width,
        "layer": layer,
    }

Returning an empty dict prevents properties in the GeoJSON output and also avoids
wraping entities into "Feature" objects.
r4   r|   )r   )rM   r   r}   s      r+   properties_makerr   >  s     lA. r.   c                2    U R                   U R                  4$ )zkDummy transformation function.  Does not apply any transformations and
just returns the input coordinates.
)r   r   )locations    r+   no_transformr   Q  s     JJ

##r.   c                   ^  SU 4S jjnU$ )a/  Returns a function to transform WGS84 World Mercator `EPSG:3395 <https://epsg.io/3395>`_
location given as cartesian 2D coordinates x, y in meters into WGS84 decimal
degrees as longitude and latitude `EPSG:4326 <https://epsg.io/4326>`_ as
used by GPS.

Args:
    tol: accuracy for latitude calculation

c                F   > [        U R                  U R                  T5      $ )zITransforms WGS84 World Mercator EPSG:3395 coordinates to WGS84 EPSG:4326.)r   r   r   )r   tols    r+   
_transform7make_world_mercator_to_gps_function.<locals>._transformc  s    $XZZSAAr.   r   r   r[   ztuple[float, float]r1   )r   r   s   ` r+   #make_world_mercator_to_gps_functionr   X  s    B r.   c                    ^  \ rS rSrSr\\4     SU 4S jjjr\SS j5       r	SS jr
SS jr\SS j5       r\SS j5       r\      SS	 j5       r\SS
 j5       r\      SS j5       r\      SS j5       rSrU =r$ )r   ii  a  Creates a JSON-like output according the `GeoJSON`_ scheme.
GeoJSON uses a geographic coordinate reference system, World Geodetic
System 1984 `EPSG:4326 <https://epsg.io/4326>`_, and units of decimal degrees.

- Latitude: -90 to +90 (South/North)
- Longitude: -180 to +180 (East/West)

So most DXF files will produce invalid coordinates and it is the job of the
**package-user** to provide a function to transfrom the input coordinates to
EPSG:4326!  The :class:`~ezdxf.addons.drawing.recorder.Recorder` and
:class:`~ezdxf.addons.drawing.recorder.Player` classes can help to detect the
extents of the DXF content.

Default implementation:

.. autofunction:: no_transform

Factory function to make a transform function from WGS84 World Mercator
`EPSG:3395 <https://epsg.io/3395>`_  coordinates to WGS84 (GPS) 
`EPSG:4326 <https://epsg.io/4326>`_.

.. autofunction:: make_world_mercator_to_gps_function

The GeoJSON format supports only straight lines so curved shapes are flattened to
polylines and polygons.

The properties are handled as a foreign member feature and is therefore not defined
in the GeoJSON specs.  It is possible to provide a custom function to create these
property objects.

Default implementation:

.. autofunction:: properties_maker


Args:
    properties_maker: function to create a properties dict.

**Class Methods**

.. automethod:: get_json_data

.. automethod:: get_string

.. versionadded:: 1.3.0

.. _GeoJSON: https://geojson.org/
c                :   > [         TU ]  5         Xl        X l        g r0   )rm   r,   _properties_dict_maker_transform_function)r*   r   transform_funcrn   s      r+   r,   GeoJSONBackend.__init__  s    
 	&6##1 r.   c                    [        U R                  5      S:X  a  0 $ U R                  S   S   S:H  nU(       a  SU R                  S.$ SU R                  S.$ )zMReturns the result as a JSON-like data structure according the GeoJSON specs.r   rt   FeatureFeatureCollection)rt   featuresGeometryCollection)rt   
geometries)r   r$   )r*   using_featuress     r+   r2   GeoJSONBackend.get_json_data  sS     t~~!#I*62i?/T^^LL0OOr.   c                    U(       d  g U R                   " U R                  U5      6 nU(       a   U R                  R                  SUUS.5        g U R                  R                  U5        g )Nr   rs   )r   make_propertiesr$   rv   )r*   rT   rH   properties_dicts       r+   ry   GeoJSONBackend.add_entity  s_    *.*E*E!!*-+
 NN!!%"1 & NN!!&)r.   c                    U R                   (       a  U R                   nO-[        U R                  UR                  U R                  -  5      nUR
                  [        US5      UR                  4$ )Nr4   r~   r   s      r+   r   GeoJSONBackend.make_properties  s^      00L##Z%:%:T=T=T%TL   %a"8*:J:JKKr.   c           
     l    U R                  [        S[        U R                  U5      5      5      U5        g )NPoint)ry   geojson_objectr   r   r   s      r+   r   GeoJSONBackend.draw_point  s*    7D)A)A#)F$GH*	
r.   c           	     p    U R                   nU R                  [        SU" U5      U" U5      /5      U5        g )N
LineString)r   ry   r   )r*   r   r   rH   tfs        r+   r   GeoJSONBackend.draw_line  s3    %%<"U)RW)=>	
r.   c                    [        U5      n[        U5      S:X  a  g U R                  nU VVs/ s H  u  pEU" U5      U" U5      4PM     nnnU R                  [	        SU5      U5        g s  snnf )Nr   MultiLineString)r   r   r   ry   r   )r*   r   rH   r   r   r   
json_liness          r+   r   GeoJSONBackend.draw_solid_lines  sc     Uu:?%%167r!uben
7'8*EzR 8s   A)c                    [        U5      S:X  a  g U R                  nUR                  U R                  S9 Vs/ s H
  oC" U5      PM     nnU R	                  [        SU5      U5        g s  snf )Nr   )distancer   )r   r   
flatteningr%   ry   r   )r*   r   rH   r   r   r   s         r+   r   GeoJSONBackend.draw_path  sa    t9>%%#'??D<L<L?#MN#MaBqE#MN|X>
K Os   A(c           	        [        U5      n[        U5      S:X  a  g / nU HB  n[        U5      (       d  M  UR                  [        X@R                  U R
                  S95        MD     U(       a  U R                  [        SU5      U5        g g )Nr   )r%   r   MultiPolygon)r   r   extendgeojson_polygonsr%   r   ry   r   )r*   r   rH   polygonsr   s        r+   r    GeoJSONBackend.draw_filled_paths  sw     Uu:?)+D4yy$*:*:t?W?W  OON>8DjQ r.   c                ,   UR                  5       n[        U5      S:  a  g US   R                  US   5      (       d  UR                  US   5        U R                  nU R                  [        SU Vs/ s H
  oT" U5      PM     sn/5      U5        g s  snf )Nr   r   r   Polygon)r   r   r   rv   r   ry   r   )r*   r   rH   r   r   r   s         r+   r   "GeoJSONBackend.draw_filled_polygon  s      &0x=1{""8B<00OOHQK(%%9x'@x!1x'@&ABJ	
'@s   2B)r   r   )r   r   r   r   r[   r\   )r[   r   )rT   r   rH   r   )rH   r   r[   ztuple[str, float, str]r   r   r   r   r   r   )r^   r_   r`   ra   r   r   r   r,   r   r2   ry   r   r   r   r   r   r   r   rd   r   r   s   @r+   r   r   i  s$   /f -=(42)2 &2 
	2 2 P P*"L 
 

 
 
 S0S>OS	S S L L R'R5FR	R R$ 
 
.?
	
 
r.   c                
    XS.$ )N)rt   coordinatesr1   )namer  s     r+   r   r     s    55r.   c                t   U R                   (       a  [        S5      eU R                  U5       Vs/ s H
  oC" U5      PM     nnU R                  (       d#  U R                  nUR                  U" U5      5        U R                  5       nU(       a  U(       a  U(       d  U(       a  UR                  5         U$ s  snf )a  Returns a linear ring according to the GeoJSON specs.

-  A linear ring is a closed LineString with four or more positions.
-  The first and last positions are equivalent, and they MUST contain
   identical values; their representation SHOULD also be identical.
-  A linear ring is the boundary of a surface or the boundary of a
   hole in a surface.
-  A linear ring MUST follow the right-hand rule with respect to the
   area it bounds, i.e., exterior rings are counterclockwise, and
   holes are clockwise.

zmulti-paths not allowed)has_sub_paths	TypeErrorr   	is_closedr   rv   has_clockwise_orientationreverse)r   is_holer%   r   r   r   r   	clockwises           r+   geojson_ringr    s     122%)__[%AB%Abe%AHB>>

5	"..0I	7yO Cs   B5c           
     ^   U R                  5       n[        U5      S:X  a  / $ [        U5      S:X  a  [        US   SX5      //$ [        R                  " U5      n/ nU H  n[        US   SX5      /n[        U5      S:  a  US   n[        U[        5      (       a  UR                  [        USX5      5        M[  [        U[        [        45      (       aE  U H?  n	[        U	[        [        45      (       a  U	S   n	UR                  [        U	SX5      5        MA     UR                  U5        M     U$ )zReturns a list of polygons, where each polygon is a list of an exterior path and
optional holes e.g. [[ext0, hole0, hole1], [ext1], [ext2, hole0], ...].

r   r   FT)
	sub_pathsr   r  r   make_polygon_structure
isinstancer   rv   tupler   )
r   r%   r   r  r  r  polygongeojson_polygonholesholes
             r+   r  r  ,  s!    !% 0I
9~	
9~ilE;CDEE--i8H-/UK<+
 w<! AJE%**&&|E4'QR%%//!D!$66#Aw#**<dK+TU	 " 	0% & r.   r   )r   r   r[   z	list[Any])rM   r]   r   floatr}   r]   r[   r   r   )gư>)r   r  r[   r   )r	  r]   r  r   r[   r   )
r   r   r  boolr%   r  r   r   r[   r   )r   r   r%   r  r   r   r[   zlist[GeoJsonPolygon])<
__future__r   typingr   r   r   r   r   r	   r
   r   typing_extensionsr   r   rb   r8   
ezdxf.mathr   r   
ezdxf.pathr   r   ezdxf.npshapesr   r   
type_hintsr   backendr   r   r   r   r?   r   rH   r   __all__CUSTOM_JSON_SPECSr   r   r   r   r   r   r   r   r]   r  r   __annotations__r   r   r   r   r   r   r   r   r  r  r1   r.   r+   <module>r)     sz   # V V V 1 
  2 ' 5  F F ! )  0
1W t3# 3l 
lV lV^  0 &sE3&7c3h&GH H#TFE%,,?$?@y @uUE\*+i + !J	 &&$"a
\ a
H6
!05;H	6"
"!&",9""r.   