fc552d84 |
1 | // Author: Kirill Gavrilov |
2 | // Copyright (c) 2016-2019 OPEN CASCADE SAS |
3 | // |
4 | // This file is part of Open CASCADE Technology software library. |
5 | // |
6 | // This library is free software; you can redistribute it and/or modify it under |
7 | // the terms of the GNU Lesser General Public License version 2.1 as published |
8 | // by the Free Software Foundation, with special exception defined in the file |
9 | // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT |
10 | // distribution for complete text of the license and disclaimer of any warranty. |
11 | // |
12 | // Alternatively, this file may be used under the terms of Open CASCADE |
13 | // commercial license or contractual agreement. |
14 | |
15 | #ifndef _RWMesh_CafReader_HeaderFile |
16 | #define _RWMesh_CafReader_HeaderFile |
17 | |
7e785937 |
18 | #include <Message_ProgressRange.hxx> |
0435edfe |
19 | #include <OSD_OpenFile.hxx> |
fc552d84 |
20 | #include <RWMesh_CoordinateSystemConverter.hxx> |
21 | #include <RWMesh_NodeAttributes.hxx> |
22 | #include <TColStd_IndexedDataMapOfStringString.hxx> |
23 | #include <TDF_Label.hxx> |
24 | #include <TopTools_SequenceOfShape.hxx> |
25 | |
fc552d84 |
26 | class TDocStd_Document; |
5a8d30b8 |
27 | class XCAFDoc_ShapeTool; |
28 | class XCAFDoc_ColorTool; |
29 | class XCAFDoc_VisMaterialTool; |
fc552d84 |
30 | |
31 | //! Extended status bits. |
32 | enum RWMesh_CafReaderStatusEx |
33 | { |
34 | RWMesh_CafReaderStatusEx_NONE = 0, //!< empty status |
35 | RWMesh_CafReaderStatusEx_Partial = 0x01, //!< partial read (due to unexpected EOF, syntax error, memory limit) |
36 | }; |
37 | |
38 | //! The general interface for importing mesh data into XDE document. |
39 | //! |
40 | //! The tool implements auxiliary structures for creating an XDE document in two steps: |
41 | //! 1) Creating TopoDS_Shape hierarchy (myRootShapes) |
42 | //! and Shape attributes (myAttribMap) separately within performMesh(). |
43 | //! Attributes include names and styles. |
44 | //! 2) Filling XDE document from these auxiliary structures. |
45 | //! Named elements are expanded within document structure, while Compounds having no named children will remain collapsed. |
46 | //! In addition, unnamed nodes can be filled with generated names like "Face", "Compound" via generateNames() method, |
47 | //! and the very root unnamed node can be filled from file name like "MyModel.obj". |
48 | class RWMesh_CafReader : public Standard_Transient |
49 | { |
50 | DEFINE_STANDARD_RTTIEXT(RWMesh_CafReader, Standard_Transient) |
5a8d30b8 |
51 | public: |
52 | |
53 | //! Structure holding tools for filling the document. |
54 | struct CafDocumentTools |
55 | { |
56 | Handle(XCAFDoc_ShapeTool) ShapeTool; |
57 | Handle(XCAFDoc_ColorTool) ColorTool; |
58 | Handle(XCAFDoc_VisMaterialTool) VisMaterialTool; |
59 | NCollection_DataMap<TopoDS_Shape, TDF_Label, TopTools_ShapeMapHasher> ComponentMap; |
60 | }; |
61 | |
fc552d84 |
62 | public: |
63 | |
64 | //! Empty constructor. |
65 | Standard_EXPORT RWMesh_CafReader(); |
66 | |
67 | //! Destructor. |
68 | Standard_EXPORT virtual ~RWMesh_CafReader(); |
69 | |
70 | //! Return target document. |
71 | const Handle(TDocStd_Document)& Document() const { return myXdeDoc; } |
72 | |
73 | //! Set target document. |
da80ff68 |
74 | //! Set system length unit according to the units of the document |
75 | Standard_EXPORT void SetDocument(const Handle(TDocStd_Document)& theDoc); |
fc552d84 |
76 | |
77 | //! Return prefix for generating root labels names. |
78 | const TCollection_AsciiString& RootPrefix() const { return myRootPrefix; } |
79 | |
80 | //! Set prefix for generating root labels names |
81 | void SetRootPrefix (const TCollection_AsciiString& theRootPrefix) { myRootPrefix = theRootPrefix; } |
82 | |
83 | //! Flag indicating if partially read file content should be put into the XDE document, TRUE by default. |
84 | //! |
85 | //! Partial read means unexpected end of file, critical parsing syntax errors in the middle of file, or reached memory limit |
86 | //! indicated by performMesh() returning FALSE. |
87 | //! Partial read allows importing a model even in case of formal reading failure, |
88 | //! so that it will be up to user to decide if processed data has any value. |
89 | //! |
90 | //! In case of partial read (performMesh() returns FALSE, but there are some data that could be put into document), |
91 | //! Perform() will return TRUE and result flag will have failure bit set. |
92 | //! @sa MemoryLimitMiB(), ExtraStatus(). |
93 | Standard_Boolean ToFillIncompleteDocument() const { return myToFillIncomplete; } |
94 | |
95 | //! Set flag allowing partially read file content to be put into the XDE document. |
96 | void SetFillIncompleteDocument (Standard_Boolean theToFillIncomplete) { myToFillIncomplete = theToFillIncomplete; } |
97 | |
98 | //! Return memory usage limit in MiB, -1 by default which means no limit. |
99 | Standard_Integer MemoryLimitMiB() const { return myMemoryLimitMiB; } |
100 | |
101 | //! Set memory usage limit in MiB; can be ignored by reader implementation! |
102 | void SetMemoryLimitMiB (Standard_Integer theLimitMiB) { myMemoryLimitMiB = theLimitMiB; } |
103 | |
104 | public: |
105 | |
106 | //! Return coordinate system converter. |
107 | const RWMesh_CoordinateSystemConverter& CoordinateSystemConverter() const { return myCoordSysConverter; } |
108 | |
109 | //! Set coordinate system converter. |
110 | void SetCoordinateSystemConverter (const RWMesh_CoordinateSystemConverter& theConverter) { myCoordSysConverter = theConverter; } |
111 | |
112 | //! Return the length unit to convert into while reading the file, defined as scale factor for m (meters); |
113 | //! -1.0 by default, which means that NO conversion will be applied. |
114 | Standard_Real SystemLengthUnit() const { return myCoordSysConverter.OutputLengthUnit(); } |
115 | |
116 | //! Set system length units to convert into while reading the file, defined as scale factor for m (meters). |
117 | void SetSystemLengthUnit (Standard_Real theUnits) { myCoordSysConverter.SetOutputLengthUnit (theUnits); } |
118 | |
119 | //! Return TRUE if system coordinate system has been defined; FALSE by default. |
120 | Standard_Boolean HasSystemCoordinateSystem() const { return myCoordSysConverter.HasOutputCoordinateSystem(); } |
121 | |
122 | //! Return system coordinate system; UNDEFINED by default, which means that no conversion will be done. |
123 | const gp_Ax3& SystemCoordinateSystem() const { return myCoordSysConverter.OutputCoordinateSystem(); } |
124 | |
125 | //! Set system origin coordinate system to perform conversion into during read. |
126 | void SetSystemCoordinateSystem (const gp_Ax3& theCS) { myCoordSysConverter.SetOutputCoordinateSystem (theCS); } |
127 | |
128 | //! Set system origin coordinate system to perform conversion into during read. |
129 | void SetSystemCoordinateSystem (RWMesh_CoordinateSystem theCS) { myCoordSysConverter.SetOutputCoordinateSystem (theCS); } |
130 | |
131 | //! Return the length unit to convert from while reading the file, defined as scale factor for m (meters). |
132 | //! Can be undefined (-1.0) if file format is unitless. |
133 | Standard_Real FileLengthUnit() const { return myCoordSysConverter.InputLengthUnit(); } |
134 | |
135 | //! Set (override) file length units to convert from while reading the file, defined as scale factor for m (meters). |
136 | void SetFileLengthUnit (Standard_Real theUnits) { myCoordSysConverter.SetInputLengthUnit (theUnits); } |
137 | |
138 | //! Return TRUE if file origin coordinate system has been defined. |
139 | Standard_Boolean HasFileCoordinateSystem() const { return myCoordSysConverter.HasInputCoordinateSystem(); } |
140 | |
141 | //! Return file origin coordinate system; can be UNDEFINED, which means no conversion will be done. |
142 | const gp_Ax3& FileCoordinateSystem() const { return myCoordSysConverter.InputCoordinateSystem(); } |
143 | |
144 | //! Set (override) file origin coordinate system to perform conversion during read. |
145 | void SetFileCoordinateSystem (const gp_Ax3& theCS) { myCoordSysConverter.SetInputCoordinateSystem (theCS); } |
146 | |
147 | //! Set (override) file origin coordinate system to perform conversion during read. |
148 | void SetFileCoordinateSystem (RWMesh_CoordinateSystem theCS) { myCoordSysConverter.SetInputCoordinateSystem (theCS); } |
149 | |
150 | public: |
151 | |
0435edfe |
152 | //! Open stream and pass it to Perform method. |
fc552d84 |
153 | //! The Document instance should be set beforehand. |
154 | bool Perform (const TCollection_AsciiString& theFile, |
7e785937 |
155 | const Message_ProgressRange& theProgress) |
fc552d84 |
156 | { |
0435edfe |
157 | std::ifstream aStream; |
158 | OSD_OpenStream(aStream, theFile, std::ios_base::in | std::ios_base::binary); |
159 | return Perform(aStream, theProgress, theFile); |
160 | } |
161 | |
162 | //! Read the data from specified file. |
163 | bool Perform (std::istream& theStream, |
164 | const Message_ProgressRange& theProgress, |
165 | const TCollection_AsciiString& theFile = "") |
166 | { |
167 | return perform(theStream, theFile, theProgress, Standard_False); |
fc552d84 |
168 | } |
169 | |
170 | //! Return extended status flags. |
171 | //! @sa RWMesh_CafReaderStatusEx enumeration. |
172 | Standard_Integer ExtraStatus() const { return myExtraStatus; } |
173 | |
174 | public: |
175 | |
176 | //! Return result as a single shape. |
177 | Standard_EXPORT TopoDS_Shape SingleShape() const; |
178 | |
179 | //! Return the list of complementary files - external references (textures, data, etc.). |
180 | const NCollection_IndexedMap<TCollection_AsciiString>& ExternalFiles() const { return myExternalFiles; } |
181 | |
182 | //! Return metadata map. |
183 | const TColStd_IndexedDataMapOfStringString& Metadata() const { return myMetadata; } |
184 | |
0435edfe |
185 | //! Open stream and pass it to ProbeHeader method. |
186 | Standard_Boolean ProbeHeader (const TCollection_AsciiString& theFile, |
187 | const Message_ProgressRange& theProgress = Message_ProgressRange()) |
188 | { |
189 | std::ifstream aStream; |
190 | OSD_OpenStream(aStream, theFile, std::ios_base::in | std::ios_base::binary); |
191 | return ProbeHeader (aStream, theFile, theProgress); |
192 | } |
193 | |
fc552d84 |
194 | //! Read the header data from specified file without reading entire model. |
195 | //! The main purpose is collecting metadata and external references - for copying model into a new location, for example. |
196 | //! Can be NOT implemented (unsupported by format / reader). |
0435edfe |
197 | Standard_Boolean ProbeHeader (std::istream& theStream, |
198 | const TCollection_AsciiString& theFile = "", |
7e785937 |
199 | const Message_ProgressRange& theProgress = Message_ProgressRange()) |
fc552d84 |
200 | { |
0435edfe |
201 | return perform(theStream, theFile, theProgress, Standard_True); |
fc552d84 |
202 | } |
203 | |
204 | protected: |
205 | |
0435edfe |
206 | //! Open stream and pass it to Perform method. |
fc552d84 |
207 | //! @param theFile file to read |
208 | //! @param optional progress indicator |
209 | //! @param theToProbe flag indicating that mesh data should be skipped and only basing information to be read |
82c59511 |
210 | Standard_EXPORT virtual Standard_Boolean perform (const TCollection_AsciiString& theFile, |
7e785937 |
211 | const Message_ProgressRange& theProgress, |
82c59511 |
212 | const Standard_Boolean theToProbe); |
fc552d84 |
213 | |
0435edfe |
214 | //! Read the data from specified file. |
215 | //! Default implementation calls performMesh() and fills XDE document from collected shapes. |
216 | //! @param theStream input stream |
217 | //! @param theFile path of additional files |
218 | //! @param optional progress indicator |
219 | //! @param theToProbe flag indicating that mesh data should be skipped and only basing information to be read |
220 | Standard_EXPORT virtual Standard_Boolean perform (std::istream& theStream, |
221 | const TCollection_AsciiString& theFile, |
222 | const Message_ProgressRange& theProgress, |
223 | const Standard_Boolean theToProbe); |
224 | |
225 | //! Read the mesh from specified file |
82c59511 |
226 | Standard_EXPORT virtual Standard_Boolean performMesh (const TCollection_AsciiString& theFile, |
0435edfe |
227 | const Message_ProgressRange& theProgress, |
228 | const Standard_Boolean theToProbe) |
229 | { |
230 | std::ifstream aStream; |
231 | OSD_OpenStream(aStream, theFile, std::ios_base::in | std::ios_base::binary); |
232 | return performMesh(aStream, theFile, theProgress, theToProbe); |
233 | } |
234 | |
235 | //! Read the mesh from specified file - interface to be implemented by sub-classes. |
236 | Standard_EXPORT virtual Standard_Boolean performMesh (std::istream& theStream, |
237 | const TCollection_AsciiString& theFile, |
7e785937 |
238 | const Message_ProgressRange& theProgress, |
82c59511 |
239 | const Standard_Boolean theToProbe) = 0; |
fc552d84 |
240 | |
241 | //! @name tools for filling XDE document |
242 | protected: |
243 | |
82c59511 |
244 | //! Fill document with new root shapes. |
596e7839 |
245 | Standard_EXPORT virtual void fillDocument(); |
82c59511 |
246 | |
fc552d84 |
247 | //! Append new shape into the document (recursively). |
5a8d30b8 |
248 | Standard_EXPORT Standard_Boolean addShapeIntoDoc (CafDocumentTools& theTools, |
249 | const TopoDS_Shape& theShape, |
fc552d84 |
250 | const TDF_Label& theLabel, |
251 | const TCollection_AsciiString& theParentName); |
252 | |
5a8d30b8 |
253 | //! Append new sub-shape into the document (recursively). |
254 | Standard_EXPORT Standard_Boolean addSubShapeIntoDoc (CafDocumentTools& theTools, |
255 | const TopoDS_Shape& theShape, |
596e7839 |
256 | const TDF_Label& theParentLabel); |
5a8d30b8 |
257 | |
258 | //! Put name attribute onto the label. |
259 | Standard_EXPORT void setShapeName (const TDF_Label& theLabel, |
260 | const TopAbs_ShapeEnum theShapeType, |
261 | const TCollection_AsciiString& theName, |
262 | const TDF_Label& theParentLabel, |
263 | const TCollection_AsciiString& theParentName); |
264 | |
265 | //! Put color and material attributes onto the label. |
266 | Standard_EXPORT void setShapeStyle (const CafDocumentTools& theTools, |
267 | const TDF_Label& theLabel, |
268 | const XCAFPrs_Style& theStyle); |
269 | |
270 | //! Put name data (metadata) attribute onto the label. |
271 | Standard_EXPORT void setShapeNamedData (const CafDocumentTools& theTools, |
272 | const TDF_Label& theLabel, |
273 | const Handle(TDataStd_NamedData)& theNameData); |
274 | |
fc552d84 |
275 | //! Generate names for root labels starting from specified index. |
276 | Standard_EXPORT void generateNames (const TCollection_AsciiString& theFile, |
277 | const Standard_Integer theRootLower, |
278 | const Standard_Boolean theWithSubLabels); |
279 | |
280 | //! Return shape type as string. |
281 | //! @sa TopAbs::ShapeTypeToString() |
282 | static TCollection_AsciiString shapeTypeToString (TopAbs_ShapeEnum theType) |
283 | { |
284 | TCollection_AsciiString aString = TopAbs::ShapeTypeToString (theType); |
285 | aString.Capitalize(); |
286 | return aString; |
287 | } |
288 | |
289 | protected: |
290 | |
291 | Handle(TDocStd_Document) myXdeDoc; //!< target document |
292 | |
293 | TColStd_IndexedDataMapOfStringString |
294 | myMetadata; //!< metadata map |
295 | NCollection_IndexedMap<TCollection_AsciiString> |
296 | myExternalFiles; //!< the list of complementary files - external references (textures, data, etc.) |
297 | TCollection_AsciiString myRootPrefix; //!< root folder for generating root labels names |
298 | TopTools_SequenceOfShape myRootShapes; //!< sequence of result root shapes |
299 | RWMesh_NodeAttributeMap myAttribMap; //!< map of per-shape attributes |
300 | |
301 | RWMesh_CoordinateSystemConverter |
302 | myCoordSysConverter; //!< coordinate system converter |
303 | Standard_Boolean myToFillDoc; //!< fill document from shape sequence |
304 | Standard_Boolean myToFillIncomplete; //!< fill the document with partially retrieved data even if reader has failed with error |
305 | Standard_Integer myMemoryLimitMiB; //!< memory usage limit |
306 | Standard_Integer myExtraStatus; //!< extra status bitmask |
307 | |
308 | }; |
309 | |
310 | #endif // _RWMesh_CafReader_HeaderFile |