pycadkit 0.2.0__tar.gz → 0.3.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (177) hide show
  1. {pycadkit-0.2.0 → pycadkit-0.3.0}/Cargo.lock +10 -10
  2. {pycadkit-0.2.0 → pycadkit-0.3.0}/Cargo.toml +7 -7
  3. {pycadkit-0.2.0 → pycadkit-0.3.0}/PKG-INFO +1 -1
  4. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit/examples/interchange.rs +1 -0
  5. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-core/src/model.rs +30 -2
  6. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dgn/src/map/mod.rs +100 -30
  7. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dgn/src/map/v8.rs +0 -42
  8. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dgn/src/native/decode_v8.rs +9 -1
  9. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dgn/src/native/element.rs +6 -0
  10. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dgn/src/native/v7.rs +3 -0
  11. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dgn/src/writer/encode.rs +106 -22
  12. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dgn/src/writer/mod.rs +281 -62
  13. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dgn/src/writer/raster.rs +83 -40
  14. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dgn/src/writer/tables.rs +86 -2
  15. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dgn/src/writer/tests/application.rs +44 -0
  16. pycadkit-0.3.0/crates/cadkit-dgn/src/writer/tests/microstation.rs +531 -0
  17. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dgn/src/writer/tests/raster.rs +4 -3
  18. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dgn/src/writer/tests/regressions.rs +3 -0
  19. pycadkit-0.3.0/crates/cadkit-dgn/src/writer/tests/text.rs +358 -0
  20. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dgn/src/writer/tests.rs +5 -0
  21. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dgn/src/writer/text.rs +31 -2
  22. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dgn/tests/private_corpus.rs +40 -7
  23. pycadkit-0.3.0/crates/cadkit-dgn/tests/v8_range.rs +61 -0
  24. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dwg/src/mapping/entity.rs +1 -0
  25. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dxf/src/reader/entities.rs +1 -0
  26. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dxf/tests/review_fixes.rs +1 -0
  27. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dxf/tests/synthetic_write.rs +2 -0
  28. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-gml/src/mapping.rs +1 -0
  29. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-gml/tests/support/export_cases.rs +1 -0
  30. pycadkit-0.2.0/crates/cadkit-dgn/src/writer/tests/text.rs +0 -113
  31. {pycadkit-0.2.0 → pycadkit-0.3.0}/LICENSE-APACHE +0 -0
  32. {pycadkit-0.2.0 → pycadkit-0.3.0}/LICENSE-MIT +0 -0
  33. {pycadkit-0.2.0 → pycadkit-0.3.0}/NOTICE +0 -0
  34. {pycadkit-0.2.0 → pycadkit-0.3.0}/README.md +0 -0
  35. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit/Cargo.toml +0 -0
  36. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit/LICENSE-APACHE +0 -0
  37. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit/LICENSE-MIT +0 -0
  38. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit/NOTICE +0 -0
  39. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit/README.md +0 -0
  40. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit/src/lib.rs +0 -0
  41. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-core/Cargo.toml +0 -0
  42. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-core/LICENSE-APACHE +0 -0
  43. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-core/LICENSE-MIT +0 -0
  44. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-core/NOTICE +0 -0
  45. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-core/README.md +0 -0
  46. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-core/src/aci.rs +0 -0
  47. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-core/src/bytes.rs +0 -0
  48. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-core/src/error.rs +0 -0
  49. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-core/src/export.rs +0 -0
  50. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-core/src/geom.rs +0 -0
  51. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-core/src/geom_ops.rs +0 -0
  52. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-core/src/lib.rs +0 -0
  53. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-core/src/ops.rs +0 -0
  54. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-core/src/options.rs +0 -0
  55. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-core/src/polygon.rs +0 -0
  56. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-core/src/svg.rs +0 -0
  57. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-core/src/text.rs +0 -0
  58. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-core/src/units.rs +0 -0
  59. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dgn/Cargo.toml +0 -0
  60. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dgn/LICENSE-APACHE +0 -0
  61. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dgn/LICENSE-MIT +0 -0
  62. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dgn/NOTICE +0 -0
  63. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dgn/README.md +0 -0
  64. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dgn/examples/dgn_summary.rs +0 -0
  65. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dgn/examples/raster_structure.rs +0 -0
  66. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dgn/src/budget.rs +0 -0
  67. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dgn/src/cfb.rs +0 -0
  68. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dgn/src/fuzz_tests.rs +0 -0
  69. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dgn/src/le.rs +0 -0
  70. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dgn/src/level_names.rs +0 -0
  71. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dgn/src/lib.rs +0 -0
  72. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dgn/src/map/v7.rs +0 -0
  73. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dgn/src/native/linkage.rs +0 -0
  74. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dgn/src/native/mod.rs +0 -0
  75. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dgn/src/native/v8.rs +0 -0
  76. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dgn/src/palette.rs +0 -0
  77. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dgn/src/text.rs +0 -0
  78. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dgn/src/writer/container.rs +0 -0
  79. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dgn/src/writer/polyline.rs +0 -0
  80. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dgn/src/zlib.rs +0 -0
  81. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dgn/tests/common/mod.rs +0 -0
  82. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dgn/tests/robustness.rs +0 -0
  83. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dgn/tests/v7_corpus.rs +0 -0
  84. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dgn/tests/v8_oracle.rs +0 -0
  85. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dgn/tests/v8_public.rs +0 -0
  86. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dwg/Cargo.toml +0 -0
  87. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dwg/LICENSE-APACHE +0 -0
  88. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dwg/LICENSE-MIT +0 -0
  89. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dwg/NOTICE +0 -0
  90. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dwg/README.md +0 -0
  91. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dwg/examples/docsummary.rs +0 -0
  92. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dwg/examples/dwgdump.rs +0 -0
  93. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dwg/src/bits.rs +0 -0
  94. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dwg/src/classes.rs +0 -0
  95. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dwg/src/codepage.rs +0 -0
  96. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dwg/src/container/lz77_r2004.rs +0 -0
  97. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dwg/src/container/lz77_r2007.rs +0 -0
  98. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dwg/src/container/mod.rs +0 -0
  99. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dwg/src/container/r13.rs +0 -0
  100. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dwg/src/container/r2004.rs +0 -0
  101. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dwg/src/container/r2007.rs +0 -0
  102. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dwg/src/container/reed_solomon.rs +0 -0
  103. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dwg/src/crc.rs +0 -0
  104. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dwg/src/handles.rs +0 -0
  105. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dwg/src/header.rs +0 -0
  106. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dwg/src/lib.rs +0 -0
  107. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dwg/src/mapping/mod.rs +0 -0
  108. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dwg/src/native/entities.rs +0 -0
  109. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dwg/src/native/mod.rs +0 -0
  110. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dwg/src/object/annotation.rs +0 -0
  111. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dwg/src/object/curves.rs +0 -0
  112. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dwg/src/object/entities.rs +0 -0
  113. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dwg/src/object/hatch.rs +0 -0
  114. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dwg/src/object/misc.rs +0 -0
  115. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dwg/src/object/mod.rs +0 -0
  116. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dwg/src/object/registry.rs +0 -0
  117. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dwg/src/object/tables.rs +0 -0
  118. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dwg/src/reader.rs +0 -0
  119. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dwg/src/version.rs +0 -0
  120. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dwg/tests/corpus.rs +0 -0
  121. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dwg/tests/oracle.rs +0 -0
  122. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dwg/tests/robustness.rs +0 -0
  123. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dxf/Cargo.toml +0 -0
  124. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dxf/LICENSE-APACHE +0 -0
  125. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dxf/LICENSE-MIT +0 -0
  126. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dxf/NOTICE +0 -0
  127. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dxf/README.md +0 -0
  128. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dxf/examples/dump.rs +0 -0
  129. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dxf/src/lib.rs +0 -0
  130. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dxf/src/native/mod.rs +0 -0
  131. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dxf/src/native/text.rs +0 -0
  132. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dxf/src/ocs.rs +0 -0
  133. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dxf/src/reader/common.rs +0 -0
  134. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dxf/src/reader/hatch.rs +0 -0
  135. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dxf/src/reader/mod.rs +0 -0
  136. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dxf/src/reader/records.rs +0 -0
  137. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dxf/src/reader/tables.rs +0 -0
  138. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dxf/src/writer/curves.rs +0 -0
  139. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dxf/src/writer/entities.rs +0 -0
  140. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dxf/src/writer/mod.rs +0 -0
  141. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dxf/src/writer/out.rs +0 -0
  142. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dxf/tests/ascii_vs_binary.rs +0 -0
  143. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dxf/tests/common/mod.rs +0 -0
  144. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dxf/tests/compare_reader_with_ezdxf.py +0 -0
  145. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dxf/tests/robustness.rs +0 -0
  146. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dxf/tests/roundtrip.rs +0 -0
  147. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dxf/tests/synthetic_read.rs +0 -0
  148. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-dxf/tests/validate_with_ezdxf.py +0 -0
  149. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-gml/Cargo.toml +0 -0
  150. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-gml/LICENSE-APACHE +0 -0
  151. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-gml/LICENSE-MIT +0 -0
  152. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-gml/NOTICE +0 -0
  153. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-gml/README.md +0 -0
  154. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-gml/src/curves.rs +0 -0
  155. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-gml/src/export.rs +0 -0
  156. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-gml/src/geometry.rs +0 -0
  157. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-gml/src/lib.rs +0 -0
  158. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-gml/src/native.rs +0 -0
  159. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-gml/src/tkgm.rs +0 -0
  160. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-gml/src/validate.rs +0 -0
  161. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-gml/src/xml.rs +0 -0
  162. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-gml/tests/roundtrip.rs +0 -0
  163. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-gml/tests/support/tkgm_cases.rs +0 -0
  164. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-py/Cargo.toml +0 -0
  165. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-py/LICENSE-APACHE +0 -0
  166. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-py/LICENSE-MIT +0 -0
  167. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-py/NOTICE +0 -0
  168. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-py/README.md +0 -0
  169. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-py/src/lib.rs +0 -0
  170. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-py/tests/conftest.py +0 -0
  171. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-py/tests/test_cadkit.py +0 -0
  172. {pycadkit-0.2.0 → pycadkit-0.3.0}/crates/cadkit-py/tests/test_citygml.py +0 -0
  173. {pycadkit-0.2.0 → pycadkit-0.3.0}/pyproject.toml +0 -0
  174. {pycadkit-0.2.0 → pycadkit-0.3.0}/python/cadkit/__init__.py +0 -0
  175. {pycadkit-0.2.0 → pycadkit-0.3.0}/python/cadkit/__init__.pyi +0 -0
  176. {pycadkit-0.2.0 → pycadkit-0.3.0}/python/cadkit/_cadkit.pyi +0 -0
  177. {pycadkit-0.2.0 → pycadkit-0.3.0}/python/cadkit/py.typed +0 -0
@@ -66,7 +66,7 @@ checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649"
66
66
 
67
67
  [[package]]
68
68
  name = "cadkit"
69
- version = "0.2.0"
69
+ version = "0.3.0"
70
70
  dependencies = [
71
71
  "cadkit-core",
72
72
  "cadkit-dgn",
@@ -78,7 +78,7 @@ dependencies = [
78
78
 
79
79
  [[package]]
80
80
  name = "cadkit-capi"
81
- version = "0.2.0"
81
+ version = "0.3.0"
82
82
  dependencies = [
83
83
  "cadkit",
84
84
  "serde",
@@ -87,7 +87,7 @@ dependencies = [
87
87
 
88
88
  [[package]]
89
89
  name = "cadkit-cli"
90
- version = "0.2.0"
90
+ version = "0.3.0"
91
91
  dependencies = [
92
92
  "cadkit",
93
93
  "clap",
@@ -96,7 +96,7 @@ dependencies = [
96
96
 
97
97
  [[package]]
98
98
  name = "cadkit-core"
99
- version = "0.2.0"
99
+ version = "0.3.0"
100
100
  dependencies = [
101
101
  "serde",
102
102
  "serde_json",
@@ -105,7 +105,7 @@ dependencies = [
105
105
 
106
106
  [[package]]
107
107
  name = "cadkit-dgn"
108
- version = "0.2.0"
108
+ version = "0.3.0"
109
109
  dependencies = [
110
110
  "cadkit-core",
111
111
  "cfb",
@@ -116,7 +116,7 @@ dependencies = [
116
116
 
117
117
  [[package]]
118
118
  name = "cadkit-dwg"
119
- version = "0.2.0"
119
+ version = "0.3.0"
120
120
  dependencies = [
121
121
  "cadkit-core",
122
122
  "cadkit-dxf",
@@ -126,7 +126,7 @@ dependencies = [
126
126
 
127
127
  [[package]]
128
128
  name = "cadkit-dxf"
129
- version = "0.2.0"
129
+ version = "0.3.0"
130
130
  dependencies = [
131
131
  "cadkit-core",
132
132
  "encoding_rs",
@@ -135,7 +135,7 @@ dependencies = [
135
135
 
136
136
  [[package]]
137
137
  name = "cadkit-gml"
138
- version = "0.2.0"
138
+ version = "0.3.0"
139
139
  dependencies = [
140
140
  "cadkit-core",
141
141
  "quick-xml",
@@ -145,7 +145,7 @@ dependencies = [
145
145
 
146
146
  [[package]]
147
147
  name = "cadkit-py"
148
- version = "0.2.0"
148
+ version = "0.3.0"
149
149
  dependencies = [
150
150
  "cadkit",
151
151
  "pyo3",
@@ -155,7 +155,7 @@ dependencies = [
155
155
 
156
156
  [[package]]
157
157
  name = "cadkit-wasm"
158
- version = "0.2.0"
158
+ version = "0.3.0"
159
159
  dependencies = [
160
160
  "cadkit",
161
161
  "js-sys",
@@ -4,7 +4,7 @@ members = ["crates/*"]
4
4
  exclude = ["fuzz"]
5
5
 
6
6
  [workspace.package]
7
- version = "0.2.0"
7
+ version = "0.3.0"
8
8
  edition = "2024"
9
9
  rust-version = "1.85"
10
10
  license = "MIT OR Apache-2.0"
@@ -14,12 +14,12 @@ keywords = ["cad", "dwg", "dgn", "dxf", "citygml"]
14
14
  categories = ["parser-implementations", "graphics", "encoding", "science::geo"]
15
15
 
16
16
  [workspace.dependencies]
17
- cadkit-core = { path = "crates/cadkit-core", version = "0.2.0" }
18
- cadkit-dgn = { path = "crates/cadkit-dgn", version = "0.2.0" }
19
- cadkit-dwg = { path = "crates/cadkit-dwg", version = "0.2.0" }
20
- cadkit-dxf = { path = "crates/cadkit-dxf", version = "0.2.0" }
21
- cadkit-gml = { path = "crates/cadkit-gml", version = "0.2.0" }
22
- cadkit = { path = "crates/cadkit", version = "0.2.0" }
17
+ cadkit-core = { path = "crates/cadkit-core", version = "0.3.0" }
18
+ cadkit-dgn = { path = "crates/cadkit-dgn", version = "0.3.0" }
19
+ cadkit-dwg = { path = "crates/cadkit-dwg", version = "0.3.0" }
20
+ cadkit-dxf = { path = "crates/cadkit-dxf", version = "0.3.0" }
21
+ cadkit-gml = { path = "crates/cadkit-gml", version = "0.3.0" }
22
+ cadkit = { path = "crates/cadkit", version = "0.3.0" }
23
23
  serde = { version = "1", features = ["derive"] }
24
24
  serde_json = "1"
25
25
  thiserror = "2"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pycadkit
3
- Version: 0.2.0
3
+ Version: 0.3.0
4
4
  Classifier: Development Status :: 3 - Alpha
5
5
  Classifier: Intended Audience :: Developers
6
6
  Classifier: Intended Audience :: Science/Research
@@ -75,6 +75,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
75
75
  set: Some("Örnek".into()),
76
76
  position: None,
77
77
  invisible: true,
78
+ ..Default::default()
78
79
  });
79
80
  if let EntityKind::Polygon {
80
81
  exterior,
@@ -722,7 +722,7 @@ pub enum Lineweight {
722
722
  }
723
723
 
724
724
  /// Non-graphic data attached to an entity (DWG ATTRIB, DGN tag, item-type property).
725
- #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
725
+ #[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)]
726
726
  pub struct Attribute {
727
727
  /// Tag / property name.
728
728
  pub tag: String,
@@ -734,13 +734,41 @@ pub struct Attribute {
734
734
  pub position: Option<Point3>,
735
735
  /// The attribute is not displayed.
736
736
  pub invisible: bool,
737
+ /// Layer of the attribute's own record when the format stores one (a DGN tag
738
+ /// element has its own level). `None` uses the owning entity's layer.
739
+ #[serde(default, skip_serializing_if = "Option::is_none")]
740
+ pub layer: Option<String>,
741
+ /// How the value text is drawn at `position`; `None` when unknown or not drawn.
742
+ #[serde(default, skip_serializing_if = "Option::is_none")]
743
+ pub display: Option<AttributeDisplay>,
744
+ /// Format-specific data with no neutral field (e.g. `dgn.color_index`, `dgn.weight`).
745
+ #[serde(default, skip_serializing_if = "Props::is_empty")]
746
+ pub props: Props,
747
+ }
748
+
749
+ /// Text presentation of a displayed attribute value.
750
+ #[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)]
751
+ pub struct AttributeDisplay {
752
+ /// Text height, in drawing units.
753
+ pub height: f64,
754
+ /// Character width, in drawing units (DGN stores it separately from the height).
755
+ pub width: f64,
756
+ /// Text style (DGN font) name; `None` leaves the choice to the writer's default.
757
+ pub style: Option<String>,
758
+ /// Horizontal alignment of the text about `Attribute::position`.
759
+ pub halign: HAlign,
760
+ /// Vertical alignment of the text about `Attribute::position`.
761
+ pub valign: VAlign,
762
+ /// Rotation about the drawing Z axis, in radians.
763
+ pub rotation: f64,
737
764
  }
738
765
 
739
766
  /// A loosely typed value for attributes and props.
740
- #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
767
+ #[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)]
741
768
  #[serde(untagged)]
742
769
  pub enum Value {
743
770
  /// No value.
771
+ #[default]
744
772
  Null,
745
773
  /// Boolean.
746
774
  Bool(bool),
@@ -8,8 +8,8 @@ use std::f64::consts::{FRAC_PI_2, TAU};
8
8
 
9
9
  use cadkit_core::geom_ops::{arbitrary_axes, clamped_uniform_knots};
10
10
  use cadkit_core::{
11
- Attribute, Color, Entity, EntityKind, GroupKind, HAlign, LengthUnit, Linetype, Lineweight,
12
- Point3, Props, Raw, TextStyle, VAlign, Value, Vec3, Vertex, Warning,
11
+ Attribute, AttributeDisplay, Color, Entity, EntityKind, GroupKind, HAlign, LengthUnit,
12
+ Linetype, Lineweight, Point3, Props, Raw, TextStyle, VAlign, Value, Vec3, Vertex, Warning,
13
13
  };
14
14
 
15
15
  use crate::native::element::{
@@ -203,8 +203,6 @@ pub(crate) struct Mapper {
203
203
  pub(crate) xattributes: HashMap<u64, Vec<u32>>,
204
204
  /// Raster frame id -> image path.
205
205
  pub(crate) raster_paths: HashMap<u64, (Option<String>, Option<String>)>,
206
- /// Raster frames whose stored extent corner and file are shared with another frame.
207
- pub(crate) shared_raster_extent: HashSet<u64>,
208
206
  /// Aggregated warnings: code -> (count, first message).
209
207
  counts: BTreeMap<String, (u64, String)>,
210
208
  pub(crate) warnings: Vec<Warning>,
@@ -226,7 +224,6 @@ impl Mapper {
226
224
  attached: HashSet::new(),
227
225
  xattributes: HashMap::new(),
228
226
  raster_paths: HashMap::new(),
229
- shared_raster_extent: HashSet::new(),
230
227
  counts: BTreeMap::new(),
231
228
  warnings: Vec::new(),
232
229
  }
@@ -402,6 +399,14 @@ impl Mapper {
402
399
  );
403
400
  }
404
401
  p.insert("dgn.properties".into(), Value::Int(i64::from(h.properties)));
402
+ // Undocumented type-word flags MicroStation sets on its graphics (`0x00C0`);
403
+ // kept so a rewrite reproduces them.
404
+ if h.type_flags & 0x00c0 != 0 {
405
+ p.insert(
406
+ "dgn.type_flags".into(),
407
+ Value::Int(i64::from(h.type_flags & 0x00c0)),
408
+ );
409
+ }
405
410
  if h.properties & 0x8000 != 0 && matches!(h.type_code, 6 | 14) {
406
411
  p.insert("dgn.hole".into(), Value::Bool(true));
407
412
  }
@@ -441,7 +446,10 @@ impl Mapper {
441
446
  }
442
447
  if let Some(id) = h.id {
443
448
  if let Some(attrs) = self.pending_tags.remove(&id) {
444
- e.attributes = attrs.into_iter().map(|(_, a)| a).collect();
449
+ e.attributes = attrs
450
+ .into_iter()
451
+ .map(|(_, a)| relative_to_owner(a, &e))
452
+ .collect();
445
453
  }
446
454
  }
447
455
  e
@@ -561,7 +569,8 @@ impl Mapper {
561
569
  type_name: "dgn.type_37".into(),
562
570
  },
563
571
  );
564
- e.attributes.push(self.attribute(t, &item.el.header, xf));
572
+ let a = self.attribute(t, &item.el.header, xf);
573
+ e.attributes.push(relative_to_owner(a, &e));
565
574
  return Some(e);
566
575
  }
567
576
  ElementData::RasterFrame { .. } => self.image(item, xf),
@@ -670,15 +679,6 @@ impl Mapper {
670
679
  Value::List([a.x, a.y, a.z, b.x, b.y, b.z].map(Value::Float).to_vec()),
671
680
  );
672
681
  }
673
- if item
674
- .el
675
- .header
676
- .id
677
- .is_some_and(|id| self.shared_raster_extent.contains(&id))
678
- {
679
- e.props
680
- .insert("dgn.raster_extent_shared".into(), Value::Bool(true));
681
- }
682
682
  e.props.insert(
683
683
  "dgn.raster_matrix".into(),
684
684
  Value::List(matrix.iter().map(|v| Value::Float(*v)).collect()),
@@ -925,9 +925,10 @@ impl Mapper {
925
925
  }
926
926
  }
927
927
 
928
- /// A tag as an attribute (`position` = origin + offset).
928
+ /// A tag as an attribute (`position` = origin + offset). The tag element's own level,
929
+ /// its text presentation and its symbology are kept so a writer can reproduce it.
929
930
  pub(crate) fn attribute(
930
- &self,
931
+ &mut self,
931
932
  t: &TagData,
932
933
  h: &crate::native::element::ElementHeader,
933
934
  xf: &Xf,
@@ -937,18 +938,66 @@ impl Mapper {
937
938
  .or(t.set_number.map(u64::from))
938
939
  .and_then(|k| self.tag_sets.get(&k));
939
940
  let def = set.and_then(|s| s.tags.iter().find(|d| d.id == t.tag_index));
941
+ let tag = def
942
+ .map(|d| d.name.clone())
943
+ .unwrap_or_else(|| format!("tag_{}", t.tag_index));
944
+ let set_name = set.and_then(|s| s.name.clone());
940
945
  let [ox, oy, oz] = t.origin;
941
946
  let [dx, dy, dz] = t.offset;
942
947
  let has_pos = t.origin != [0.0; 3] || t.offset != [0.0; 3];
948
+ // Observed: hidden tags carry 0x0080 in the property word (FORMAT_NOTES).
949
+ let invisible = h.properties & 0x0080 != 0;
950
+ let mut props = Props::new();
951
+ let mut layer = None;
952
+ if h.has_display_header {
953
+ layer = Some(self.level_name(h.level));
954
+ props.insert("dgn.color_index".into(), Value::Int(i64::from(h.color)));
955
+ props.insert("dgn.weight".into(), Value::Int(i64::from(h.weight)));
956
+ props.insert("dgn.style".into(), Value::Int(i64::from(h.style)));
957
+ if h.graphic_group != 0 {
958
+ props.insert(
959
+ "dgn.graphic_group".into(),
960
+ Value::Int(i64::from(h.graphic_group)),
961
+ );
962
+ }
963
+ // Only MicroStation's undecoded property bits add anything to `invisible`.
964
+ if h.properties & 0x0600 != 0 {
965
+ props.insert("dgn.properties".into(), Value::Int(i64::from(h.properties)));
966
+ }
967
+ if h.type_flags & 0x00c0 != 0 {
968
+ props.insert(
969
+ "dgn.type_flags".into(),
970
+ Value::Int(i64::from(h.type_flags & 0x00c0)),
971
+ );
972
+ }
973
+ }
974
+ // V7 tags and hidden V8 tags without a text size have no usable presentation.
975
+ let display = (t.size[1] > 0.0 && t.size[0] > 0.0).then(|| {
976
+ self.used_fonts.insert(t.font);
977
+ props.insert("dgn.font_number".into(), Value::Int(i64::from(t.font)));
978
+ props.insert(
979
+ "dgn.justification".into(),
980
+ Value::Int(i64::from(t.justification)),
981
+ );
982
+ let (halign, valign, _, _) = justification(t.justification);
983
+ AttributeDisplay {
984
+ height: xf.dist(t.size[1]),
985
+ width: xf.dist(t.size[0]),
986
+ style: Some(self.font_style_name(t.font)),
987
+ halign,
988
+ valign,
989
+ rotation: tag_rotation(t.quaternion),
990
+ }
991
+ });
943
992
  Attribute {
944
- tag: def
945
- .map(|d| d.name.clone())
946
- .unwrap_or_else(|| format!("tag_{}", t.tag_index)),
993
+ tag,
947
994
  value: tag_value(&t.value),
948
- set: set.and_then(|s| s.name.clone()),
995
+ set: set_name,
949
996
  position: has_pos.then(|| xf.pt([ox + dx, oy + dy, oz + dz])),
950
- // Observed: hidden tags carry 0x0080 in the property word (FORMAT_NOTES).
951
- invisible: h.properties & 0x0080 != 0,
997
+ invisible,
998
+ layer,
999
+ display,
1000
+ props,
952
1001
  }
953
1002
  }
954
1003
  }
@@ -1071,8 +1120,9 @@ pub(crate) fn frame_placement(
1071
1120
  let [m00, m01, _, m03, m10, m11, _, m13, m20, m21, _, m23, ..] = *m;
1072
1121
  let a = Vec3::new(m00, m10, m20);
1073
1122
  let b = Vec3::new(m01, m11, m21);
1074
- let [cx, cy] = corner?;
1075
- let (dx, dy) = (cx - m03, cy - m13);
1123
+ // `0x108`/`0x110` is the frame's extent from its origin (the same values as the
1124
+ // element range extent on the private sample), not an absolute corner.
1125
+ let [dx, dy] = corner?;
1076
1126
  let det = a.x * b.y - a.y * b.x;
1077
1127
  if !det.is_finite() || det.abs() <= 1e-12 * a.length() * b.length() {
1078
1128
  return None;
@@ -1154,6 +1204,28 @@ pub(crate) fn justification(code: u16) -> (HAlign, VAlign, f64, f64) {
1154
1204
  (h, v, fx, fy)
1155
1205
  }
1156
1206
 
1207
+ /// Keeps only what a tag element does not share with its owner: `layer` stays `None` on the
1208
+ /// owner's level, and symbology/flag props equal to the owner's are dropped.
1209
+ fn relative_to_owner(mut a: Attribute, owner: &Entity) -> Attribute {
1210
+ if a.layer.is_some() && a.layer == owner.layer {
1211
+ a.layer = None;
1212
+ }
1213
+ a.props
1214
+ .retain(|key, value| owner.props.get(key) != Some(value) || key == "dgn.font_number");
1215
+ a
1216
+ }
1217
+
1218
+ /// Rotation of a displayed tag about +Z in radians, from its stored quaternion (same
1219
+ /// convention as text, see [`Rotation::matrix`]). An all-zero quaternion means none.
1220
+ pub(crate) fn tag_rotation(q: [f64; 4]) -> f64 {
1221
+ if q.iter().all(|v| *v == 0.0) {
1222
+ return 0.0;
1223
+ }
1224
+ let [m00, _, _, m10, ..] = Rotation::Quaternion(q).matrix();
1225
+ let a = m10.atan2(m00);
1226
+ if a.abs() < 1e-12 { 0.0 } else { a }
1227
+ }
1228
+
1157
1229
  /// Text length in UOR and whether it is estimated (`characters x character width`, the
1158
1230
  /// estimate GDAL dgnlib's writer uses for text bounds).
1159
1231
  fn text_length(t: &TextData) -> (f64, bool) {
@@ -1458,15 +1530,13 @@ mod tests {
1458
1530
  #[test]
1459
1531
  fn raster_placement_follows_the_matrix() {
1460
1532
  // 30 degree rotation, 2 UOR per pixel, translation (100, 50); a 300 x 200 pixel image.
1533
+ // The frame stores its extent from the translation (rotated frames unverified).
1461
1534
  let (s, c) = 30f64.to_radians().sin_cos();
1462
1535
  let (a, b) = ([2.0 * c, 2.0 * s], [-2.0 * s, 2.0 * c]);
1463
1536
  let m = [
1464
1537
  a[0], b[0], 0.0, 100.0, a[1], b[1], 0.0, 50.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0,
1465
1538
  ];
1466
- let corner = [
1467
- 100.0 + 300.0 * a[0] + 200.0 * b[0],
1468
- 50.0 + 300.0 * a[1] + 200.0 * b[1],
1469
- ];
1539
+ let corner = [300.0 * a[0] + 200.0 * b[0], 300.0 * a[1] + 200.0 * b[1]];
1470
1540
  let (o, u, v) = frame_placement(&m, Some(corner)).unwrap();
1471
1541
  assert_eq!(o, [100.0, 50.0, 0.0]);
1472
1542
  assert!(close(u.x, 600.0 * c) && close(u.y, 600.0 * s));
@@ -203,48 +203,6 @@ fn map_file(file: &V8File, options: &ReadOptions, enc: &'static encoding_rs::Enc
203
203
  enc,
204
204
  options,
205
205
  );
206
- // Frames that store the same extent corner for the same file: their extents are then
207
- // not image footprints (private sample: 8 frames, one file, one corner).
208
- m.shared_raster_extent.clear();
209
- let mut by_extent: HashMap<(i64, i64, Option<String>), Vec<u64>> = HashMap::new();
210
- for it in &graphic {
211
- if let (
212
- ElementData::RasterFrame {
213
- corner: Some([cx, cy]),
214
- ..
215
- },
216
- Some(id),
217
- ) = (&it.el.data, it.el.header.id)
218
- {
219
- let file = m
220
- .raster_paths
221
- .get(&id)
222
- .and_then(|(n, f)| f.clone().or_else(|| n.clone()));
223
- by_extent
224
- .entry((cx.round() as i64, cy.round() as i64, file))
225
- .or_default()
226
- .push(id);
227
- }
228
- }
229
- let shared: Vec<u64> = by_extent
230
- .into_values()
231
- .filter(|v| v.len() > 1)
232
- .flatten()
233
- .collect();
234
- if !shared.is_empty() {
235
- m.warn(
236
- "dgn.raster_extent_shared",
237
- format!(
238
- "{} raster frames share one stored extent corner and file; their \
239
- rectangles (as stored, equal to the element ranges) are probably not \
240
- image footprints",
241
- shared.len()
242
- ),
243
- None,
244
- None,
245
- );
246
- m.shared_raster_extent.extend(shared);
247
- }
248
206
  m.pending_tags.clear();
249
207
  m.attached.clear();
250
208
  for (i, it) in graphic.iter().enumerate() {
@@ -42,9 +42,14 @@ pub fn decode(raw: &RawElement, enc: &'static Encoding, limits: &Limits) -> Elem
42
42
  } else {
43
43
  0
44
44
  };
45
+ // The second range triple is the extent (high - low) for every graphic type, not
46
+ // an absolute corner: MicroStation and ODA files agree on this (FORMAT_NOTES,
47
+ // "Element range").
45
48
  let range = if display {
46
49
  let r = |o: usize| le::i64_at(b, o).map(|v| v as f64).unwrap_or(0.0);
47
- Some([[r(0x38), r(0x40), r(0x48)], [r(0x50), r(0x58), r(0x60)]])
50
+ let low = [r(0x38), r(0x40), r(0x48)];
51
+ let span = [r(0x50), r(0x58), r(0x60)];
52
+ Some([low, [low[0] + span[0], low[1] + span[1], low[2] + span[2]]])
48
53
  } else {
49
54
  None
50
55
  };
@@ -420,6 +425,9 @@ impl Decoder<'_> {
420
425
  le::f64_at(self.b, 0xf0).unwrap_or(0.0) * TEXT_MULT_TO_UOR,
421
426
  le::f64_at(self.b, 0xf8).unwrap_or(0.0) * TEXT_MULT_TO_UOR,
422
427
  ],
428
+ font: le::u32_at(self.b, 0x12c).unwrap_or(0),
429
+ justification: le::u16_at(self.b, 0x130).unwrap_or(0),
430
+ quaternion: le::f64s::<4>(self.b, 0x100).unwrap_or([0.0; 4]),
423
431
  })
424
432
  }
425
433
 
@@ -195,6 +195,12 @@ pub struct TagData {
195
195
  pub offset: UorPoint,
196
196
  /// Text character width / height multipliers in UOR.
197
197
  pub size: [f64; 2],
198
+ /// V8: font number of the displayed value (`0x12C`).
199
+ pub font: u32,
200
+ /// V8: text justification code of the displayed value (`0x130`).
201
+ pub justification: u16,
202
+ /// V8: display orientation quaternion `(w, x, y, z)` as stored (`0x100`).
203
+ pub quaternion: [f64; 4],
198
204
  }
199
205
 
200
206
  /// One tag definition in a tag set.
@@ -583,6 +583,9 @@ impl V7<'_> {
583
583
  origin: [0.0; 3],
584
584
  offset: [0.0; 3],
585
585
  size: [0.0; 2],
586
+ font: 0,
587
+ justification: 0,
588
+ quaternion: [0.0; 4],
586
589
  }))
587
590
  }
588
591