AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
SKILL verified MIT Self-run

Crosstech Errors Coordinate Mismatch

skill-impertio-studio-cross-tech-aec-claude-skill-package-crosstech-errors-coordinate-mismatch · by Impertio-Studio

>

No reviews yet
0 installs
18 views
0.0% view→install

Install

$ agentstack add skill-impertio-studio-cross-tech-aec-claude-skill-package-crosstech-errors-coordinate-mismatch

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/skill-impertio-studio-cross-tech-aec-claude-skill-package-crosstech-errors-coordinate-mismatch)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
4mo ago

Declared compatibility

Claude CodeClaude Desktop

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Crosstech Errors Coordinate Mismatch? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

crosstech-errors-coordinate-mismatch

Quick Reference

| Symptom | Likely Cause | Jump To | |---------|-------------|---------| | Model rotated 90° / lying on side | Y-up vs Z-up axis swap | [Failure Mode 1](#failure-mode-1-y-up-vs-z-up-axis-swap) | | Model 1000x too large or too small | Unit mismatch (mm/m/ft) | [Failure Mode 2](#failure-mode-2-unit-mismatch-mmmft) | | Model at (0°N, 0°E) in Gulf of Guinea | Missing georeferencing | [Failure Mode 3](#failure-mode-3-missing-georeferencing) | | Model offset by hundreds of km | Wrong CRS / EPSG code | [Failure Mode 4](#failure-mode-4-wrong-crs--epsg-code) | | Building rotated on map, footprint correct | True North rotation error | [Failure Mode 5](#failure-mode-5-true-north-rotation-error) | | Coordinates jump at project boundary | UTM zone boundary | [Failure Mode 6](#failure-mode-6-utm-zone-boundary) | | Building floating ~43m above terrain | Vertical datum confusion | [Failure Mode 7](#failure-mode-7-vertical-datum-confusion) |


Axis Convention Table

| Tool | Up Axis | Handedness | Default Units | Coordinate Order | |------|---------|-----------|---------------|-----------------| | Blender | Z-up | Right-handed | Meters | (X, Y, Z) | | Three.js | Y-up | Right-handed | Unitless | (X, Y, Z) | | QGIS | Z-up (2.5D) | Right-handed | Map units (m/deg) | (X=East, Y=North) | | IFC | Z-up | Right-handed | Project units (mm/m) | (X, Y, Z) | | Revit | Z-up | Right-handed | Internal: feet | (X, Y, Z) | | FreeCAD | Z-up | Right-handed | Internal: mm | (X, Y, Z) | | Speckle | Z-up | Right-handed | Meters | (X, Y, Z) | | web-ifc | Z-up | Right-handed | IFC project units | (X, Y, Z) |

Key boundary: ALL BIM/GIS tools use Z-up. ONLY web 3D renderers (Three.js, Babylon.js) use Y-up.


Diagnostic Decision Tree

START: Model appears wrong in target application
│
├─ Is the model rotated 90°?
│  YES → Failure Mode 1 (Y/Z axis swap)
│
├─ Is the model at the correct location but wrong size?
│  ├─ ~1000x too large → IFC in mm, target expects m (Scale missing)
│  ├─ ~3.28x too large → IFC in feet, target expects m
│  ├─ ~0.3x too small  → IFC in m, target expects feet
│  └─ YES → Failure Mode 2 (unit mismatch)
│
├─ Is the model near (0, 0) / Gulf of Guinea?
│  YES → Failure Mode 3 (missing georeferencing)
│
├─ Is the model offset by >1 km from expected position?
│  ├─ Offset ~100–500 km → Failure Mode 4 (wrong CRS)
│  ├─ Offset ~500,000 m in easting → Failure Mode 6 (UTM zone)
│  └─ Offset  1.0) {
    console.error("Y/Z axis swap detected: model is lying flat");
}

Fix

// JavaScript: BIM Z-up → Three.js Y-up
function bimToThreeJs(x, y, z) {
    return { x: x, y: z, z: -y };
}

The negation of y-z preserves right-handedness. Without negation, the model appears mirrored.

ALWAYS apply this transform when loading IFC/BIM data into Three.js or Babylon.js.

NEVER apply this transform when loading into Blender, QGIS, or other Z-up tools.

Tool-Specific Notes

  • web-ifc / ThatOpen Components: Handles Y/Z swap automatically when using FragmentsManager. Manual loading via IfcLoader requires explicit swap.
  • Three.js GLTFLoader: glTF is Y-up by spec — no swap needed for glTF files. Only swap for raw IFC coordinate data.
  • Speckle: Converts axes automatically per target application on receive.

Failure Mode 2: Unit Mismatch (mm/m/ft)

Symptom

Model appears at the correct location but is absurdly large or small. A 10m building spans 10km on the map (mm→m) or appears as a 3m speck (feet→m without conversion).

Detection

import ifcopenshell

ifc = ifcopenshell.open("model.ifc")

# Step 1: Read project length units
units = ifc.by_type("IfcUnitAssignment")[0]
for unit in units.Units:
    if hasattr(unit, "UnitType") and unit.UnitType == "LENGTHUNIT":
        if hasattr(unit, "Prefix") and unit.Prefix == "MILLI":
            project_unit = "mm"
            expected_scale = 0.001
        elif hasattr(unit, "Name") and unit.Name == "FOOT":
            project_unit = "ft"
            expected_scale = 0.3048
        else:
            project_unit = "m"
            expected_scale = 1.0

# Step 2: Read IfcMapConversion Scale
map_conv = ifc.by_type("IfcMapConversion")
if map_conv:
    actual_scale = map_conv[0].Scale or 1.0  # None defaults to 1.0
    if abs(actual_scale - expected_scale) > 0.0001:
        print(f"SCALE MISMATCH: project={project_unit}, "
              f"MapConversion.Scale={actual_scale}, expected={expected_scale}")

Common Scale Factors

| From | To | Scale Factor | |------|----|-------------| | mm | m | 0.001 | | m | m | 1.0 | | ft | m | 0.3048 | | in | m | 0.0254 |

Fix

Set IfcMapConversion.Scale to the correct conversion factor from project units to CRS map units.

ALWAYS check IfcUnitAssignment before interpreting IfcMapConversion.Scale.

NEVER assume project units are meters — Revit uses feet internally, FreeCAD uses mm.


Failure Mode 3: Missing Georeferencing

Symptom

Model appears at latitude 0°, longitude 0° (Gulf of Guinea, West Africa) or at the CRS origin point. This is the single most common BIM↔GIS integration failure.

Detection

import ifcopenshell

ifc = ifcopenshell.open("model.ifc")
has_map_conv = len(ifc.by_type("IfcMapConversion")) > 0
has_crs = len(ifc.by_type("IfcProjectedCRS")) > 0

if not has_map_conv:
    print("MISSING: IfcMapConversion — no coordinate transformation defined")
if not has_crs:
    print("MISSING: IfcProjectedCRS — no target CRS defined")

Fix

Add georeferencing using IfcOpenShell:

import ifcopenshell
import ifcopenshell.api

ifc = ifcopenshell.open("model.ifc")

# Add georeferencing entities
ifcopenshell.api.run("georeference.add_georeferencing", ifc)

# Set CRS and map conversion parameters
ifcopenshell.api.run("georeference.edit_georeferencing", ifc,
    projected_crs={"Name": "EPSG:28992"},
    coordinate_operation={
        "Eastings": 155000.0,
        "Northings": 463000.0,
        "OrthogonalHeight": 0.0,
    })

ifc.write("model_georef.ifc")

ALWAYS verify Eastings/Northings fall within the valid range of the target CRS.

NEVER leave IfcProjectedCRS.Name empty — downstream tools rely on this field to resolve the CRS.


Failure Mode 4: Wrong CRS / EPSG Code

Symptom

Model appears offset by tens to hundreds of kilometers from the expected position.

Detection

Validate that coordinate values are plausible for the assigned CRS:

| CRS | Valid Easting Range | Valid Northing Range | |-----|-------------------|---------------------| | EPSG:28992 (RD New) | -7,000 to 300,000 | 289,000 to 629,000 | | EPSG:32631 (UTM 31N) | 166,000 to 834,000 | 0 to 9,400,000 | | EPSG:32632 (UTM 32N) | 166,000 to 834,000 | 0 to 9,400,000 |

import ifcopenshell

ifc = ifcopenshell.open("model.ifc")
map_conv = ifc.by_type("IfcMapConversion")
crs = ifc.by_type("IfcProjectedCRS")

if map_conv and crs:
    e = map_conv[0].Eastings
    n = map_conv[0].Northings
    crs_name = crs[0].Name

    # Example: validate RD New range
    if "28992" in (crs_name or ""):
        if not (-7000  0.001:
        print(f"WARNING: direction vector not normalized (length={vec_length:.4f})")

Fix

Set XAxisAbscissa = cos(angle) and XAxisOrdinate = sin(angle) where angle is the anti-clockwise rotation from grid north (CRS Y-axis) to project north.

ALWAYS verify the direction vector is normalized (length = 1.0).

NEVER confuse the sign convention — positive angle = anti-clockwise rotation in IFC.


Failure Mode 6: UTM Zone Boundary

Symptom

Project straddles a UTM zone boundary. Coordinates jump by ~500,000m in easting, or measurements near the boundary show 0.04% distortion.

Detection

from pyproj import CRS

def utm_zone_from_longitude(lon):
    """Return UTM zone number for a given longitude."""
    return int((lon + 180) / 6) + 1

# Example: Netherlands straddles UTM zones 31 and 32
# Zone 31N: 0°E to 6°E (central meridian 3°E)
# Zone 32N: 6°E to 12°E (central meridian 9°E)
western_nl_zone = utm_zone_from_longitude(4.5)   # Zone 31
eastern_nl_zone = utm_zone_from_longitude(6.5)   # Zone 32

Fix

NEVER mix coordinates from different UTM zones in one project.

Use a single CRS that covers the entire project area:

  • Netherlands: EPSG:28992 (RD New) covers the entire country
  • Europe-wide: EPSG:3035 (ETRS89 / LAEA) for pan-European projects
  • If UTM is required, pick the zone containing the project centroid

Failure Mode 7: Vertical Datum Confusion

Symptom

Model floats ~42–44 meters above the terrain (Netherlands) or is buried below ground. Horizontal position is correct.

Cause

Mixing NAP (Normaal Amsterdams Peil) orthometric heights with WGS84 ellipsoidal heights. In the Netherlands, the geoid undulation (difference between ellipsoid and geoid) is approximately 42–44 meters.

Detection

import ifcopenshell

ifc = ifcopenshell.open("model.ifc")
crs = ifc.by_type("IfcProjectedCRS")
map_conv = ifc.by_type("IfcMapConversion")

if crs:
    vert_datum = crs[0].VerticalDatum
    if vert_datum is None:
        print("WARNING: No vertical datum specified — height interpretation ambiguous")

if map_conv:
    h = map_conv[0].OrthogonalHeight
    if abs(h) > 40 and abs(h) < 50:
        print(f"SUSPICIOUS: OrthogonalHeight={h}m — possible NAP↔ellipsoid confusion")

Fix

from pyproj import Transformer

# Transform NAP height to WGS84 ellipsoidal height (or vice versa)
# Requires PROJ grid files (nl_nsgi_nlgeo2018.tif)
t = Transformer.from_crs(
    "EPSG:7415",   # RD New + NAP (compound)
    "EPSG:4979",   # WGS84 3D (geographic + ellipsoidal height)
    always_xy=True
)
lon, lat, h_ellipsoid = t.transform(easting, northing, h_nap)
geoid_undulation = h_ellipsoid - h_nap  # ~42-44m in NL

ALWAYS specify IfcProjectedCRS.VerticalDatum (e.g., "NAP") to make height interpretation unambiguous.

NEVER assume heights are ellipsoidal — most BIM models use orthometric (above sea level) heights.


Critical Rules

  1. ALWAYS check axis conventions before crossing a tool boundary — Z-up to Y-up swaps are the most common error.
  2. ALWAYS verify IfcMapConversion.Scale matches the ratio of project units to CRS units.
  3. ALWAYS use always_xy=True when creating pyproj Transformers.
  4. ALWAYS validate coordinate ranges against the assigned CRS before declaring georeferencing correct.
  5. NEVER assume georeferencing exists — explicitly check for IfcMapConversion and IfcProjectedCRS.
  6. NEVER mix coordinates from different UTM zones in a single project.
  7. NEVER assume heights are ellipsoidal — BIM models use orthometric heights by default.
  8. NEVER skip the direction vector normalization check for True North rotation.
  9. ALWAYS check for compound errors — multiple failure modes can occur simultaneously.
  10. ALWAYS verify fixes with a known reference point before declaring the issue resolved.

Reference Links

  • [references/methods.md](references/methods.md) — Diagnostic API signatures for coordinate issues per tool
  • [references/examples.md](references/examples.md) — Real coordinate error scenarios with step-by-step fixes
  • [references/anti-patterns.md](references/anti-patterns.md) — Coordinate handling mistakes to avoid

Official Sources

  • https://standards.buildingsmart.org/IFC/RELEASE/IFC4/ADD2_TC1/HTML/schema/ifcrepresentationresource/lexical/ifcmapconversion.htm
  • https://standards.buildingsmart.org/IFC/RELEASE/IFC4/ADD2_TC1/HTML/schema/ifcrepresentationresource/lexical/ifcprojectedcrs.htm
  • https://pyproj4.github.io/pyproj/stable/api/transformer.html
  • https://ifcopenshell.github.io/docs/python/html/ifcopenshell-python/geometry_processing.html
  • https://epsg.io/

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.