public static void ProcessSiteLocations(Document doc, IList <IFCSite> sites) { BaseSiteOffset = null; // Ideally, in most cases, this routine will do nothing. In particular, that is // true if the project has an arbitrary number of sites that are "close" to the // origin. if (sites == null || sites.Count == 0) { return; } ProjectLocation projectLocation = doc.ActiveProjectLocation; if (projectLocation == null) { return; } // If there is one site, and it is far from the origin, then we will move the site // close to the origin, give a warning, and set the shared coordinates in the file. // If there is more than one site, and at least one site is far from the origin: // 1. If all of the sites have an origin close to one another, then we will move the // site close to the origin based on the first site encountered, give a warning, // and set the shared coordinates in the file and the rest of the sites relative to // the first site. // 2. If the sites do not have origins close to one another, then we will do nothing // and give an error that the site is far from the origin and may have poor // performance and appearance. int numSites = sites.Count; bool hasSiteLocation = false; // First pass: deal with latitude and longitude. for (int ii = 0; ii < numSites; ii++) { IFCSite currSite = sites[ii]; // Set the project latitude and longitude if the information is available, and // it hasn't already been set. SiteLocation siteLocation = projectLocation.GetSiteLocation(); if (siteLocation != null) { // Some Tekla files may have invalid information here that would otherwise cause the // link to fail. Recover with a warning. try { bool foundSiteLocation = (currSite.RefLatitude.HasValue && currSite.RefLongitude.HasValue); if (foundSiteLocation) { if (hasSiteLocation) { Importer.TheLog.LogWarning(currSite.Id, "Duplicate latitude or longitude value supplied for IFCSITE, ignoring.", false); } else { hasSiteLocation = true; siteLocation.Latitude = currSite.RefLatitude.Value * Math.PI / 180.0; siteLocation.Longitude = currSite.RefLongitude.Value * Math.PI / 180.0; } } } catch (Exception ex) { Importer.TheLog.LogWarning(currSite.Id, "Invalid latitude or longitude value supplied for IFCSITE: " + ex.Message, false); } } } int?distantOriginFirstSiteId = null; for (int ii = 0; ii < numSites; ii++) { IFCSite currSite = sites[ii]; // This is effectively no offset. This is good, as long as we don't have // a distance origin. In that case, we will warn and not do any special offsets. if (currSite.ObjectLocation?.RelativeTransform == null) { if (distantOriginFirstSiteId.HasValue) { BaseSiteOffset = null; break; } continue; } XYZ projectLoc = currSite.ObjectLocation.RelativeTransform.Origin; XYZ offset = new XYZ(projectLoc.X, projectLoc.Y, projectLoc.Z); if (XYZ.IsWithinLengthLimits(offset)) { if (distantOriginFirstSiteId.HasValue) { BaseSiteOffset = null; break; } continue; } if (BaseSiteOffset == null) { distantOriginFirstSiteId = currSite.Id; // If the index is greater than 0, then we have found some sites close to the // origin. That means we have incompatible origins which is an issue. if (ii == 0) { BaseSiteOffset = offset; } else { break; } } } if (BaseSiteOffset != null) { // Modify the RelativeTransforms for each of these sites. // Note that the RelativeTransform must be defined to have gotten here. for (int ii = 0; ii < numSites; ii++) { XYZ currentOffset = new XYZ(-BaseSiteOffset.X, -BaseSiteOffset.Y, -BaseSiteOffset.Z /*+ sites[ii].RefElevation*/); Transform newSiteTransform = sites[ii].ObjectLocation.TotalTransform; newSiteTransform.Origin += currentOffset; sites[ii].ObjectLocation = IFCLocation.CreateDummyLocation(newSiteTransform); } // Register the offset by moving the Shared Coordinates away ProjectPosition pPos = projectLocation.GetProjectPosition(XYZ.Zero); pPos.EastWest += BaseSiteOffset.X; pPos.NorthSouth += BaseSiteOffset.Y; pPos.Elevation += BaseSiteOffset.Z; projectLocation.SetProjectPosition(XYZ.Zero, pPos); } else { // In this case, we just have to make sure that the RefElevation is included in // the site transform. for (int ii = 0; ii < numSites; ii++) { if (MathUtil.IsAlmostZero(sites[ii].RefElevation)) { continue; } if (sites[ii].ObjectLocation == null || sites[ii].ObjectLocation.RelativeTransform == null) { XYZ currentOffset = XYZ.Zero; sites[ii].ObjectLocation = IFCLocation.CreateDummyLocation(Transform.CreateTranslation(currentOffset)); } else { double currRefElevation = sites[ii].RefElevation; double currZOffset = sites[ii].ObjectLocation.RelativeTransform.Origin.Z; if (!MathUtil.IsAlmostEqual(currZOffset, currRefElevation)) { Transform newSiteTransform = sites[ii].ObjectLocation.TotalTransform; sites[ii].ObjectLocation = IFCLocation.CreateDummyLocation(newSiteTransform); } } } } if (BaseSiteOffset == null && distantOriginFirstSiteId.HasValue) { Importer.TheLog.LogError(distantOriginFirstSiteId.Value, "There are multiple sites in the file that are located far away from each other. This may result in poor visualization of the data.", false); } }