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