Skip to content

Commit 1df8a14

Browse files
author
Wawan Solihin
committed
Fixed issue with placements on import
1 parent 4348681 commit 1df8a14

File tree

2 files changed

+114
-49
lines changed

2 files changed

+114
-49
lines changed

Source/Revit.IFC.Import/Data/IFCProject.cs

+110-21
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,10 @@ protected override void Process(IFCAnyHandle ifcProjectHandle)
143143
// process true north - take the first valid representation context that has a true north value.
144144
HashSet<IFCAnyHandle> repContexts = IFCAnyHandleUtil.GetAggregateInstanceAttribute<HashSet<IFCAnyHandle>>(ifcProjectHandle, "RepresentationContexts");
145145

146+
bool hasMapConv = false;
147+
XYZ geoRef = XYZ.Zero;
148+
string geoRefName = null;
149+
double trueNorth = 0.0;
146150
if (repContexts != null)
147151
{
148152
foreach (IFCAnyHandle geomRepContextHandle in repContexts)
@@ -161,37 +165,122 @@ protected override void Process(IFCAnyHandle ifcProjectHandle)
161165
{
162166
WorldCoordinateSystem = context.WorldCoordinateSystem;
163167
}
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+
}
164230
}
165231
}
166232

167233
ProjectLocation projectLocation = IFCImportFile.TheFile.Document.ActiveProjectLocation;
234+
ProjectPosition projectPosition;
168235
if (projectLocation != null)
169236
{
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)
174238
{
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);
181241

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);
191244
}
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+
}
192254

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+
}
195284
}
196285
}
197286
}

Source/Revit.IFC.Import/Data/IFCSite.cs

+4-28
Original file line numberDiff line numberDiff line change
@@ -322,22 +322,8 @@ public static void ProcessSiteLocations(Document doc, IList<IFCSite> sites)
322322
continue;
323323
}
324324

325-
double elevationToUse = currSite.RefElevation;
326325
XYZ projectLoc = currSite.ObjectLocation.RelativeTransform.Origin;
327-
if (!MathUtil.IsAlmostZero(projectLoc.Z))
328-
{
329-
if (MathUtil.IsAlmostZero(elevationToUse))
330-
{
331-
currSite.RefElevation = projectLoc.Z;
332-
Importer.TheLog.LogError(currSite.Id, "The Z-value of the IfcSite object placement relative transform should be zero. This will override the RefElevation value of zero.", false);
333-
}
334-
else
335-
{
336-
Importer.TheLog.LogError(currSite.Id, "The Z-value of the IfcSite object placement relative transform should be zero. This will be ignored in favor of the non-zero RefElevation value.", false);
337-
}
338-
}
339-
340-
XYZ offset = new XYZ(projectLoc.X, projectLoc.Y, elevationToUse);
326+
XYZ offset = new XYZ(projectLoc.X, projectLoc.Y, projectLoc.Z);
341327
if (XYZ.IsWithinLengthLimits(offset))
342328
{
343329
if (distantOriginFirstSiteId.HasValue)
@@ -351,7 +337,7 @@ public static void ProcessSiteLocations(Document doc, IList<IFCSite> sites)
351337
if (BaseSiteOffset == null)
352338
{
353339
distantOriginFirstSiteId = currSite.Id;
354-
340+
355341
// If the index is greater than 0, then we have found some sites close to the
356342
// origin. That means we have incompatible origins which is an issue.
357343
if (ii == 0)
@@ -363,20 +349,12 @@ public static void ProcessSiteLocations(Document doc, IList<IFCSite> sites)
363349

364350
if (BaseSiteOffset != null)
365351
{
366-
ProjectPosition projectPosition = projectLocation.GetProjectPosition(XYZ.Zero);
367-
368-
projectPosition.EastWest += BaseSiteOffset.X;
369-
projectPosition.NorthSouth += BaseSiteOffset.Y;
370-
projectPosition.Elevation += BaseSiteOffset.Z;
371-
372-
projectLocation.SetProjectPosition(XYZ.Zero, projectPosition);
373-
374352
// Modify the RelativeTransforms for each of these sites.
375353
// Note that the RelativeTransform must be defined to have gotten here.
376354
for (int ii = 0; ii < numSites; ii++)
377355
{
378-
XYZ currentOffset =
379-
new XYZ(-BaseSiteOffset.X, -BaseSiteOffset.Y, -BaseSiteOffset.Z + sites[ii].RefElevation);
356+
XYZ currentOffset =
357+
new XYZ(-BaseSiteOffset.X, -BaseSiteOffset.Y, -BaseSiteOffset.Z /*+ sites[ii].RefElevation*/);
380358
Transform newSiteTransform = sites[ii].ObjectLocation.TotalTransform;
381359
newSiteTransform.Origin += currentOffset;
382360
sites[ii].ObjectLocation = IFCLocation.CreateDummyLocation(newSiteTransform);
@@ -402,9 +380,7 @@ public static void ProcessSiteLocations(Document doc, IList<IFCSite> sites)
402380
double currZOffset = sites[ii].ObjectLocation.RelativeTransform.Origin.Z;
403381
if (!MathUtil.IsAlmostEqual(currZOffset, currRefElevation))
404382
{
405-
XYZ currentOffset = new XYZ(0, 0, currRefElevation - currZOffset);
406383
Transform newSiteTransform = sites[ii].ObjectLocation.TotalTransform;
407-
newSiteTransform.Origin += currentOffset;
408384
sites[ii].ObjectLocation = IFCLocation.CreateDummyLocation(newSiteTransform);
409385
}
410386
}

0 commit comments

Comments
 (0)