public void QuaternionVersusMatrixMovingTests() { XbimVector3D t = new XbimVector3D(2, 0, 0); XbimMatrix3D T = new XbimMatrix3D(t); T.RotateAroundZAxis(Math.PI / 2); XbimQuaternion q; XbimQuaternion.RotationMatrix(ref T, out q); // Do the quaternion approach XbimVector3D v = new XbimVector3D(1, 1, 0); XbimVector3D v1; XbimQuaternion.Transform(ref v, ref q, out v1); // Rotate and translate var p1Result = v1 + t; // Do the same with matrix approach XbimPoint3D p = new XbimPoint3D(1, 1, 0); var p2Result = T.Transform(p); Assert.AreEqual(p1Result, XbimPoint3D.Subtract(p2Result, XbimPoint3D.Zero)); // Test quaternion and delta translation (relocating) XbimVector3D mt = new XbimVector3D(2, 2, 0); var dt = t - mt; var pMoved = v1 + dt; var p3Result = pMoved + mt; Assert.AreEqual(p1Result, p3Result); }
public void QuaternionAndMatrixOrientationTests() { var t = new XbimMatrix3D(new XbimVector3D(1, 1, 0)); t.RotateAroundZAxis(Math.PI / 2); // Left chaining matrix operation => transposed in Xbim Assert.AreEqual(new XbimVector3D(0, 1, 0), t.Right); Assert.AreEqual(new XbimVector3D(-1, 0, 0), t.Up); Assert.AreEqual(new XbimVector3D(0, 0, 1), t.Backward); var q = t.GetRotationQuaternion(); Assert.AreEqual(Math.Sqrt(2) / 2, q.W, 1e-5); Assert.AreEqual(Math.Sqrt(2) / 2, q.Z, 1e-5); Assert.AreEqual(0, q.X, 1e-8); Assert.AreEqual(0, q.Y, 1e-8); }
/// <summary> /// Get point on arc by given start point, start direction, arc radius, /// is counter-clockwise and distance along. /// </summary> /// <param name="start"></param> /// <param name="dir"></param> /// <param name="radius"></param> /// <param name="isCCW"></param> /// <param name="dist"></param> /// <returns></returns> public static (XbimPoint3D pt, XbimVector3D vec) GetPointOnCurve(XbimPoint3D start, XbimVector3D dir, double radius, bool isCCW, double dist) { // Compute the location of arc center. var zAxis = new XbimVector3D(0, 0, 1); var start2center = isCCW ? zAxis.CrossProduct(dir) : dir.CrossProduct(zAxis); var center = start + radius * start2center; // Compute the location of arc end point var theta = isCCW ? dist / radius : -dist / radius; var center2start = start2center.Negated(); var mat = new XbimMatrix3D(); mat.RotateAroundZAxis(theta); var center2end = mat.Transform(center2start); var lateral = isCCW ? center2end.Negated() : center2end; return(center + radius * center2end, lateral); }
public void TransformSolidRectangularProfileDef() { using (var m = new MemoryModel(new Xbim.Ifc4.EntityFactoryIfc4())) { using (var txn = m.BeginTransaction("Test")) { var profile = IfcModelBuilder.MakeRectangleHollowProfileDef(m, 20, 10, 1); var extrude = IfcModelBuilder.MakeExtrudedAreaSolid(m, profile, 40); var solid = _geomEngine.CreateSolid(extrude); var transform = new XbimMatrix3D(); //test first with identity var solid2 = (IXbimSolid)solid.Transform(transform); var s1Verts = solid.Vertices.ToList(); var s2Verts = solid2.Vertices.ToList(); for (int i = 0; i < s1Verts.Count; i++) { XbimVector3D v = s1Verts[i].VertexGeometry - s2Verts[i].VertexGeometry; Assert.IsTrue(v.Length < m.ModelFactors.Precision, "vertices not the same"); } transform.RotateAroundXAxis(Math.PI / 2); transform.RotateAroundYAxis(Math.PI / 4); transform.RotateAroundZAxis(Math.PI); transform.OffsetX += 100; transform.OffsetY += 200; transform.OffsetZ += 300; solid2 = (IXbimSolid)solid.Transform(transform); Assert.IsTrue(Math.Abs(solid.Volume - solid2.Volume) < 0.001, "Volume differs"); transform.Invert(); solid2 = (IXbimSolid)solid2.Transform(transform); s1Verts = solid.Vertices.ToList(); s2Verts = solid2.Vertices.ToList(); for (int i = 0; i < s1Verts.Count; i++) { XbimVector3D v = s1Verts[i].VertexGeometry - s2Verts[i].VertexGeometry; Assert.IsTrue(v.Length < m.ModelFactors.Precision, "vertices not the same"); } txn.Commit(); } } }
/// <summary> /// Calculate the ObjectPlacment for an IfcProduct from row data and the parent object /// </summary> /// <param name="row">COBieCoordinateRow holding the data</param> /// <param name="placementRelToIfcProduct">IfcProduct that the ObjectPlacment relates too, i.e. the parent of the ifcProduct ObjectPlacment we are calculating</param> /// <returns></returns> private IfcLocalPlacement CalcObjectPlacement(COBieCoordinateRow row, IfcProduct placementRelToIfcProduct) { XbimPoint3D locationPt; bool havePoint = GetPointFromRow(row, out locationPt); if (havePoint) { if ((placementRelToIfcProduct != null) && (placementRelToIfcProduct.ObjectPlacement is IfcLocalPlacement)) { //TEST, change the building position to see if the same point comes out in Excel sheet, it should be, and in test was. //((IfcAxis2Placement3D)((IfcLocalPlacement)placementRelToIfcProduct.ObjectPlacement).RelativePlacement).SetNewLocation(10.0, 10.0, 0.0); IfcLocalPlacement placementRelTo = (IfcLocalPlacement)placementRelToIfcProduct.ObjectPlacement; XbimMatrix3D matrix3D = ConvertMatrix3D(placementRelTo); //we want to take off the translations and rotations caused by IfcLocalPlacement of the parent objects as we will add these to the new IfcLocalPlacement for this floor matrix3D.Invert(); //so invert matrix to remove the translations to give the origin for the next IfcLocalPlacement locationPt = matrix3D.Transform(locationPt); //get the point with relation to the last IfcLocalPlacement i.e the parent element //Get the WCS matrix values double rotX, rotY, rotZ; if (!(double.TryParse(row.YawRotation, out rotX) && (double.NaN.CompareTo(rotX) != 0))) { rotX = 0.0; } if (!(double.TryParse(row.ElevationalRotation, out rotY) && (double.NaN.CompareTo(rotY) != 0))) { rotY = 0.0; } if (double.TryParse(row.ClockwiseRotation, out rotZ) && (double.NaN.CompareTo(rotZ) != 0)) { rotZ = rotZ * -1; //convert back from clockwise to anti clockwise } else { rotZ = 0.0; } //apply the WCS rotation from COBie Coordinates stored values XbimMatrix3D matrixNewRot3D = new XbimMatrix3D(); if (rotX != 0.0) { matrixNewRot3D.RotateAroundXAxis(TransformedBoundingBox.DegreesToRadians(rotX)); } if (rotY != 0.0) { matrixNewRot3D.RotateAroundYAxis(TransformedBoundingBox.DegreesToRadians(rotY)); } if (rotZ != 0.0) { matrixNewRot3D.RotateAroundZAxis(TransformedBoundingBox.DegreesToRadians(rotZ)); } //remove any displacement from the matrix which moved/rotated us to the object space matrix3D.OffsetX = 0.0F; matrix3D.OffsetY = 0.0F; matrix3D.OffsetZ = 0.0F; //remove the matrix that got use to the object space from the WCS location of this object XbimMatrix3D matrixRot3D = matrixNewRot3D * matrix3D; //get the rotation vectors to place in the new IfcAxis2Placement3D for the new IfcLocalPlacement for this object XbimVector3D ucsAxisX = matrixRot3D.Transform(new XbimVector3D(1, 0, 0)); XbimVector3D ucsAxisZ = matrixRot3D.Transform(new XbimVector3D(0, 0, 1)); ucsAxisX = ucsAxisX.Normalized(); ucsAxisZ = ucsAxisZ.Normalized(); //create the new IfcAxis2Placement3D IfcAxis2Placement3D relativePlacemant = Model.Instances.New <IfcAxis2Placement3D>(); relativePlacemant.SetNewDirectionOf_XZ(ucsAxisX.X, ucsAxisX.Y, ucsAxisX.Z, ucsAxisZ.X, ucsAxisZ.Y, ucsAxisZ.Z); relativePlacemant.SetNewLocation(locationPt.X, locationPt.Y, locationPt.Z); //Set up IfcLocalPlacement IfcLocalPlacement objectPlacement = Model.Instances.New <IfcLocalPlacement>(); objectPlacement.PlacementRelTo = placementRelTo; objectPlacement.RelativePlacement = relativePlacemant; return(objectPlacement); } } return(null); }