DXFLoader.cpp 45 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147
  1. /*
  2. ---------------------------------------------------------------------------
  3. Open Asset Import Library (assimp)
  4. ---------------------------------------------------------------------------
  5. Copyright (c) 2006-2025, assimp team
  6. All rights reserved.
  7. Redistribution and use of this software in source and binary forms,
  8. with or without modification, are permitted provided that the following
  9. conditions are met:
  10. * Redistributions of source code must retain the above
  11. copyright notice, this list of conditions and the
  12. following disclaimer.
  13. * Redistributions in binary form must reproduce the above
  14. copyright notice, this list of conditions and the
  15. following disclaimer in the documentation and/or other
  16. materials provided with the distribution.
  17. * Neither the name of the assimp team, nor the names of its
  18. contributors may be used to endorse or promote products
  19. derived from this software without specific prior
  20. written permission of the assimp team.
  21. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  22. "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  23. LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  24. A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  25. OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  26. SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  27. LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  28. DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  29. THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  30. (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  31. OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  32. ---------------------------------------------------------------------------
  33. */
  34. /** @file DXFLoader.cpp
  35. * @brief Implementation of the DXF importer class
  36. */
  37. #ifndef ASSIMP_BUILD_NO_DXF_IMPORTER
  38. #include "AssetLib/DXF/DXFLoader.h"
  39. #include "AssetLib/DXF/DXFHelper.h"
  40. #include "PostProcessing/ConvertToLHProcess.h"
  41. #include <assimp/ParsingUtils.h>
  42. #include <assimp/fast_atof.h>
  43. #include <assimp/IOSystem.hpp>
  44. #include <assimp/scene.h>
  45. #include <assimp/importerdesc.h>
  46. #include <numeric>
  47. #include <utility>
  48. using namespace Assimp;
  49. // AutoCAD Binary DXF<CR><LF><SUB><NULL>
  50. static constexpr char AI_DXF_BINARY_IDENT[] = "AutoCAD Binary DXF\r\n\x1a";
  51. static constexpr size_t AI_DXF_BINARY_IDENT_LEN = sizeof AI_DXF_BINARY_IDENT;
  52. // default vertex color that all uncolored vertices will receive
  53. static const aiColor4D AI_DXF_DEFAULT_COLOR(aiColor4D(0.6f, 0.6f, 0.6f, 0.6f));
  54. // color indices for DXF - 256 are supported, the table is
  55. // taken directly from the AutoCad Index (ACI) table
  56. // https://gohtx.com/acadcolors.php
  57. //STH 2024-0126
  58. static const aiColor4D g_aclrDxfIndexColors[256] = {
  59. aiColor4D (0.0f, 0.0f ,0.0f, 1.0f), //dxf color code 0
  60. aiColor4D (1.0f, 0.0f ,0.0f, 1.0f), //dxf color code 1
  61. aiColor4D (1.0f, 1.0f ,0.0f, 1.0f), //dxf color code 2
  62. aiColor4D (0.0f, 1.0f ,0.0f, 1.0f), //dxf color code 3
  63. aiColor4D (0.0f, 1.0f ,1.0f, 1.0f), //dxf color code 4
  64. aiColor4D (0.0f, 0.0f ,1.0f, 1.0f), //dxf color code 5
  65. aiColor4D (1.0f, 0.0f ,1.0f, 1.0f), //dxf color code 6
  66. aiColor4D (1.0f, 1.0f ,1.0f, 1.0f), //dxf color code 7
  67. aiColor4D (0.3f, 0.3f ,0.3f, 1.0f), //dxf color code 8
  68. aiColor4D (0.5f, 0.5f ,0.5f, 1.0f), //dxf color code 9
  69. aiColor4D (1.0f, 0.0f ,0.0f, 1.0f), //dxf color code 10
  70. aiColor4D (1.0f, 0.7f ,0.7f, 1.0f), //dxf color code 11
  71. aiColor4D (0.7f, 0.0f ,0.0f, 1.0f), //dxf color code 12
  72. aiColor4D (0.7f, 0.5f ,0.5f, 1.0f), //dxf color code 13
  73. aiColor4D (0.5f, 0.0f ,0.0f, 1.0f), //dxf color code 14
  74. aiColor4D (0.5f, 0.3f ,0.3f, 1.0f), //dxf color code 15
  75. aiColor4D (0.4f, 0.0f ,0.0f, 1.0f), //dxf color code 16
  76. aiColor4D (0.4f, 0.3f ,0.3f, 1.0f), //dxf color code 17
  77. aiColor4D (0.3f, 0.0f ,0.0f, 1.0f), //dxf color code 18
  78. aiColor4D (0.3f, 0.2f ,0.2f, 1.0f), //dxf color code 19
  79. aiColor4D (1.0f, 0.2f ,0.0f, 1.0f), //dxf color code 20
  80. aiColor4D (1.0f, 0.7f ,0.7f, 1.0f), //dxf color code 21
  81. aiColor4D (0.7f, 0.2f ,0.0f, 1.0f), //dxf color code 22
  82. aiColor4D (0.7f, 0.6f ,0.5f, 1.0f), //dxf color code 23
  83. aiColor4D (0.5f, 0.1f ,0.0f, 1.0f), //dxf color code 24
  84. aiColor4D (0.5f, 0.4f ,0.3f, 1.0f), //dxf color code 25
  85. aiColor4D (0.4f, 0.1f ,0.0f, 1.0f), //dxf color code 26
  86. aiColor4D (0.4f, 0.3f ,0.3f, 1.0f), //dxf color code 27
  87. aiColor4D (0.3f, 0.1f ,0.0f, 1.0f), //dxf color code 28
  88. aiColor4D (0.3f, 0.2f ,0.2f, 1.0f), //dxf color code 29
  89. aiColor4D (1.0f, 0.5f ,0.0f, 1.0f), //dxf color code 30
  90. aiColor4D (1.0f, 0.8f ,0.7f, 1.0f), //dxf color code 31
  91. aiColor4D (0.7f, 0.4f ,0.0f, 1.0f), //dxf color code 32
  92. aiColor4D (0.7f, 0.6f ,0.5f, 1.0f), //dxf color code 33
  93. aiColor4D (0.5f, 0.3f ,0.0f, 1.0f), //dxf color code 34
  94. aiColor4D (0.5f, 0.4f ,0.3f, 1.0f), //dxf color code 35
  95. aiColor4D (0.4f, 0.2f ,0.0f, 1.0f), //dxf color code 36
  96. aiColor4D (0.4f, 0.3f ,0.3f, 1.0f), //dxf color code 37
  97. aiColor4D (0.3f, 0.2f ,0.0f, 1.0f), //dxf color code 38
  98. aiColor4D (0.3f, 0.3f ,0.2f, 1.0f), //dxf color code 39
  99. aiColor4D (1.0f, 0.7f ,0.0f, 1.0f), //dxf color code 40
  100. aiColor4D (1.0f, 0.9f ,0.7f, 1.0f), //dxf color code 41
  101. aiColor4D (0.7f, 0.6f ,0.0f, 1.0f), //dxf color code 42
  102. aiColor4D (0.7f, 0.7f ,0.5f, 1.0f), //dxf color code 43
  103. aiColor4D (0.5f, 0.4f ,0.0f, 1.0f), //dxf color code 44
  104. aiColor4D (0.5f, 0.5f ,0.3f, 1.0f), //dxf color code 45
  105. aiColor4D (0.4f, 0.3f ,0.0f, 1.0f), //dxf color code 46
  106. aiColor4D (0.4f, 0.4f ,0.3f, 1.0f), //dxf color code 47
  107. aiColor4D (0.3f, 0.2f ,0.0f, 1.0f), //dxf color code 48
  108. aiColor4D (0.3f, 0.3f ,0.2f, 1.0f), //dxf color code 49
  109. aiColor4D (1.0f, 1.0f ,0.0f, 1.0f), //dxf color code 50
  110. aiColor4D (1.0f, 1.0f ,0.7f, 1.0f), //dxf color code 51
  111. aiColor4D (0.7f, 0.7f ,0.0f, 1.0f), //dxf color code 52
  112. aiColor4D (0.7f, 0.7f ,0.5f, 1.0f), //dxf color code 53
  113. aiColor4D (0.5f, 0.5f ,0.0f, 1.0f), //dxf color code 54
  114. aiColor4D (0.5f, 0.5f ,0.3f, 1.0f), //dxf color code 55
  115. aiColor4D (0.4f, 0.4f ,0.0f, 1.0f), //dxf color code 56
  116. aiColor4D (0.4f, 0.4f ,0.3f, 1.0f), //dxf color code 57
  117. aiColor4D (0.3f, 0.3f ,0.0f, 1.0f), //dxf color code 58
  118. aiColor4D (0.3f, 0.3f ,0.2f, 1.0f), //dxf color code 59
  119. aiColor4D (0.7f, 1.0f ,0.0f, 1.0f), //dxf color code 60
  120. aiColor4D (0.9f, 1.0f ,0.7f, 1.0f), //dxf color code 61
  121. aiColor4D (0.6f, 0.7f ,0.0f, 1.0f), //dxf color code 62
  122. aiColor4D (0.7f, 0.7f ,0.5f, 1.0f), //dxf color code 63
  123. aiColor4D (0.4f, 0.5f ,0.0f, 1.0f), //dxf color code 64
  124. aiColor4D (0.5f, 0.5f ,0.3f, 1.0f), //dxf color code 65
  125. aiColor4D (0.3f, 0.4f ,0.0f, 1.0f), //dxf color code 66
  126. aiColor4D (0.4f, 0.4f ,0.3f, 1.0f), //dxf color code 67
  127. aiColor4D (0.2f, 0.3f ,0.0f, 1.0f), //dxf color code 68
  128. aiColor4D (0.3f, 0.3f ,0.2f, 1.0f), //dxf color code 69
  129. aiColor4D (0.5f, 1.0f ,0.0f, 1.0f), //dxf color code 70
  130. aiColor4D (0.8f, 1.0f ,0.7f, 1.0f), //dxf color code 71
  131. aiColor4D (0.4f, 0.7f ,0.0f, 1.0f), //dxf color code 72
  132. aiColor4D (0.6f, 0.7f ,0.5f, 1.0f), //dxf color code 73
  133. aiColor4D (0.3f, 0.5f ,0.0f, 1.0f), //dxf color code 74
  134. aiColor4D (0.4f, 0.5f ,0.3f, 1.0f), //dxf color code 75
  135. aiColor4D (0.2f, 0.4f ,0.0f, 1.0f), //dxf color code 76
  136. aiColor4D (0.3f, 0.4f ,0.3f, 1.0f), //dxf color code 77
  137. aiColor4D (0.2f, 0.3f ,0.0f, 1.0f), //dxf color code 78
  138. aiColor4D (0.3f, 0.3f ,0.2f, 1.0f), //dxf color code 79
  139. aiColor4D (0.2f, 1.0f ,0.0f, 1.0f), //dxf color code 80
  140. aiColor4D (0.7f, 1.0f ,0.7f, 1.0f), //dxf color code 81
  141. aiColor4D (0.2f, 0.7f ,0.0f, 1.0f), //dxf color code 82
  142. aiColor4D (0.6f, 0.7f ,0.5f, 1.0f), //dxf color code 83
  143. aiColor4D (0.1f, 0.5f ,0.0f, 1.0f), //dxf color code 84
  144. aiColor4D (0.4f, 0.5f ,0.3f, 1.0f), //dxf color code 85
  145. aiColor4D (0.1f, 0.4f ,0.0f, 1.0f), //dxf color code 86
  146. aiColor4D (0.3f, 0.4f ,0.3f, 1.0f), //dxf color code 87
  147. aiColor4D (0.1f, 0.3f ,0.0f, 1.0f), //dxf color code 88
  148. aiColor4D (0.2f, 0.3f ,0.2f, 1.0f), //dxf color code 89
  149. aiColor4D (0.0f, 1.0f ,0.0f, 1.0f), //dxf color code 90
  150. aiColor4D (0.7f, 1.0f ,0.7f, 1.0f), //dxf color code 91
  151. aiColor4D (0.0f, 0.7f ,0.0f, 1.0f), //dxf color code 92
  152. aiColor4D (0.5f, 0.7f ,0.5f, 1.0f), //dxf color code 93
  153. aiColor4D (0.0f, 0.5f ,0.0f, 1.0f), //dxf color code 94
  154. aiColor4D (0.3f, 0.5f ,0.3f, 1.0f), //dxf color code 95
  155. aiColor4D (0.0f, 0.4f ,0.0f, 1.0f), //dxf color code 96
  156. aiColor4D (0.3f, 0.4f ,0.3f, 1.0f), //dxf color code 97
  157. aiColor4D (0.0f, 0.3f ,0.0f, 1.0f), //dxf color code 98
  158. aiColor4D (0.2f, 0.3f ,0.2f, 1.0f), //dxf color code 99
  159. aiColor4D (0.0f, 1.0f ,0.2f, 1.0f), //dxf color code 100
  160. aiColor4D (0.7f, 1.0f ,0.7f, 1.0f), //dxf color code 101
  161. aiColor4D (0.0f, 0.7f ,0.2f, 1.0f), //dxf color code 102
  162. aiColor4D (0.5f, 0.7f ,0.6f, 1.0f), //dxf color code 103
  163. aiColor4D (0.0f, 0.5f ,0.1f, 1.0f), //dxf color code 104
  164. aiColor4D (0.3f, 0.5f ,0.4f, 1.0f), //dxf color code 105
  165. aiColor4D (0.0f, 0.4f ,0.1f, 1.0f), //dxf color code 106
  166. aiColor4D (0.3f, 0.4f ,0.3f, 1.0f), //dxf color code 107
  167. aiColor4D (0.0f, 0.3f ,0.1f, 1.0f), //dxf color code 108
  168. aiColor4D (0.2f, 0.3f ,0.2f, 1.0f), //dxf color code 109
  169. aiColor4D (0.0f, 1.0f ,0.5f, 1.0f), //dxf color code 110
  170. aiColor4D (0.7f, 1.0f ,0.8f, 1.0f), //dxf color code 111
  171. aiColor4D (0.0f, 0.7f ,0.4f, 1.0f), //dxf color code 112
  172. aiColor4D (0.5f, 0.7f ,0.6f, 1.0f), //dxf color code 113
  173. aiColor4D (0.0f, 0.5f ,0.3f, 1.0f), //dxf color code 114
  174. aiColor4D (0.3f, 0.5f ,0.4f, 1.0f), //dxf color code 115
  175. aiColor4D (0.0f, 0.4f ,0.2f, 1.0f), //dxf color code 116
  176. aiColor4D (0.3f, 0.4f ,0.3f, 1.0f), //dxf color code 117
  177. aiColor4D (0.0f, 0.3f ,0.2f, 1.0f), //dxf color code 118
  178. aiColor4D (0.2f, 0.3f ,0.3f, 1.0f), //dxf color code 119
  179. aiColor4D (0.0f, 1.0f ,0.7f, 1.0f), //dxf color code 120
  180. aiColor4D (0.7f, 1.0f ,0.9f, 1.0f), //dxf color code 121
  181. aiColor4D (0.0f, 0.7f ,0.6f, 1.0f), //dxf color code 122
  182. aiColor4D (0.5f, 0.7f ,0.7f, 1.0f), //dxf color code 123
  183. aiColor4D (0.0f, 0.5f ,0.4f, 1.0f), //dxf color code 124
  184. aiColor4D (0.3f, 0.5f ,0.5f, 1.0f), //dxf color code 125
  185. aiColor4D (0.0f, 0.4f ,0.3f, 1.0f), //dxf color code 126
  186. aiColor4D (0.3f, 0.4f ,0.4f, 1.0f), //dxf color code 127
  187. aiColor4D (0.0f, 0.3f ,0.2f, 1.0f), //dxf color code 128
  188. aiColor4D (0.2f, 0.3f ,0.3f, 1.0f), //dxf color code 129
  189. aiColor4D (0.0f, 1.0f ,1.0f, 1.0f), //dxf color code 130
  190. aiColor4D (0.7f, 1.0f ,1.0f, 1.0f), //dxf color code 131
  191. aiColor4D (0.0f, 0.7f ,0.7f, 1.0f), //dxf color code 132
  192. aiColor4D (0.5f, 0.7f ,0.7f, 1.0f), //dxf color code 133
  193. aiColor4D (0.0f, 0.5f ,0.5f, 1.0f), //dxf color code 134
  194. aiColor4D (0.3f, 0.5f ,0.5f, 1.0f), //dxf color code 135
  195. aiColor4D (0.0f, 0.4f ,0.4f, 1.0f), //dxf color code 136
  196. aiColor4D (0.3f, 0.4f ,0.4f, 1.0f), //dxf color code 137
  197. aiColor4D (0.0f, 0.3f ,0.3f, 1.0f), //dxf color code 138
  198. aiColor4D (0.2f, 0.3f ,0.3f, 1.0f), //dxf color code 139
  199. aiColor4D (0.0f, 0.7f ,1.0f, 1.0f), //dxf color code 140
  200. aiColor4D (0.7f, 0.9f ,1.0f, 1.0f), //dxf color code 141
  201. aiColor4D (0.0f, 0.6f ,0.7f, 1.0f), //dxf color code 142
  202. aiColor4D (0.5f, 0.7f ,0.7f, 1.0f), //dxf color code 143
  203. aiColor4D (0.0f, 0.4f ,0.5f, 1.0f), //dxf color code 144
  204. aiColor4D (0.3f, 0.5f ,0.5f, 1.0f), //dxf color code 145
  205. aiColor4D (0.0f, 0.3f ,0.4f, 1.0f), //dxf color code 146
  206. aiColor4D (0.3f, 0.4f ,0.4f, 1.0f), //dxf color code 147
  207. aiColor4D (0.0f, 0.2f ,0.3f, 1.0f), //dxf color code 148
  208. aiColor4D (0.2f, 0.3f ,0.3f, 1.0f), //dxf color code 149
  209. aiColor4D (0.0f, 0.5f ,1.0f, 1.0f), //dxf color code 150
  210. aiColor4D (0.7f, 0.8f ,1.0f, 1.0f), //dxf color code 151
  211. aiColor4D (0.0f, 0.4f ,0.7f, 1.0f), //dxf color code 152
  212. aiColor4D (0.5f, 0.6f ,0.7f, 1.0f), //dxf color code 153
  213. aiColor4D (0.0f, 0.3f ,0.5f, 1.0f), //dxf color code 154
  214. aiColor4D (0.3f, 0.4f ,0.5f, 1.0f), //dxf color code 155
  215. aiColor4D (0.0f, 0.2f ,0.4f, 1.0f), //dxf color code 156
  216. aiColor4D (0.3f, 0.3f ,0.4f, 1.0f), //dxf color code 157
  217. aiColor4D (0.0f, 0.2f ,0.3f, 1.0f), //dxf color code 158
  218. aiColor4D (0.2f, 0.3f ,0.3f, 1.0f), //dxf color code 159
  219. aiColor4D (0.0f, 0.2f ,1.0f, 1.0f), //dxf color code 160
  220. aiColor4D (0.7f, 0.7f ,1.0f, 1.0f), //dxf color code 161
  221. aiColor4D (0.0f, 0.2f ,0.7f, 1.0f), //dxf color code 162
  222. aiColor4D (0.5f, 0.6f ,0.7f, 1.0f), //dxf color code 163
  223. aiColor4D (0.0f, 0.1f ,0.5f, 1.0f), //dxf color code 164
  224. aiColor4D (0.3f, 0.4f ,0.5f, 1.0f), //dxf color code 165
  225. aiColor4D (0.0f, 0.1f ,0.4f, 1.0f), //dxf color code 166
  226. aiColor4D (0.3f, 0.3f ,0.4f, 1.0f), //dxf color code 167
  227. aiColor4D (0.0f, 0.1f ,0.3f, 1.0f), //dxf color code 168
  228. aiColor4D (0.2f, 0.2f ,0.3f, 1.0f), //dxf color code 169
  229. aiColor4D (0.0f, 0.0f ,1.0f, 1.0f), //dxf color code 170
  230. aiColor4D (0.7f, 0.7f ,1.0f, 1.0f), //dxf color code 171
  231. aiColor4D (0.0f, 0.0f ,0.7f, 1.0f), //dxf color code 172
  232. aiColor4D (0.5f, 0.5f ,0.7f, 1.0f), //dxf color code 173
  233. aiColor4D (0.0f, 0.0f ,0.5f, 1.0f), //dxf color code 174
  234. aiColor4D (0.3f, 0.3f ,0.5f, 1.0f), //dxf color code 175
  235. aiColor4D (0.0f, 0.0f ,0.4f, 1.0f), //dxf color code 176
  236. aiColor4D (0.3f, 0.3f ,0.4f, 1.0f), //dxf color code 177
  237. aiColor4D (0.0f, 0.0f ,0.3f, 1.0f), //dxf color code 178
  238. aiColor4D (0.2f, 0.2f ,0.3f, 1.0f), //dxf color code 179
  239. aiColor4D (0.2f, 0.0f ,1.0f, 1.0f), //dxf color code 180
  240. aiColor4D (0.7f, 0.7f ,1.0f, 1.0f), //dxf color code 181
  241. aiColor4D (0.2f, 0.0f ,0.7f, 1.0f), //dxf color code 182
  242. aiColor4D (0.6f, 0.5f ,0.7f, 1.0f), //dxf color code 183
  243. aiColor4D (0.1f, 0.0f ,0.5f, 1.0f), //dxf color code 184
  244. aiColor4D (0.4f, 0.3f ,0.5f, 1.0f), //dxf color code 185
  245. aiColor4D (0.1f, 0.0f ,0.4f, 1.0f), //dxf color code 186
  246. aiColor4D (0.3f, 0.3f ,0.4f, 1.0f), //dxf color code 187
  247. aiColor4D (0.1f, 0.0f ,0.3f, 1.0f), //dxf color code 188
  248. aiColor4D (0.2f, 0.2f ,0.3f, 1.0f), //dxf color code 189
  249. aiColor4D (0.5f, 0.0f ,1.0f, 1.0f), //dxf color code 190
  250. aiColor4D (0.8f, 0.7f ,1.0f, 1.0f), //dxf color code 191
  251. aiColor4D (0.4f, 0.0f ,0.7f, 1.0f), //dxf color code 192
  252. aiColor4D (0.6f, 0.5f ,0.7f, 1.0f), //dxf color code 193
  253. aiColor4D (0.3f, 0.0f ,0.5f, 1.0f), //dxf color code 194
  254. aiColor4D (0.4f, 0.3f ,0.5f, 1.0f), //dxf color code 195
  255. aiColor4D (0.2f, 0.0f ,0.4f, 1.0f), //dxf color code 196
  256. aiColor4D (0.3f, 0.3f ,0.4f, 1.0f), //dxf color code 197
  257. aiColor4D (0.2f, 0.0f ,0.3f, 1.0f), //dxf color code 198
  258. aiColor4D (0.3f, 0.2f ,0.3f, 1.0f), //dxf color code 199
  259. aiColor4D (0.7f, 0.0f ,1.0f, 1.0f), //dxf color code 200
  260. aiColor4D (0.9f, 0.7f ,1.0f, 1.0f), //dxf color code 201
  261. aiColor4D (0.6f, 0.0f ,0.7f, 1.0f), //dxf color code 202
  262. aiColor4D (0.7f, 0.5f ,0.7f, 1.0f), //dxf color code 203
  263. aiColor4D (0.4f, 0.0f ,0.5f, 1.0f), //dxf color code 204
  264. aiColor4D (0.5f, 0.3f ,0.5f, 1.0f), //dxf color code 205
  265. aiColor4D (0.3f, 0.0f ,0.4f, 1.0f), //dxf color code 206
  266. aiColor4D (0.4f, 0.3f ,0.4f, 1.0f), //dxf color code 207
  267. aiColor4D (0.2f, 0.0f ,0.3f, 1.0f), //dxf color code 208
  268. aiColor4D (0.3f, 0.2f ,0.3f, 1.0f), //dxf color code 209
  269. aiColor4D (1.0f, 0.0f ,1.0f, 1.0f), //dxf color code 210
  270. aiColor4D (1.0f, 0.7f ,1.0f, 1.0f), //dxf color code 211
  271. aiColor4D (0.7f, 0.0f ,0.7f, 1.0f), //dxf color code 212
  272. aiColor4D (0.7f, 0.5f ,0.7f, 1.0f), //dxf color code 213
  273. aiColor4D (0.5f, 0.0f ,0.5f, 1.0f), //dxf color code 214
  274. aiColor4D (0.5f, 0.3f ,0.5f, 1.0f), //dxf color code 215
  275. aiColor4D (0.4f, 0.0f ,0.4f, 1.0f), //dxf color code 216
  276. aiColor4D (0.4f, 0.3f ,0.4f, 1.0f), //dxf color code 217
  277. aiColor4D (0.3f, 0.0f ,0.3f, 1.0f), //dxf color code 218
  278. aiColor4D (0.3f, 0.2f ,0.3f, 1.0f), //dxf color code 219
  279. aiColor4D (1.0f, 0.0f ,0.7f, 1.0f), //dxf color code 220
  280. aiColor4D (1.0f, 0.7f ,0.9f, 1.0f), //dxf color code 221
  281. aiColor4D (0.7f, 0.0f ,0.6f, 1.0f), //dxf color code 222
  282. aiColor4D (0.7f, 0.5f ,0.7f, 1.0f), //dxf color code 223
  283. aiColor4D (0.5f, 0.0f ,0.4f, 1.0f), //dxf color code 224
  284. aiColor4D (0.5f, 0.3f ,0.5f, 1.0f), //dxf color code 225
  285. aiColor4D (0.4f, 0.0f ,0.3f, 1.0f), //dxf color code 226
  286. aiColor4D (0.4f, 0.3f ,0.4f, 1.0f), //dxf color code 227
  287. aiColor4D (0.3f, 0.0f ,0.2f, 1.0f), //dxf color code 228
  288. aiColor4D (0.3f, 0.2f ,0.3f, 1.0f), //dxf color code 229
  289. aiColor4D (1.0f, 0.0f ,0.5f, 1.0f), //dxf color code 230
  290. aiColor4D (1.0f, 0.7f ,0.8f, 1.0f), //dxf color code 231
  291. aiColor4D (0.7f, 0.0f ,0.4f, 1.0f), //dxf color code 232
  292. aiColor4D (0.7f, 0.5f ,0.6f, 1.0f), //dxf color code 233
  293. aiColor4D (0.5f, 0.0f ,0.3f, 1.0f), //dxf color code 234
  294. aiColor4D (0.5f, 0.3f ,0.4f, 1.0f), //dxf color code 235
  295. aiColor4D (0.4f, 0.0f ,0.2f, 1.0f), //dxf color code 236
  296. aiColor4D (0.4f, 0.3f ,0.3f, 1.0f), //dxf color code 237
  297. aiColor4D (0.3f, 0.0f ,0.2f, 1.0f), //dxf color code 238
  298. aiColor4D (0.3f, 0.2f ,0.3f, 1.0f), //dxf color code 239
  299. aiColor4D (1.0f, 0.0f ,0.2f, 1.0f), //dxf color code 240
  300. aiColor4D (1.0f, 0.7f ,0.7f, 1.0f), //dxf color code 241
  301. aiColor4D (0.7f, 0.0f ,0.2f, 1.0f), //dxf color code 242
  302. aiColor4D (0.7f, 0.5f ,0.6f, 1.0f), //dxf color code 243
  303. aiColor4D (0.5f, 0.0f ,0.1f, 1.0f), //dxf color code 244
  304. aiColor4D (0.5f, 0.3f ,0.4f, 1.0f), //dxf color code 245
  305. aiColor4D (0.4f, 0.0f ,0.1f, 1.0f), //dxf color code 246
  306. aiColor4D (0.4f, 0.3f ,0.3f, 1.0f), //dxf color code 247
  307. aiColor4D (0.3f, 0.0f ,0.1f, 1.0f), //dxf color code 248
  308. aiColor4D (0.3f, 0.2f ,0.2f, 1.0f), //dxf color code 249
  309. aiColor4D (0.2f, 0.2f ,0.2f, 1.0f), //dxf color code 250
  310. aiColor4D (0.3f, 0.3f ,0.3f, 1.0f), //dxf color code 251
  311. aiColor4D (0.4f, 0.4f ,0.4f, 1.0f), //dxf color code 252
  312. aiColor4D (0.5f, 0.5f ,0.5f, 1.0f), //dxf color code 253
  313. aiColor4D (0.7f, 0.7f ,0.7f, 1.0f), //dxf color code 254
  314. aiColor4D (1.0f, 1.0f ,1.0f, 1.0f) //dxf color code 255
  315. };
  316. #define AI_DXF_NUM_INDEX_COLORS (sizeof(g_aclrDxfIndexColors)/sizeof(g_aclrDxfIndexColors[0]))
  317. #define AI_DXF_ENTITIES_MAGIC_BLOCK "$ASSIMP_ENTITIES_MAGIC"
  318. static const int GroupCode_Name = 2;
  319. static const int GroupCode_XComp = 10;
  320. static const int GroupCode_YComp = 20;
  321. static const int GroupCode_ZComp = 30;
  322. static constexpr aiImporterDesc desc = {
  323. "Drawing Interchange Format (DXF) Importer",
  324. "",
  325. "",
  326. "",
  327. aiImporterFlags_SupportTextFlavour | aiImporterFlags_LimitedSupport,
  328. 0,
  329. 0,
  330. 0,
  331. 0,
  332. "dxf"
  333. };
  334. // ------------------------------------------------------------------------------------------------
  335. // Returns whether the class can handle the format of the given file.
  336. bool DXFImporter::CanRead( const std::string& filename, IOSystem* pIOHandler, bool /*checkSig*/ ) const {
  337. static const char *tokens[] = { "SECTION", "HEADER", "ENDSEC", "BLOCKS" };
  338. return SearchFileHeaderForToken(pIOHandler, filename, tokens, AI_COUNT_OF(tokens), 32);
  339. }
  340. // ------------------------------------------------------------------------------------------------
  341. // Get a list of all supported file extensions
  342. const aiImporterDesc* DXFImporter::GetInfo () const {
  343. return &desc;
  344. }
  345. // ------------------------------------------------------------------------------------------------
  346. // Imports the given file into the given scene structure.
  347. void DXFImporter::InternReadFile( const std::string& filename, aiScene* pScene, IOSystem* pIOHandler) {
  348. std::shared_ptr<IOStream> file = std::shared_ptr<IOStream>( pIOHandler->Open( filename) );
  349. // Check whether we can read the file
  350. if (file == nullptr) {
  351. throw DeadlyImportError( "Failed to open DXF file ", filename, "");
  352. }
  353. // Check whether this is a binary DXF file - we can't read binary DXF files :-(
  354. char buff[AI_DXF_BINARY_IDENT_LEN] = {0};
  355. file->Read(buff,AI_DXF_BINARY_IDENT_LEN,1);
  356. if (0 == memcmp(AI_DXF_BINARY_IDENT,buff,AI_DXF_BINARY_IDENT_LEN)) {
  357. throw DeadlyImportError("DXF: Binary files are not supported at the moment");
  358. }
  359. // DXF files can grow very large, so read them via the StreamReader,
  360. // which will choose a suitable strategy.
  361. file->Seek(0,aiOrigin_SET);
  362. StreamReaderLE stream( std::move(file) );
  363. DXF::LineReader reader (stream);
  364. DXF::FileData output;
  365. // now get all lines of the file and process top-level sections
  366. bool eof = false;
  367. while(!reader.End()) {
  368. // blocks table - these 'build blocks' are later (in ENTITIES)
  369. // referenced an included via INSERT statements.
  370. if (reader.Is(2,"BLOCKS")) {
  371. ParseBlocks(reader,output);
  372. continue;
  373. }
  374. // primary entity table
  375. if (reader.Is(2,"ENTITIES")) {
  376. ParseEntities(reader,output);
  377. continue;
  378. }
  379. // skip unneeded sections entirely to avoid any problems with them
  380. // altogether.
  381. else if (reader.Is(2,"CLASSES") || reader.Is(2,"TABLES")) {
  382. SkipSection(reader);
  383. continue;
  384. }
  385. else if (reader.Is(2,"HEADER")) {
  386. ParseHeader(reader,output);
  387. continue;
  388. }
  389. // comments
  390. else if (reader.Is(999)) {
  391. ASSIMP_LOG_INFO("DXF Comment: ", reader.Value());
  392. }
  393. // don't read past the official EOF sign
  394. else if (reader.Is(0,"EOF")) {
  395. eof = true;
  396. break;
  397. }
  398. ++reader;
  399. }
  400. if (!eof) {
  401. ASSIMP_LOG_WARN("DXF: EOF reached, but did not encounter DXF EOF marker");
  402. }
  403. ConvertMeshes(pScene,output);
  404. // Now rotate the whole scene by 90 degrees around the x axis to convert from AutoCAD's to Assimp's coordinate system
  405. pScene->mRootNode->mTransformation = aiMatrix4x4(
  406. 1.f,0.f,0.f,0.f,
  407. 0.f,0.f,1.f,0.f,
  408. 0.f,-1.f,0.f,0.f,
  409. 0.f,0.f,0.f,1.f) * pScene->mRootNode->mTransformation;
  410. }
  411. // ------------------------------------------------------------------------------------------------
  412. void DXFImporter::ConvertMeshes(aiScene* pScene, DXF::FileData& output) {
  413. // the process of resolving all the INSERT statements can grow the
  414. // poly-count excessively, so log the original number.
  415. // XXX Option to import blocks as separate nodes?
  416. if (!DefaultLogger::isNullLogger()) {
  417. unsigned int vcount = 0, icount = 0;
  418. for (const DXF::Block& bl : output.blocks) {
  419. for (std::shared_ptr<const DXF::PolyLine> pl : bl.lines) {
  420. vcount += static_cast<unsigned int>(pl->positions.size());
  421. icount += static_cast<unsigned int>(pl->counts.size());
  422. }
  423. }
  424. ASSIMP_LOG_VERBOSE_DEBUG("DXF: Unexpanded polycount is ", icount, ", vertex count is ", vcount);
  425. }
  426. if (output.blocks.empty()) {
  427. throw DeadlyImportError("DXF: no data blocks loaded");
  428. }
  429. DXF::Block* entities( nullptr );
  430. // index blocks by name
  431. DXF::BlockMap blocks_by_name;
  432. for (DXF::Block& bl : output.blocks) {
  433. blocks_by_name[bl.name] = &bl;
  434. if ( !entities && bl.name == AI_DXF_ENTITIES_MAGIC_BLOCK ) {
  435. entities = &bl;
  436. }
  437. }
  438. if (!entities) {
  439. throw DeadlyImportError("DXF: no ENTITIES data block loaded");
  440. }
  441. typedef std::map<std::string, unsigned int> LayerMap;
  442. LayerMap layers;
  443. std::vector< std::vector< const DXF::PolyLine*> > corr;
  444. // now expand all block references in the primary ENTITIES block
  445. // XXX this involves heavy memory copying, consider a faster solution for future versions.
  446. ExpandBlockReferences(*entities,blocks_by_name);
  447. unsigned int cur = 0;
  448. for (std::shared_ptr<const DXF::PolyLine> pl : entities->lines) {
  449. if (pl->positions.size()) {
  450. std::map<std::string, unsigned int>::iterator it = layers.find(pl->layer);
  451. if (it == layers.end()) {
  452. ++pScene->mNumMeshes;
  453. layers[pl->layer] = cur++;
  454. std::vector< const DXF::PolyLine* > pv;
  455. pv.push_back(&*pl);
  456. corr.push_back(pv);
  457. }
  458. else {
  459. corr[(*it).second].push_back(&*pl);
  460. }
  461. }
  462. }
  463. if ( 0 == pScene->mNumMeshes) {
  464. throw DeadlyImportError("DXF: this file contains no 3d data");
  465. }
  466. pScene->mMeshes = new aiMesh*[ pScene->mNumMeshes ] ();
  467. for(const LayerMap::value_type& elem : layers){
  468. aiMesh* const mesh = pScene->mMeshes[elem.second] = new aiMesh();
  469. mesh->mName.Set(elem.first);
  470. unsigned int cvert = 0,cface = 0;
  471. for(const DXF::PolyLine* pl : corr[elem.second]){
  472. // sum over all faces since we need to 'verbosify' them.
  473. cvert += std::accumulate(pl->counts.begin(),pl->counts.end(),0);
  474. cface += static_cast<unsigned int>(pl->counts.size());
  475. }
  476. aiVector3D* verts = mesh->mVertices = new aiVector3D[cvert];
  477. aiColor4D* colors = mesh->mColors[0] = new aiColor4D[cvert];
  478. aiFace* faces = mesh->mFaces = new aiFace[cface];
  479. mesh->mNumVertices = cvert;
  480. mesh->mNumFaces = cface;
  481. unsigned int prims = 0;
  482. unsigned int overall_indices = 0;
  483. for(const DXF::PolyLine* pl : corr[elem.second]){
  484. std::vector<unsigned int>::const_iterator it = pl->indices.begin();
  485. for(unsigned int facenumv : pl->counts) {
  486. aiFace& face = *faces++;
  487. face.mIndices = new unsigned int[face.mNumIndices = facenumv];
  488. for (unsigned int i = 0; i < facenumv; ++i) {
  489. face.mIndices[i] = overall_indices++;
  490. ai_assert(pl->positions.size() == pl->colors.size());
  491. if (*it >= pl->positions.size()) {
  492. throw DeadlyImportError("DXF: vertex index out of bounds");
  493. }
  494. *verts++ = pl->positions[*it];
  495. *colors++ = pl->colors[*it++];
  496. }
  497. // set primitive flags now, this saves the extra pass in ScenePreprocessor.
  498. switch(face.mNumIndices) {
  499. case 1:
  500. prims |= aiPrimitiveType_POINT;
  501. break;
  502. case 2:
  503. prims |= aiPrimitiveType_LINE;
  504. break;
  505. case 3:
  506. prims |= aiPrimitiveType_TRIANGLE;
  507. break;
  508. default:
  509. prims |= aiPrimitiveType_POLYGON;
  510. break;
  511. }
  512. }
  513. }
  514. mesh->mPrimitiveTypes = prims;
  515. mesh->mMaterialIndex = 0;
  516. }
  517. GenerateHierarchy(pScene,output);
  518. GenerateMaterials(pScene,output);
  519. }
  520. // ------------------------------------------------------------------------------------------------
  521. void DXFImporter::ExpandBlockReferences(DXF::Block& bl,const DXF::BlockMap& blocks_by_name) {
  522. for (const DXF::InsertBlock& insert : bl.insertions) {
  523. // first check if the referenced blocks exists ...
  524. const DXF::BlockMap::const_iterator it = blocks_by_name.find(insert.name);
  525. if (it == blocks_by_name.end()) {
  526. ASSIMP_LOG_ERROR("DXF: Failed to resolve block reference: ", insert.name,"; skipping" );
  527. continue;
  528. }
  529. // XXX this would be the place to implement recursive expansion if needed.
  530. const DXF::Block& bl_src = *(*it).second;
  531. const size_t size = bl_src.lines.size(); // the size may increase in the loop
  532. for (size_t i = 0; i < size; ++i) {
  533. std::shared_ptr<const DXF::PolyLine> pl_in = bl_src.lines[i];
  534. if (!pl_in) {
  535. ASSIMP_LOG_ERROR("DXF: PolyLine instance is nullptr, skipping.");
  536. continue;
  537. }
  538. std::shared_ptr<DXF::PolyLine> pl_out = std::shared_ptr<DXF::PolyLine>(new DXF::PolyLine(*pl_in));
  539. if (bl_src.base.Length() || insert.scale.x!=1.f || insert.scale.y!=1.f || insert.scale.z!=1.f || insert.angle || insert.pos.Length()) {
  540. // manual coordinate system transformation
  541. // XXX order
  542. aiMatrix4x4 trafo, tmp;
  543. aiMatrix4x4::Translation(-bl_src.base,trafo);
  544. //Need to translate position before scaling the insert
  545. //otherwise the position ends up being the position*scaling
  546. //STH 2024.01.17
  547. trafo *= aiMatrix4x4::Translation(insert.pos,tmp);
  548. trafo *= aiMatrix4x4::Scaling(insert.scale,tmp);
  549. //trafo *= aiMatrix4x4::Translation(insert.pos,tmp);
  550. // XXX rotation currently ignored - I didn't find an appropriate sample model.
  551. if (insert.angle != 0.f) {
  552. ASSIMP_LOG_WARN("DXF: BLOCK rotation not currently implemented");
  553. }
  554. for (aiVector3D& v : pl_out->positions) {
  555. v *= trafo;
  556. }
  557. }
  558. bl.lines.push_back(pl_out);
  559. }
  560. }
  561. }
  562. // ------------------------------------------------------------------------------------------------
  563. void DXFImporter::GenerateMaterials(aiScene* pScene, DXF::FileData& /*output*/) {
  564. // generate an almost-white default material. Reason:
  565. // the default vertex color is GREY, so we are
  566. // already at Assimp's usual default color.
  567. // generate a default material
  568. aiMaterial* pcMat = new aiMaterial();
  569. aiString s;
  570. s.Set(AI_DEFAULT_MATERIAL_NAME);
  571. pcMat->AddProperty(&s, AI_MATKEY_NAME);
  572. aiColor4D clrDiffuse(0.9f,0.9f,0.9f,1.0f);
  573. pcMat->AddProperty(&clrDiffuse,1,AI_MATKEY_COLOR_DIFFUSE);
  574. clrDiffuse = aiColor4D(1.0f,1.0f,1.0f,1.0f);
  575. pcMat->AddProperty(&clrDiffuse,1,AI_MATKEY_COLOR_SPECULAR);
  576. clrDiffuse = aiColor4D(0.05f,0.05f,0.05f,1.0f);
  577. pcMat->AddProperty(&clrDiffuse,1,AI_MATKEY_COLOR_AMBIENT);
  578. pScene->mNumMaterials = 1;
  579. pScene->mMaterials = new aiMaterial*[1];
  580. pScene->mMaterials[0] = pcMat;
  581. }
  582. // ------------------------------------------------------------------------------------------------
  583. void DXFImporter::GenerateHierarchy(aiScene* pScene, DXF::FileData& /*output*/) {
  584. // generate the output scene graph, which is just the root node with a single child for each layer.
  585. pScene->mRootNode = new aiNode();
  586. pScene->mRootNode->mName.Set("<DXF_ROOT>");
  587. if (1 == pScene->mNumMeshes) {
  588. pScene->mRootNode->mMeshes = new unsigned int[ pScene->mRootNode->mNumMeshes = 1 ];
  589. pScene->mRootNode->mMeshes[0] = 0;
  590. } else {
  591. pScene->mRootNode->mChildren = new aiNode*[ pScene->mRootNode->mNumChildren = pScene->mNumMeshes ];
  592. for (unsigned int m = 0; m < pScene->mRootNode->mNumChildren;++m) {
  593. aiNode* p = pScene->mRootNode->mChildren[m] = new aiNode();
  594. p->mName = pScene->mMeshes[m]->mName;
  595. p->mMeshes = new unsigned int[p->mNumMeshes = 1];
  596. p->mMeshes[0] = m;
  597. p->mParent = pScene->mRootNode;
  598. }
  599. }
  600. }
  601. // ------------------------------------------------------------------------------------------------
  602. void DXFImporter::SkipSection(DXF::LineReader& reader) {
  603. for( ;!reader.End() && !reader.Is(0,"ENDSEC"); reader++);
  604. }
  605. // ------------------------------------------------------------------------------------------------
  606. void DXFImporter::ParseHeader(DXF::LineReader& reader, DXF::FileData& ) {
  607. for( ;!reader.End() && !reader.Is(0,"ENDSEC"); reader++);
  608. }
  609. // ------------------------------------------------------------------------------------------------
  610. void DXFImporter::ParseBlocks(DXF::LineReader& reader, DXF::FileData& output) {
  611. while( !reader.End() && !reader.Is(0,"ENDSEC")) {
  612. if (reader.Is(0,"BLOCK")) {
  613. ParseBlock(++reader,output);
  614. continue;
  615. }
  616. ++reader;
  617. }
  618. ASSIMP_LOG_VERBOSE_DEBUG("DXF: got ", output.blocks.size()," entries in BLOCKS" );
  619. }
  620. // ------------------------------------------------------------------------------------------------
  621. void DXFImporter::ParseBlock(DXF::LineReader& reader, DXF::FileData& output) {
  622. // push a new block onto the stack.
  623. output.blocks.emplace_back();
  624. DXF::Block& block = output.blocks.back();
  625. while( !reader.End() && !reader.Is(0,"ENDBLK")) {
  626. switch(reader.GroupCode()) {
  627. case GroupCode_Name:
  628. block.name = reader.Value();
  629. break;
  630. case GroupCode_XComp:
  631. block.base.x = reader.ValueAsFloat();
  632. break;
  633. case GroupCode_YComp:
  634. block.base.y = reader.ValueAsFloat();
  635. break;
  636. case GroupCode_ZComp:
  637. block.base.z = reader.ValueAsFloat();
  638. break;
  639. }
  640. if (reader.Is(0,"POLYLINE")) {
  641. ParsePolyLine(++reader,output);
  642. continue;
  643. }
  644. // XXX is this a valid case?
  645. if (reader.Is(0,"INSERT")) {
  646. ASSIMP_LOG_WARN("DXF: INSERT within a BLOCK not currently supported; skipping");
  647. for( ;!reader.End() && !reader.Is(0,"ENDBLK"); ++reader);
  648. break;
  649. }
  650. else if (reader.Is(0,"3DFACE") || reader.Is(0,"LINE") || reader.Is(0,"3DLINE")) {
  651. //http://sourceforge.net/tracker/index.php?func=detail&aid=2970566&group_id=226462&atid=1067632
  652. Parse3DFace(++reader, output);
  653. continue;
  654. }
  655. ++reader;
  656. }
  657. }
  658. // ------------------------------------------------------------------------------------------------
  659. void DXFImporter::ParseEntities(DXF::LineReader& reader, DXF::FileData& output) {
  660. // Push a new block onto the stack.
  661. output.blocks.emplace_back();
  662. DXF::Block& block = output.blocks.back();
  663. block.name = AI_DXF_ENTITIES_MAGIC_BLOCK;
  664. while( !reader.End() && !reader.Is(0,"ENDSEC")) {
  665. if (reader.Is(0,"POLYLINE")) {
  666. ParsePolyLine(++reader,output);
  667. continue;
  668. }
  669. else if (reader.Is(0,"INSERT")) {
  670. ParseInsertion(++reader,output);
  671. continue;
  672. }
  673. else if (reader.Is(0,"3DFACE") || reader.Is(0,"LINE") || reader.Is(0,"3DLINE")) {
  674. //http://sourceforge.net/tracker/index.php?func=detail&aid=2970566&group_id=226462&atid=1067632
  675. Parse3DFace(++reader, output);
  676. continue;
  677. }
  678. ++reader;
  679. }
  680. ASSIMP_LOG_VERBOSE_DEBUG( "DXF: got ", block.lines.size()," polylines and ", block.insertions.size(),
  681. " inserted blocks in ENTITIES" );
  682. }
  683. void DXFImporter::ParseInsertion(DXF::LineReader& reader, DXF::FileData& output) {
  684. output.blocks.back().insertions.emplace_back();
  685. DXF::InsertBlock& bl = output.blocks.back().insertions.back();
  686. while( !reader.End() && !reader.Is(0)) {
  687. switch(reader.GroupCode()) {
  688. // name of referenced block
  689. case GroupCode_Name:
  690. bl.name = reader.Value();
  691. break;
  692. // translation
  693. case GroupCode_XComp:
  694. bl.pos.x = reader.ValueAsFloat();
  695. break;
  696. case GroupCode_YComp:
  697. bl.pos.y = reader.ValueAsFloat();
  698. break;
  699. case GroupCode_ZComp:
  700. bl.pos.z = reader.ValueAsFloat();
  701. break;
  702. // scaling
  703. case 41:
  704. bl.scale.x = reader.ValueAsFloat();
  705. break;
  706. case 42:
  707. bl.scale.y = reader.ValueAsFloat();
  708. break;
  709. case 43:
  710. bl.scale.z = reader.ValueAsFloat();
  711. break;
  712. // rotation angle
  713. case 50:
  714. bl.angle = reader.ValueAsFloat();
  715. break;
  716. }
  717. reader++;
  718. }
  719. }
  720. static constexpr unsigned int DXF_POLYLINE_FLAG_CLOSED = 0x1;
  721. // Currently unused
  722. //static constexpr unsigned int DXF_POLYLINE_FLAG_3D_POLYLINE = 0x8;
  723. //static constexpr unsigned int DXF_POLYLINE_FLAG_3D_POLYMESH = 0x10;
  724. static constexpr unsigned int DXF_POLYLINE_FLAG_POLYFACEMESH = 0x40;
  725. // ------------------------------------------------------------------------------------------------
  726. void DXFImporter::ParsePolyLine(DXF::LineReader& reader, DXF::FileData& output) {
  727. output.blocks.back().lines.push_back( std::shared_ptr<DXF::PolyLine>( new DXF::PolyLine() ) );
  728. DXF::PolyLine& line = *output.blocks.back().lines.back();
  729. unsigned int iguess = 0, vguess = 0;
  730. while( !reader.End() && !reader.Is(0,"ENDSEC")) {
  731. if (reader.Is(0,"VERTEX")) {
  732. ParsePolyLineVertex(++reader,line);
  733. if (reader.Is(0,"SEQEND")) {
  734. break;
  735. }
  736. continue;
  737. }
  738. switch(reader.GroupCode())
  739. {
  740. // flags --- important that we know whether it is a
  741. // polyface mesh or 'just' a line.
  742. case 70:
  743. if (!line.flags) {
  744. line.flags = reader.ValueAsSignedInt();
  745. }
  746. break;
  747. // optional number of vertices
  748. case 71:
  749. vguess = reader.ValueAsSignedInt();
  750. line.positions.reserve(vguess);
  751. break;
  752. // optional number of faces
  753. case 72:
  754. iguess = reader.ValueAsSignedInt();
  755. line.indices.reserve(iguess);
  756. break;
  757. // 8 specifies the layer on which this line is placed on
  758. case 8:
  759. line.layer = reader.Value();
  760. break;
  761. }
  762. reader++;
  763. }
  764. if (vguess && line.positions.size() != vguess) {
  765. ASSIMP_LOG_WARN("DXF: unexpected vertex count in polymesh: ",
  766. line.positions.size(),", expected ", vguess );
  767. }
  768. if (line.flags & DXF_POLYLINE_FLAG_POLYFACEMESH ) {
  769. if (line.positions.size() < 3 || line.indices.size() < 3) {
  770. ASSIMP_LOG_WARN("DXF: not enough vertices for polymesh; ignoring");
  771. output.blocks.back().lines.pop_back();
  772. return;
  773. }
  774. // if these numbers are wrong, parsing might have gone wild.
  775. // however, the docs state that applications are not required
  776. // to set the 71 and 72 fields, respectively, to valid values.
  777. // So just fire a warning.
  778. if (iguess && line.counts.size() != iguess) {
  779. ASSIMP_LOG_WARN( "DXF: unexpected face count in polymesh: ", line.counts.size(),", expected ", iguess );
  780. }
  781. }
  782. else if (!line.indices.size() && !line.counts.size()) {
  783. // a poly-line - so there are no indices yet.
  784. size_t guess = line.positions.size() + (line.flags & DXF_POLYLINE_FLAG_CLOSED ? 1 : 0);
  785. line.indices.reserve(guess);
  786. line.counts.reserve(guess/2);
  787. for (unsigned int i = 0; i < line.positions.size()/2; ++i) {
  788. line.indices.push_back(i*2);
  789. line.indices.push_back(i*2+1);
  790. line.counts.push_back(2);
  791. }
  792. // closed polyline?
  793. if (line.flags & DXF_POLYLINE_FLAG_CLOSED) {
  794. line.indices.push_back(static_cast<unsigned int>(line.positions.size()-1));
  795. line.indices.push_back(0);
  796. line.counts.push_back(2);
  797. }
  798. }
  799. }
  800. #define DXF_VERTEX_FLAG_PART_OF_POLYFACE 0x80
  801. #define DXF_VERTEX_FLAG_HAS_POSITIONS 0x40
  802. // ------------------------------------------------------------------------------------------------
  803. void DXFImporter::ParsePolyLineVertex(DXF::LineReader& reader, DXF::PolyLine& line) {
  804. unsigned int cnti = 0, flags = 0;
  805. unsigned int indices[4];
  806. aiVector3D out;
  807. aiColor4D clr = AI_DXF_DEFAULT_COLOR;
  808. while( !reader.End() ) {
  809. if (reader.Is(0)) { // SEQEND or another VERTEX
  810. break;
  811. }
  812. switch (reader.GroupCode()) {
  813. case 8:
  814. // layer to which the vertex belongs to - assume that
  815. // this is always the layer the top-level poly-line
  816. // entity resides on as well.
  817. if(reader.Value() != line.layer) {
  818. ASSIMP_LOG_WARN("DXF: expected vertex to be part of a poly-face but the 0x128 flag isn't set");
  819. }
  820. break;
  821. case 70:
  822. flags = reader.ValueAsUnsignedInt();
  823. break;
  824. // VERTEX COORDINATES
  825. case GroupCode_XComp:
  826. out.x = reader.ValueAsFloat();
  827. break;
  828. case GroupCode_YComp:
  829. out.y = reader.ValueAsFloat();
  830. break;
  831. case GroupCode_ZComp:
  832. out.z = reader.ValueAsFloat();
  833. break;
  834. // POLYFACE vertex indices
  835. case 71:
  836. case 72:
  837. case 73:
  838. case 74: {
  839. if (cnti == 4) {
  840. ASSIMP_LOG_WARN("DXF: more than 4 indices per face not supported; ignoring");
  841. break;
  842. }
  843. const int index = reader.ValueAsSignedInt();
  844. if (index >= 0) {
  845. indices[cnti++] = static_cast<unsigned int>(index);
  846. } else {
  847. indices[cnti++] = static_cast<unsigned int>(-index);
  848. }
  849. }
  850. break;
  851. // color
  852. case 62:
  853. clr = g_aclrDxfIndexColors[reader.ValueAsUnsignedInt() % AI_DXF_NUM_INDEX_COLORS];
  854. break;
  855. };
  856. reader++;
  857. }
  858. if (line.flags & DXF_POLYLINE_FLAG_POLYFACEMESH && !(flags & DXF_VERTEX_FLAG_PART_OF_POLYFACE)) {
  859. ASSIMP_LOG_WARN("DXF: expected vertex to be part of a polyface but the 0x128 flag isn't set");
  860. }
  861. if (cnti) {
  862. line.counts.push_back(cnti);
  863. for (unsigned int i = 0; i < cnti; ++i) {
  864. // IMPORTANT NOTE: POLYMESH indices are ONE-BASED
  865. if (indices[i] == 0) {
  866. ASSIMP_LOG_WARN("DXF: invalid vertex index, indices are one-based.");
  867. --line.counts.back();
  868. // Workaround to fix issue 2229
  869. if (line.counts.back() == 0) {
  870. line.counts.pop_back();
  871. }
  872. continue;
  873. }
  874. line.indices.push_back(indices[i]-1);
  875. }
  876. } else {
  877. line.positions.push_back(out);
  878. line.colors.push_back(clr);
  879. }
  880. }
  881. // ------------------------------------------------------------------------------------------------
  882. void DXFImporter::Parse3DFace(DXF::LineReader& reader, DXF::FileData& output) {
  883. // (note) this is also used for for parsing line entities, so we
  884. // must handle the vertex_count == 2 case as well.
  885. output.blocks.back().lines.push_back( std::shared_ptr<DXF::PolyLine>( new DXF::PolyLine() ) );
  886. DXF::PolyLine& line = *output.blocks.back().lines.back();
  887. aiVector3D vip[4];
  888. aiColor4D clr = AI_DXF_DEFAULT_COLOR;
  889. bool b[4] = {false,false,false,false};
  890. while( !reader.End() ) {
  891. // next entity with a groupcode == 0 is probably already the next vertex or polymesh entity
  892. if (reader.GroupCode() == 0) {
  893. break;
  894. }
  895. switch (reader.GroupCode()) {
  896. // 8 specifies the layer
  897. case 8:
  898. line.layer = reader.Value();
  899. break;
  900. // x position of the first corner
  901. case 10:
  902. vip[0].x = reader.ValueAsFloat();
  903. b[2] = true;
  904. break;
  905. // y position of the first corner
  906. case 20:
  907. vip[0].y = reader.ValueAsFloat();
  908. b[2] = true;
  909. break;
  910. // z position of the first corner
  911. case 30:
  912. vip[0].z = reader.ValueAsFloat();
  913. b[2] = true;
  914. break;
  915. // x position of the second corner
  916. case 11:
  917. vip[1].x = reader.ValueAsFloat();
  918. b[3] = true;
  919. break;
  920. // y position of the second corner
  921. case 21:
  922. vip[1].y = reader.ValueAsFloat();
  923. b[3] = true;
  924. break;
  925. // z position of the second corner
  926. case 31:
  927. vip[1].z = reader.ValueAsFloat();
  928. b[3] = true;
  929. break;
  930. // x position of the third corner
  931. case 12:
  932. vip[2].x = reader.ValueAsFloat();
  933. b[0] = true;
  934. break;
  935. // y position of the third corner
  936. case 22:
  937. vip[2].y = reader.ValueAsFloat();
  938. b[0] = true;
  939. break;
  940. // z position of the third corner
  941. case 32:
  942. vip[2].z = reader.ValueAsFloat();
  943. b[0] = true;
  944. break;
  945. // x position of the fourth corner
  946. case 13:
  947. vip[3].x = reader.ValueAsFloat();
  948. b[1] = true;
  949. break;
  950. // y position of the fourth corner
  951. case 23:
  952. vip[3].y = reader.ValueAsFloat();
  953. b[1] = true;
  954. break;
  955. // z position of the fourth corner
  956. case 33:
  957. vip[3].z = reader.ValueAsFloat();
  958. b[1] = true;
  959. break;
  960. // color
  961. case 62:
  962. clr = g_aclrDxfIndexColors[reader.ValueAsUnsignedInt() % AI_DXF_NUM_INDEX_COLORS];
  963. break;
  964. };
  965. ++reader;
  966. }
  967. // the fourth corner may even be identical to the third,
  968. // in this case we treat it as if it didn't exist.
  969. if (vip[3] == vip[2]) {
  970. b[1] = false;
  971. }
  972. // sanity checks to see if we got something meaningful
  973. if ((b[1] && !b[0]) || !b[2] || !b[3]) {
  974. ASSIMP_LOG_WARN("DXF: unexpected vertex setup in 3DFACE/LINE/FACE entity; ignoring");
  975. output.blocks.back().lines.pop_back();
  976. return;
  977. }
  978. const unsigned int cnt = (2+(b[0]?1:0)+(b[1]?1:0));
  979. line.counts.push_back(cnt);
  980. for (unsigned int i = 0; i < cnt; ++i) {
  981. line.indices.push_back(static_cast<unsigned int>(line.positions.size()));
  982. line.positions.push_back(vip[i]);
  983. line.colors.push_back(clr);
  984. }
  985. }
  986. #endif // !! ASSIMP_BUILD_NO_DXF_IMPORTER