/src/assimp/code/AssetLib/IFC/IFCProfile.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | Open Asset Import Library (assimp) |
3 | | ---------------------------------------------------------------------- |
4 | | |
5 | | Copyright (c) 2006-2025, assimp team |
6 | | |
7 | | All rights reserved. |
8 | | |
9 | | Redistribution and use of this software in source and binary forms, |
10 | | with or without modification, are permitted provided that the |
11 | | following conditions are met: |
12 | | |
13 | | * Redistributions of source code must retain the above |
14 | | copyright notice, this list of conditions and the |
15 | | following disclaimer. |
16 | | |
17 | | * Redistributions in binary form must reproduce the above |
18 | | copyright notice, this list of conditions and the |
19 | | following disclaimer in the documentation and/or other |
20 | | materials provided with the distribution. |
21 | | |
22 | | * Neither the name of the assimp team, nor the names of its |
23 | | contributors may be used to endorse or promote products |
24 | | derived from this software without specific prior |
25 | | written permission of the assimp team. |
26 | | |
27 | | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
28 | | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
29 | | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
30 | | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
31 | | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
32 | | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
33 | | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
34 | | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
35 | | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
36 | | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
37 | | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
38 | | |
39 | | ---------------------------------------------------------------------- |
40 | | */ |
41 | | |
42 | | /// @file IFCProfile.cpp |
43 | | /// @brief Read profile and curves entities from IFC files |
44 | | |
45 | | #ifndef ASSIMP_BUILD_NO_IFC_IMPORTER |
46 | | |
47 | | #include "IFCUtil.h" |
48 | | |
49 | | namespace Assimp { |
50 | | namespace IFC { |
51 | | |
52 | | // ------------------------------------------------------------------------------------------------ |
53 | | void ProcessPolyLine(const Schema_2x3::IfcPolyline& def, |
54 | | TempMesh& meshout, |
55 | 0 | ConversionData& /*conv*/) { |
56 | | // this won't produce a valid mesh, it just spits out a list of vertices |
57 | 0 | IfcVector3 t; |
58 | 0 | for(const Schema_2x3::IfcCartesianPoint& cp : def.Points) { |
59 | 0 | ConvertCartesianPoint(t,cp); |
60 | 0 | meshout.mVerts.push_back(t); |
61 | 0 | } |
62 | 0 | meshout.mVertcnt.push_back(static_cast<unsigned int>(meshout.mVerts.size())); |
63 | 0 | } |
64 | | |
65 | | // ------------------------------------------------------------------------------------------------ |
66 | | bool ProcessCurve(const Schema_2x3::IfcCurve& curve, |
67 | | TempMesh& meshout, |
68 | 0 | ConversionData& conv) { |
69 | 0 | std::unique_ptr<const Curve> cv(Curve::Convert(curve,conv)); |
70 | 0 | if (!cv) { |
71 | 0 | IFCImporter::LogWarn("skipping unknown IfcCurve entity, type is ", curve.GetClassName()); |
72 | 0 | return false; |
73 | 0 | } |
74 | | |
75 | | // we must have a bounded curve at this point |
76 | 0 | if (const BoundedCurve* bc = dynamic_cast<const BoundedCurve*>(cv.get())) { |
77 | 0 | try { |
78 | 0 | bc->SampleDiscrete(meshout); |
79 | 0 | } |
80 | 0 | catch(const CurveError& cv) { |
81 | 0 | IFCImporter::LogError(cv.mStr, " (error occurred while processing curve)"); |
82 | 0 | return false; |
83 | 0 | } |
84 | 0 | meshout.mVertcnt.push_back(static_cast<unsigned int>(meshout.mVerts.size())); |
85 | 0 | return true; |
86 | 0 | } |
87 | | |
88 | 0 | IFCImporter::LogError("cannot use unbounded curve as profile"); |
89 | 0 | return false; |
90 | 0 | } |
91 | | |
92 | | // ------------------------------------------------------------------------------------------------ |
93 | | void ProcessClosedProfile(const Schema_2x3::IfcArbitraryClosedProfileDef& def, |
94 | | TempMesh& meshout, |
95 | 0 | ConversionData& conv) { |
96 | 0 | ProcessCurve(def.OuterCurve,meshout,conv); |
97 | 0 | } |
98 | | |
99 | | // ------------------------------------------------------------------------------------------------ |
100 | | void ProcessOpenProfile(const Schema_2x3::IfcArbitraryOpenProfileDef& def, |
101 | | TempMesh& meshout, |
102 | 0 | ConversionData& conv) { |
103 | 0 | ProcessCurve(def.Curve,meshout,conv); |
104 | 0 | } |
105 | | |
106 | | // ------------------------------------------------------------------------------------------------ |
107 | | void ProcessParametrizedProfile(const Schema_2x3::IfcParameterizedProfileDef& def, |
108 | | TempMesh& meshout, |
109 | 0 | ConversionData& conv) { |
110 | 0 | if(const Schema_2x3::IfcRectangleProfileDef* const cprofile = def.ToPtr<Schema_2x3::IfcRectangleProfileDef>()) { |
111 | 0 | const IfcFloat x = cprofile->XDim*0.5f, y = cprofile->YDim*0.5f; |
112 | |
|
113 | 0 | meshout.mVerts.reserve(meshout.mVerts.size()+4); |
114 | 0 | meshout.mVerts.emplace_back( x, y, 0.f ); |
115 | 0 | meshout.mVerts.emplace_back(-x, y, 0.f ); |
116 | 0 | meshout.mVerts.emplace_back(-x,-y, 0.f ); |
117 | 0 | meshout.mVerts.emplace_back( x,-y, 0.f ); |
118 | 0 | meshout.mVertcnt.push_back(4); |
119 | 0 | } else if( const Schema_2x3::IfcCircleProfileDef* const circle = def.ToPtr<Schema_2x3::IfcCircleProfileDef>()) { |
120 | 0 | if(def.ToPtr<Schema_2x3::IfcCircleHollowProfileDef>()) { |
121 | | // TODO |
122 | 0 | } |
123 | 0 | const size_t segments = conv.settings.cylindricalTessellation; |
124 | 0 | const IfcFloat delta = AI_MATH_TWO_PI_F/segments, radius = circle->Radius; |
125 | |
|
126 | 0 | meshout.mVerts.reserve(segments); |
127 | |
|
128 | 0 | IfcFloat angle = 0.f; |
129 | 0 | for(size_t i = 0; i < segments; ++i, angle += delta) { |
130 | 0 | meshout.mVerts.emplace_back( std::cos(angle)*radius, std::sin(angle)*radius, 0.f ); |
131 | 0 | } |
132 | |
|
133 | 0 | meshout.mVertcnt.push_back(static_cast<unsigned int>(segments)); |
134 | 0 | } else if( const Schema_2x3::IfcIShapeProfileDef* const ishape = def.ToPtr<Schema_2x3::IfcIShapeProfileDef>()) { |
135 | | // construct simplified IBeam shape |
136 | 0 | const IfcFloat offset = (ishape->OverallWidth - ishape->WebThickness) / 2; |
137 | 0 | const IfcFloat inner_height = ishape->OverallDepth - ishape->FlangeThickness * 2; |
138 | |
|
139 | 0 | meshout.mVerts.reserve(12); |
140 | 0 | meshout.mVerts.emplace_back(0,0,0); |
141 | 0 | meshout.mVerts.emplace_back(0,ishape->FlangeThickness,0); |
142 | 0 | meshout.mVerts.emplace_back(offset,ishape->FlangeThickness,0); |
143 | 0 | meshout.mVerts.emplace_back(offset,ishape->FlangeThickness + inner_height,0); |
144 | 0 | meshout.mVerts.emplace_back(0,ishape->FlangeThickness + inner_height,0); |
145 | 0 | meshout.mVerts.emplace_back(0,ishape->OverallDepth,0); |
146 | 0 | meshout.mVerts.emplace_back(ishape->OverallWidth,ishape->OverallDepth,0); |
147 | 0 | meshout.mVerts.emplace_back(ishape->OverallWidth,ishape->FlangeThickness + inner_height,0); |
148 | 0 | meshout.mVerts.emplace_back(offset+ishape->WebThickness,ishape->FlangeThickness + inner_height,0); |
149 | 0 | meshout.mVerts.emplace_back(offset+ishape->WebThickness,ishape->FlangeThickness,0); |
150 | 0 | meshout.mVerts.emplace_back(ishape->OverallWidth,ishape->FlangeThickness,0); |
151 | 0 | meshout.mVerts.emplace_back(ishape->OverallWidth,0,0); |
152 | |
|
153 | 0 | meshout.mVertcnt.push_back(12); |
154 | 0 | } else { |
155 | 0 | IFCImporter::LogWarn("skipping unknown IfcParameterizedProfileDef entity, type is ", def.GetClassName()); |
156 | 0 | return; |
157 | 0 | } |
158 | | |
159 | 0 | IfcMatrix4 trafo; |
160 | 0 | ConvertAxisPlacement(trafo, *def.Position); |
161 | 0 | meshout.Transform(trafo); |
162 | 0 | } |
163 | | |
164 | | // ------------------------------------------------------------------------------------------------ |
165 | 0 | bool ProcessProfile(const Schema_2x3::IfcProfileDef& prof, TempMesh& meshout, ConversionData& conv) { |
166 | 0 | if(const Schema_2x3::IfcArbitraryClosedProfileDef* const cprofile = prof.ToPtr<Schema_2x3::IfcArbitraryClosedProfileDef>()) { |
167 | 0 | ProcessClosedProfile(*cprofile,meshout,conv); |
168 | 0 | } else if(const Schema_2x3::IfcArbitraryOpenProfileDef* const copen = prof.ToPtr<Schema_2x3::IfcArbitraryOpenProfileDef>()) { |
169 | 0 | ProcessOpenProfile(*copen,meshout,conv); |
170 | 0 | } else if(const Schema_2x3::IfcParameterizedProfileDef* const cparam = prof.ToPtr<Schema_2x3::IfcParameterizedProfileDef>()) { |
171 | 0 | ProcessParametrizedProfile(*cparam,meshout,conv); |
172 | 0 | } else { |
173 | 0 | IFCImporter::LogWarn("skipping unknown IfcProfileDef entity, type is ", prof.GetClassName()); |
174 | 0 | return false; |
175 | 0 | } |
176 | 0 | meshout.RemoveAdjacentDuplicates(); |
177 | 0 | if (!meshout.mVertcnt.size() || meshout.mVertcnt.front() <= 1) { |
178 | 0 | return false; |
179 | 0 | } |
180 | 0 | return true; |
181 | 0 | } |
182 | | |
183 | | } // ! IFC |
184 | | } // ! Assimp |
185 | | |
186 | | #endif // ASSIMP_BUILD_NO_IFC_IMPORTER |