Coverage Report

Created: 2025-12-05 06:25

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