@@ -143,6 +143,10 @@ protected override void Process(IFCAnyHandle ifcProjectHandle)
143
143
// process true north - take the first valid representation context that has a true north value.
144
144
HashSet < IFCAnyHandle > repContexts = IFCAnyHandleUtil . GetAggregateInstanceAttribute < HashSet < IFCAnyHandle > > ( ifcProjectHandle , "RepresentationContexts" ) ;
145
145
146
+ bool hasMapConv = false ;
147
+ XYZ geoRef = XYZ . Zero ;
148
+ string geoRefName = null ;
149
+ double trueNorth = 0.0 ;
146
150
if ( repContexts != null )
147
151
{
148
152
foreach ( IFCAnyHandle geomRepContextHandle in repContexts )
@@ -161,37 +165,122 @@ protected override void Process(IFCAnyHandle ifcProjectHandle)
161
165
{
162
166
WorldCoordinateSystem = context . WorldCoordinateSystem ;
163
167
}
168
+
169
+ // Process Map Conversion if any
170
+ HashSet < IFCAnyHandle > coordOperation = IFCAnyHandleUtil . GetAggregateInstanceAttribute < HashSet < IFCAnyHandle > > ( geomRepContextHandle , "HasCoordinateOperation" ) ;
171
+ if ( coordOperation != null )
172
+ if ( coordOperation . Count > 0 )
173
+ {
174
+ if ( IFCAnyHandleUtil . IsSubTypeOf ( coordOperation . FirstOrDefault ( ) , IFCEntityType . IfcMapConversion ) )
175
+ {
176
+ hasMapConv = true ;
177
+ IFCAnyHandle mapConv = coordOperation . FirstOrDefault ( ) ;
178
+ bool found = false ;
179
+ double eastings = IFCImportHandleUtil . GetRequiredScaledLengthAttribute ( mapConv , "Eastings" , out found ) ;
180
+ if ( ! found )
181
+ eastings = 0.0 ;
182
+ double northings = IFCImportHandleUtil . GetRequiredScaledLengthAttribute ( mapConv , "Northings" , out found ) ;
183
+ if ( ! found )
184
+ northings = 0.0 ;
185
+ double orthogonalHeight = IFCImportHandleUtil . GetRequiredScaledLengthAttribute ( mapConv , "OrthogonalHeight" , out found ) ;
186
+ if ( ! found )
187
+ orthogonalHeight = 0.0 ;
188
+ double xAxisAbs = IFCImportHandleUtil . GetOptionalRealAttribute ( mapConv , "XAxisAbscissa" , 1.0 ) ;
189
+ double xAxisOrd = IFCImportHandleUtil . GetOptionalRealAttribute ( mapConv , "XAxisOrdinate" , 0.0 ) ;
190
+ trueNorth = Math . Atan2 ( xAxisOrd , xAxisAbs ) ;
191
+ //angleToNorth = -((xAxisAngle > -Math.PI / 2.0) ? xAxisAngle - Math.PI / 2.0 : xAxisAngle + Math.PI * 1.5);
192
+ double scale = IFCImportHandleUtil . GetOptionalRealAttribute ( mapConv , "Scale" , 1.0 ) ;
193
+ geoRef = new XYZ ( scale * eastings , scale * northings , scale * orthogonalHeight ) ;
194
+
195
+ // Process the IfcProjectedCRS
196
+ IFCAnyHandle projCRS = IFCAnyHandleUtil . GetInstanceAttribute ( mapConv , "TargetCRS" ) ;
197
+ if ( projCRS != null && IFCAnyHandleUtil . IsSubTypeOf ( projCRS , IFCEntityType . IfcProjectedCRS ) )
198
+ {
199
+ geoRefName = IFCImportHandleUtil . GetRequiredStringAttribute ( projCRS , "Name" , false ) ;
200
+ string desc = IFCImportHandleUtil . GetOptionalStringAttribute ( projCRS , "Description" , null ) ;
201
+ string geodeticDatum = IFCImportHandleUtil . GetOptionalStringAttribute ( projCRS , "GeodeticDatum" , null ) ;
202
+ string verticalDatum = IFCImportHandleUtil . GetOptionalStringAttribute ( projCRS , "VerticalDatum" , null ) ;
203
+ string mapProj = IFCImportHandleUtil . GetOptionalStringAttribute ( projCRS , "MapProjection" , null ) ;
204
+ string mapZone = IFCImportHandleUtil . GetOptionalStringAttribute ( projCRS , "MapZone" , null ) ;
205
+ IFCAnyHandle mapUnit = IFCImportHandleUtil . GetOptionalInstanceAttribute ( projCRS , "MapUnit" ) ;
206
+
207
+ Document doc = IFCImportFile . TheFile . Document ;
208
+ ProjectInfo projectInfo = doc . ProjectInformation ;
209
+ Category category = IFCPropertySet . GetCategoryForParameterIfValid ( projectInfo , Id ) ;
210
+ IFCPropertySet . AddParameterString ( doc , projectInfo , category , this , "IfcProjectedCRS.Name" , geoRefName , Id ) ;
211
+ if ( ! string . IsNullOrEmpty ( desc ) )
212
+ IFCPropertySet . AddParameterString ( doc , projectInfo , category , this , "IfcProjectedCRS.Description" , desc , Id ) ;
213
+ if ( ! string . IsNullOrEmpty ( geodeticDatum ) )
214
+ IFCPropertySet . AddParameterString ( doc , projectInfo , category , this , "IfcProjectedCRS.GeodeticDatum" , geodeticDatum , Id ) ;
215
+ if ( ! string . IsNullOrEmpty ( verticalDatum ) )
216
+ IFCPropertySet . AddParameterString ( doc , projectInfo , category , this , "IfcProjectedCRS.VerticalDatum" , verticalDatum , Id ) ;
217
+ if ( ! string . IsNullOrEmpty ( mapProj ) )
218
+ IFCPropertySet . AddParameterString ( doc , projectInfo , category , this , "IfcProjectedCRS.MapProjection" , mapProj , Id ) ;
219
+ if ( ! string . IsNullOrEmpty ( mapZone ) )
220
+ IFCPropertySet . AddParameterString ( doc , projectInfo , category , this , "IfcProjectedCRS.MapZone" , mapZone , Id ) ;
221
+ if ( ! IFCAnyHandleUtil . IsNullOrHasNoValue ( mapUnit ) )
222
+ {
223
+ IFCUnit mapUnitIfc = IFCUnit . ProcessIFCUnit ( mapUnit ) ;
224
+ string unitStr = UnitUtils . GetTypeCatalogStringForUnit ( mapUnitIfc . Unit ) ;
225
+ IFCPropertySet . AddParameterString ( doc , projectInfo , category , this , "IfcProjectedCRS.MapUnit" , unitStr , Id ) ;
226
+ }
227
+ }
228
+ }
229
+ }
164
230
}
165
231
}
166
232
167
233
ProjectLocation projectLocation = IFCImportFile . TheFile . Document . ActiveProjectLocation ;
234
+ ProjectPosition projectPosition ;
168
235
if ( projectLocation != null )
169
236
{
170
- // Set initial project location based on the information above.
171
- // This may be further modified by the site.
172
- double trueNorth = 0.0 ;
173
- if ( TrueNorthDirection != null )
237
+ if ( hasMapConv )
174
238
{
175
- double geometricAngle = Math . Atan2 ( TrueNorthDirection . V , TrueNorthDirection . U ) ;
176
- // Convert from geometric angle to compass direction.
177
- // This involves two steps: (1) subtract PI/2 from the angle, staying in (-PI, PI], then (2) reversing the result.
178
- trueNorth = ( geometricAngle > - Math . PI / 2.0 ) ? geometricAngle - Math . PI / 2.0 : geometricAngle + Math . PI * 1.5 ;
179
- trueNorth = - trueNorth ;
180
- }
239
+ projectPosition = new ProjectPosition ( geoRef . X , geoRef . Y , geoRef . Z , trueNorth ) ;
240
+ projectLocation . SetProjectPosition ( XYZ . Zero , projectPosition ) ;
181
241
182
- // TODO: Extend this to work properly if the world coordinate system
183
- // isn't a simple translation.
184
- XYZ origin = XYZ . Zero ;
185
- if ( WorldCoordinateSystem != null &&
186
- WorldCoordinateSystem . IsTranslation &&
187
- ! XYZ . IsWithinLengthLimits ( WorldCoordinateSystem . Origin ) )
188
- {
189
- origin = WorldCoordinateSystem . Origin ;
190
- WorldCoordinateSystem = null ;
242
+ if ( ! string . IsNullOrEmpty ( geoRefName ) )
243
+ IFCImportFile . TheFile . Document . SiteLocation . SetGeoCoordinateSystem ( geoRefName ) ;
191
244
}
245
+ else
246
+ {
247
+ // Set initial project location based on the information above.
248
+ // This may be further modified by the site.
249
+ trueNorth = 0.0 ;
250
+ if ( TrueNorthDirection != null )
251
+ {
252
+ trueNorth = - Math . Atan2 ( - TrueNorthDirection . U , TrueNorthDirection . V ) ;
253
+ }
192
254
193
- ProjectPosition projectPosition = new ProjectPosition ( origin . X , origin . Y , origin . Z , trueNorth ) ;
194
- projectLocation . SetProjectPosition ( XYZ . Zero , projectPosition ) ;
255
+ // TODO: Extend this to work properly if the world coordinate system
256
+ // isn't a simple translation.
257
+ XYZ origin = XYZ . Zero ;
258
+ if ( WorldCoordinateSystem != null )
259
+ {
260
+ geoRef = WorldCoordinateSystem . Origin ;
261
+ double angleRot = Math . Atan2 ( WorldCoordinateSystem . BasisX . Y , WorldCoordinateSystem . BasisX . X ) ;
262
+
263
+ // If it is translation only, or if the WCS rotation is equal to trueNorth, we assume they are the same
264
+ if ( WorldCoordinateSystem . IsTranslation
265
+ || MathUtil . IsAlmostEqual ( angleRot , trueNorth ) )
266
+ {
267
+ WorldCoordinateSystem = null ;
268
+ }
269
+ else
270
+ {
271
+ // If the trueNorth is not set (=0), set the trueNorth by the rotation of the WCS, otherwise add the angle
272
+ if ( MathUtil . IsAlmostZero ( trueNorth ) )
273
+ trueNorth = angleRot ;
274
+ else
275
+ trueNorth += angleRot ;
276
+
277
+ WorldCoordinateSystem = null ;
278
+ }
279
+ }
280
+
281
+ projectPosition = new ProjectPosition ( geoRef . X , geoRef . Y , geoRef . Z , trueNorth ) ;
282
+ projectLocation . SetProjectPosition ( XYZ . Zero , projectPosition ) ;
283
+ }
195
284
}
196
285
}
197
286
}
0 commit comments