static XbimMatrix3D() { _identity = new XbimMatrix3D(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) { _isNotDefaultInitialised = true }; }
/// <summary> /// Warning: This function assumes no rotation is used for the tranform. /// </summary> /// <param name="composed">The NON-ROTATING transform to apply</param> /// <returns>the transformed bounding box.</returns> public XbimRect3D Transform(XbimMatrix3D composed) { var min = this.Min * composed; var max = this.Max * composed; return(new XbimRect3D(min, max)); }
/// <summary> /// Creates a new instance of a mat4 /// </summary> /// <param name="m">Single[16] containing values to initialize with</param> /// <returns>New mat4New mat4</returns> public static XbimMatrix3D Copy(XbimMatrix3D m) { return(new XbimMatrix3D(m.M11, m.M12, m.M13, m.M14, m.M21, m.M22, m.M23, m.M24, m.M31, m.M32, m.M33, m.M34, m.OffsetX, m.OffsetY, m.OffsetZ, m.M44)); }
public XbimModelFactors(double angToRads, double lenToMeter, double? precision = null, XbimMatrix3D? wcs= null) { WorldCoordinateSystem = wcs; AngleToRadiansConversionFactor = angToRads; LengthToMetresConversionFactor = lenToMeter; OneMeter = OneMetre = 1/lenToMeter; OneMilliMeter = OneMilliMetre = OneMeter / 1000.0; OneKilometer = OneMeter * 1000.0; OneFoot = OneMeter / 3.2808; OneInch = OneMeter / 39.37; OneMile = OneMeter * 1609.344; DeflectionTolerance = OneMilliMetre*5; //5mm chord deflection DeflectionAngle = 0.5; VertexPointDiameter = OneMilliMetre * 10; //1 cm //if (precision.HasValue) // Precision = Math.Min(precision.Value,OneMilliMetre / 1000); //else // Precision = Math.Max(1e-5, OneMilliMetre / 1000); if (precision.HasValue) Precision = precision.Value; else Precision = 1e-5; PrecisionMax = OneMilliMetre / 10; MaxBRepSewFaceCount = 0; PrecisionBoolean = Math.Max(Precision,OneMilliMetre/10); //might need to make it courser than point precision if precision is very fine PrecisionBooleanMax = OneMilliMetre *100; Rounding = Math.Abs((int)Math.Log10(Precision*100)); //default round all points to 100 times precision, this is used in the hash functions var exp = Math.Floor(Math.Log10(Math.Abs(OneMilliMetre / 10d))); //get exponent of first significant digit _significantOrder = exp > 0 ? 0 : (int)Math.Abs(exp); ShortestEdgeLength = 10 * OneMilliMetre; }
public static void AddElements(this MeshGeometry3D m, EntitySelection selection, XbimMatrix3D wcsTransform) { foreach (var item in selection) { m.AddElements(item, wcsTransform); } }
/// <summary> /// Performs a matrix multiplication /// </summary> /// <param name="mat">mat First operand</param> /// <param name="mat2">mat2 Second operand</param> /// <returns>dest if specified, mat otherwise</returns> public static XbimMatrix3D Multiply(XbimMatrix3D mat1, XbimMatrix3D mat2) { if (mat1.IsIdentity) { return(mat2); } else if (mat2.IsIdentity) { return(mat1); } else { return(new XbimMatrix3D((((mat1._m11 * mat2._m11) + (mat1._m12 * mat2._m21)) + (mat1._m13 * mat2._m31)) + (mat1._m14 * mat2._offsetX), (((mat1._m11 * mat2._m12) + (mat1._m12 * mat2._m22)) + (mat1._m13 * mat2._m32)) + (mat1._m14 * mat2._offsetY), (((mat1._m11 * mat2._m13) + (mat1._m12 * mat2._m23)) + (mat1._m13 * mat2._m33)) + (mat1._m14 * mat2._offsetZ), (((mat1._m11 * mat2._m14) + (mat1._m12 * mat2._m24)) + (mat1._m13 * mat2._m34)) + (mat1._m14 * mat2._m44), (((mat1._m21 * mat2._m11) + (mat1._m22 * mat2._m21)) + (mat1._m23 * mat2._m31)) + (mat1._m24 * mat2._offsetX), (((mat1._m21 * mat2._m12) + (mat1._m22 * mat2._m22)) + (mat1._m23 * mat2._m32)) + (mat1._m24 * mat2._offsetY), (((mat1._m21 * mat2._m13) + (mat1._m22 * mat2._m23)) + (mat1._m23 * mat2._m33)) + (mat1._m24 * mat2._offsetZ), (((mat1._m21 * mat2._m14) + (mat1._m22 * mat2._m24)) + (mat1._m23 * mat2._m34)) + (mat1._m24 * mat2._m44), (((mat1._m31 * mat2._m11) + (mat1._m32 * mat2._m21)) + (mat1._m33 * mat2._m31)) + (mat1._m34 * mat2._offsetX), (((mat1._m31 * mat2._m12) + (mat1._m32 * mat2._m22)) + (mat1._m33 * mat2._m32)) + (mat1._m34 * mat2._offsetY), (((mat1._m31 * mat2._m13) + (mat1._m32 * mat2._m23)) + (mat1._m33 * mat2._m33)) + (mat1._m34 * mat2._offsetZ), (((mat1._m31 * mat2._m14) + (mat1._m32 * mat2._m24)) + (mat1._m33 * mat2._m34)) + (mat1._m34 * mat2._m44), (((mat1._offsetX * mat2._m11) + (mat1._offsetY * mat2._m21)) + (mat1._offsetZ * mat2._m31)) + (mat1._m44 * mat2._offsetX), (((mat1._offsetX * mat2._m12) + (mat1._offsetY * mat2._m22)) + (mat1._offsetZ * mat2._m32)) + (mat1._m44 * mat2._offsetY), (((mat1._offsetX * mat2._m13) + (mat1._offsetY * mat2._m23)) + (mat1._offsetZ * mat2._m33)) + (mat1._m44 * mat2._offsetZ), (((mat1._offsetX * mat2._m14) + (mat1._offsetY * mat2._m24)) + (mat1._offsetZ * mat2._m34)) + (mat1._m44 * mat2._m44))); } }
/// <summary> /// Performs a matrix multiplication /// </summary> /// <param name="mat1">mat First operand</param> /// <param name="mat2">mat2 Second operand</param> /// <returns>dest if specified, mat otherwise</returns> public static XbimMatrix3D Multiply(XbimMatrix3D mat1, XbimMatrix3D mat2) { if (mat1.IsIdentity) { return(mat2); } else if (mat2.IsIdentity) { return(mat1); } else { return(new XbimMatrix3D(mat1._m11 * mat2._m11 + mat1._m12 * mat2._m21 + mat1._m13 * mat2._m31 + mat1._m14 * mat2._offsetX, mat1._m11 * mat2._m12 + mat1._m12 * mat2._m22 + mat1._m13 * mat2._m32 + mat1._m14 * mat2._offsetY, mat1._m11 * mat2._m13 + mat1._m12 * mat2._m23 + mat1._m13 * mat2._m33 + mat1._m14 * mat2._offsetZ, mat1._m11 * mat2._m14 + mat1._m12 * mat2._m24 + mat1._m13 * mat2._m34 + mat1._m14 * mat2._m44, mat1._m21 * mat2._m11 + mat1._m22 * mat2._m21 + mat1._m23 * mat2._m31 + mat1._m24 * mat2._offsetX, mat1._m21 * mat2._m12 + mat1._m22 * mat2._m22 + mat1._m23 * mat2._m32 + mat1._m24 * mat2._offsetY, mat1._m21 * mat2._m13 + mat1._m22 * mat2._m23 + mat1._m23 * mat2._m33 + mat1._m24 * mat2._offsetZ, mat1._m21 * mat2._m14 + mat1._m22 * mat2._m24 + mat1._m23 * mat2._m34 + mat1._m24 * mat2._m44, mat1._m31 * mat2._m11 + mat1._m32 * mat2._m21 + mat1._m33 * mat2._m31 + mat1._m34 * mat2._offsetX, mat1._m31 * mat2._m12 + mat1._m32 * mat2._m22 + mat1._m33 * mat2._m32 + mat1._m34 * mat2._offsetY, mat1._m31 * mat2._m13 + mat1._m32 * mat2._m23 + mat1._m33 * mat2._m33 + mat1._m34 * mat2._offsetZ, mat1._m31 * mat2._m14 + mat1._m32 * mat2._m24 + mat1._m33 * mat2._m34 + mat1._m34 * mat2._m44, mat1._offsetX * mat2._m11 + mat1._offsetY * mat2._m21 + mat1._offsetZ * mat2._m31 + mat1._m44 * mat2._offsetX, mat1._offsetX * mat2._m12 + mat1._offsetY * mat2._m22 + mat1._offsetZ * mat2._m32 + mat1._m44 * mat2._offsetY, mat1._offsetX * mat2._m13 + mat1._offsetY * mat2._m23 + mat1._offsetZ * mat2._m33 + mat1._m44 * mat2._offsetZ, mat1._offsetX * mat2._m14 + mat1._offsetY * mat2._m24 + mat1._offsetZ * mat2._m34 + mat1._m44 * mat2._m44)); } }
public MapRefData(MapData toAdd) { RepresentationLabel = toAdd.Geometry.RepresentationLabel; EntityLabel = toAdd.Product.EntityLabel; EntityTypeId = IfcMetaData.IfcTypeId(toAdd.Product); SurfaceStyleLabel = toAdd.Geometry.SurfaceStyleLabel; Matrix = XbimMatrix3D.Multiply(toAdd.Geometry.Transform, toAdd.Matrix); }
public XbimRegion(string name, XbimRect3D bounds, int population, XbimMatrix3D worldCoordinateSystem) { Name = name; Size = new XbimVector3D(bounds.SizeX, bounds.SizeY, bounds.SizeZ); Centre = bounds.Centroid(); Population = population; WorldCoordinateSystem = worldCoordinateSystem; }
public XbimShapeTriangulation Transform(XbimMatrix3D matrix3D) { var vertices =_vertices.Select(matrix3D.Transform).ToList(); var faces = new List<XbimFaceTriangulation>(_faces.Count); var q = matrix3D.GetRotationQuaternion(); faces.AddRange(_faces.Select(face => face.Transform(q))); return new XbimShapeTriangulation(vertices, faces, _version); }
public XbimShapeTriangulation Transform(XbimMatrix3D matrix3D) { var vertices = _vertices.Select(matrix3D.Transform).ToList(); var faces = new List <XbimFaceTriangulation>(_faces.Count); var q = matrix3D.GetRotationQuaternion(); faces.AddRange(_faces.Select(face => face.Transform(q))); return(new XbimShapeTriangulation(vertices, faces, _version)); }
public static XbimMeshGeometry3D GetMesh(this XbimModel xbimModel, IEnumerable<IPersistIfcEntity> items, XbimMatrix3D wcsTransform) { var m = new XbimMeshGeometry3D(); if (xbimModel.GeometrySupportLevel == 1) { // this is what happens for version 1 of the engine // foreach (var item in items) { var fromModel = item.ModelOf as XbimModel; if (fromModel == null) continue; var geomDataSet = fromModel.GetGeometryData(item.EntityLabel, XbimGeometryType.TriangulatedMesh); foreach (var geomData in geomDataSet) { // todo: add guidance to the TransformBy method so that users can understand how to stop using it (it's marked absolete) geomData.TransformBy(wcsTransform); m.Add(geomData); // todo: what is the modelid value to be passed? } } } else { // this is what happens for version 2 of the engine // foreach (var item in items) { var fromModel = item.ModelOf as XbimModel; if (fromModel == null || !(item is IfcProduct)) continue; var context = new Xbim3DModelContext(fromModel); var productShape = context.ShapeInstancesOf((IfcProduct) item) .Where( s => s.RepresentationType != XbimGeometryRepresentationType.OpeningsAndAdditionsExcluded) .ToList(); foreach (var shapeInstance in productShape) { IXbimShapeGeometryData shapeGeom = context.ShapeGeometry(shapeInstance.ShapeGeometryLabel); switch ((XbimGeometryType) shapeGeom.Format) { case XbimGeometryType.PolyhedronBinary: m.Read(shapeGeom.ShapeData, XbimMatrix3D.Multiply(shapeInstance.Transformation, wcsTransform)); break; case XbimGeometryType.Polyhedron: m.Read(((XbimShapeGeometry) shapeGeom).ShapeData, XbimMatrix3D.Multiply(shapeInstance.Transformation, wcsTransform)); break; } } } } return m; }
public static XbimVector3D Multiply(XbimVector3D vec, XbimMatrix3D m) { var x = vec.X; var y = vec.Y; var z = vec.Z; return(new XbimVector3D(m.M11 * x + m.M21 * y + m.M31 * z, m.M12 * x + m.M22 * y + m.M32 * z, m.M13 * x + m.M23 * y + m.M33 * z )); }
public override bool Equals(object obj) { if (obj is XbimMatrix3D) { return(XbimMatrix3D.Equal(this, (XbimMatrix3D)obj)); } else { return(false); } }
public XbimShapeInstance(int id = -1) { _instanceLabel = id; _expressTypeId = 0; _ifcProductLabel = 0; _styleLabel = 0; _shapeLabel = -1; _representationContext = 0; _representationType = XbimGeometryRepresentationType.OpeningsAndAdditionsExcluded; _transformation = XbimMatrix3D.Identity; _boundingBox = XbimRect3D.Empty; }
public static void AddElements(this MeshGeometry3D m, IPersistIfcEntity item, XbimMatrix3D wcsTransform) { var fromModel = item.ModelOf as XbimModel; if (fromModel == null || !(item is IfcProduct)) return; switch (fromModel.GeometrySupportLevel) { case 2: var context = new Xbim3DModelContext(fromModel); var productShape = context.ShapeInstancesOf((IfcProduct) item) .Where(s => s.RepresentationType != XbimGeometryRepresentationType.OpeningsAndAdditionsExcluded) .ToList(); if (!productShape.Any() && item is IfcFeatureElement) { productShape = context.ShapeInstancesOf((IfcProduct) item) .Where( s => s.RepresentationType == XbimGeometryRepresentationType.OpeningsAndAdditionsExcluded) .ToList(); } if (!productShape.Any()) return; foreach (var shapeInstance in productShape) { IXbimShapeGeometryData shapeGeom = context.ShapeGeometry(shapeInstance.ShapeGeometryLabel); switch ((XbimGeometryType) shapeGeom.Format) { case XbimGeometryType.PolyhedronBinary: m.Read(shapeGeom.ShapeData, XbimMatrix3D.Multiply(shapeInstance.Transformation, wcsTransform)); break; case XbimGeometryType.Polyhedron: m.Read(((XbimShapeGeometry) shapeGeom).ShapeData, XbimMatrix3D.Multiply(shapeInstance.Transformation, wcsTransform)); break; } } break; case 1: var xm3d = new XbimMeshGeometry3D(); var geomDataSet = fromModel.GetGeometryData(item.EntityLabel, XbimGeometryType.TriangulatedMesh); foreach (var geomData in geomDataSet) { var gd = geomData.TransformBy(wcsTransform); xm3d.Add(gd); } m.Add(xm3d); break; } }
public void QuaternionTests() { var q = new XbimQuaternion(); Assert.AreEqual(true, q.IsIdentity(), "Uninitialised quaternion should be identity."); q = new XbimQuaternion(0.0f, 0.0f, 0.0f, 1.0f); Assert.AreEqual(true, q.IsIdentity(), "Should be identity when initialised with floats."); var mat = new XbimMatrix3D(); q = mat.GetRotationQuaternion(); Assert.AreEqual(true, q.IsIdentity(), "Quaternion from identity matrix shold be identity."); }
/// <summary> /// Decomposes a matrix into a scale, rotation, and translation. /// </summary> /// <param name="scale">When the method completes, contains the scaling component of the decomposed matrix.</param> /// <param name="rotation">When the method completes, contains the rtoation component of the decomposed matrix.</param> /// <param name="translation">When the method completes, contains the translation component of the decomposed matrix.</param> /// <remarks> /// This method is designed to decompose an SRT transformation matrix only. /// </remarks> public bool Decompose(out XbimVector3D scale, out XbimQuaternion rotation, out XbimVector3D translation) { //Source: Unknown // References: http://www.gamedev.net/community/forums/topic.asp?topic_id=441695 // via https://code.google.com/p/sharpdx/source/browse/Source/SharpDX/Matrix.cs?r=9f9e209b1be04f06f294bc6d72b06055ad6abdcc //Get the translation. translation = new XbimVector3D(); translation.X = this._offsetX; translation.Y = this._offsetY; translation.Z = this._offsetZ; //Scaling is the length of the rows. scale = new XbimVector3D(); scale.X = Math.Sqrt((M11 * M11) + (M12 * M12) + (M13 * M13)); scale.Y = Math.Sqrt((M21 * M21) + (M22 * M22) + (M23 * M23)); scale.Z = Math.Sqrt((M31 * M31) + (M32 * M32) + (M33 * M33)); //If any of the scaling factors are zero, than the rotation matrix can not exist. // double ZeroTolerance = 0.000003; if (Math.Abs(scale.X) < ZeroTolerance || Math.Abs(scale.Y) < ZeroTolerance || Math.Abs(scale.Z) < ZeroTolerance) { rotation = new XbimQuaternion(); // defaults to identity return(false); } //The rotation is the left over matrix after dividing out the scaling. XbimMatrix3D rotationmatrix = new XbimMatrix3D(); rotationmatrix.M11 = M11 / scale.X; rotationmatrix.M12 = M12 / scale.X; rotationmatrix.M13 = M13 / scale.X; rotationmatrix.M21 = M21 / scale.Y; rotationmatrix.M22 = M22 / scale.Y; rotationmatrix.M23 = M23 / scale.Y; rotationmatrix.M31 = M31 / scale.Z; rotationmatrix.M32 = M32 / scale.Z; rotationmatrix.M33 = M33 / scale.Z; rotationmatrix.M44 = 1; XbimQuaternion.RotationMatrix(ref rotationmatrix, out rotation); return(true); }
public static XbimRegionCollection FromArray(byte[] bytes) { var coll = new XbimRegionCollection(); var ms = new MemoryStream(bytes); var br = new BinaryReader(ms); bool oldVersion = true; int version = br.ReadInt32();//if version is a negative number, we have a new version model, and therefore have coord data to retrieve. Otherwise version is actually the count int count = 0; if (version < 0) { count = br.ReadInt32(); oldVersion = false; } else { count = version; } for (var i = 0; i < count; i++) { var region = new XbimRegion { Name = br.ReadString(), Population = br.ReadInt32() }; float x = br.ReadSingle(); float y = br.ReadSingle(); float z = br.ReadSingle(); region.Centre = new XbimPoint3D(x, y, z); x = br.ReadSingle(); y = br.ReadSingle(); z = br.ReadSingle(); region.Size = new XbimVector3D(x, y, z); if (!oldVersion) { region.WorldCoordinateSystem = XbimMatrix3D.FromArray(br.ReadBytes(CoordSize)); #pragma warning disable CS0618 // Type or member is obsolete region.version = version; } else { region.version = 0; #pragma warning restore CS0618 // Type or member is obsolete } coll.Add(region); } return(coll); }
/// <summary> /// Creates a quaternion given a rotation matrix. /// </summary> /// <param name="matrix">The rotation matrix.</param> /// <param name="result">When the method completes, contains the newly created quaternion.</param> public static void RotationMatrix(ref XbimMatrix3D matrix, out XbimQuaternion result) { double sqrt; double half; double scale = matrix.M11 + matrix.M22 + matrix.M33; result = new XbimQuaternion(); if (scale > 0.0f) { sqrt = Math.Sqrt(scale + 1.0f); result.W = sqrt * 0.5f; sqrt = 0.5f / sqrt; result.X = (matrix.M23 - matrix.M32) * sqrt; result.Y = (matrix.M31 - matrix.M13) * sqrt; result.Z = (matrix.M12 - matrix.M21) * sqrt; } else if ((matrix.M11 >= matrix.M22) && (matrix.M11 >= matrix.M33)) { sqrt = Math.Sqrt(1.0f + matrix.M11 - matrix.M22 - matrix.M33); half = 0.5f / sqrt; result.X = 0.5f * sqrt; result.Y = (matrix.M12 + matrix.M21) * half; result.Z = (matrix.M13 + matrix.M31) * half; result.W = (matrix.M23 - matrix.M32) * half; } else if (matrix.M22 > matrix.M33) { sqrt = Math.Sqrt(1.0f + matrix.M22 - matrix.M11 - matrix.M33); half = 0.5f / sqrt; result.X = (matrix.M21 + matrix.M12) * half; result.Y = 0.5f * sqrt; result.Z = (matrix.M32 + matrix.M23) * half; result.W = (matrix.M31 - matrix.M13) * half; } else { sqrt = Math.Sqrt(1.0f + matrix.M33 - matrix.M11 - matrix.M22); half = 0.5f / sqrt; result.X = (matrix.M31 + matrix.M13) * half; result.Y = (matrix.M32 + matrix.M23) * half; result.Z = 0.5f * sqrt; result.W = (matrix.M12 - matrix.M21) * half; } }
public static XbimMatrix3D ToMatrix3D(this IfcAxis2Placement2D axis2, ConcurrentDictionary<int, Object> maps = null) { object transform; if (maps != null && maps.TryGetValue(axis2.EntityLabel, out transform)) //already converted it just return cached return (XbimMatrix3D)transform; if (axis2.RefDirection != null) { XbimVector3D v = axis2.RefDirection.XbimVector3D(); v.Normalize(); transform = new XbimMatrix3D(v.X, v.Y, 0, 0, v.Y, v.X, 0, 0, 0, 0, 1, 0, axis2.Location.X, axis2.Location.Y, 0, 1); } else transform = new XbimMatrix3D(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, axis2.Location.X, axis2.Location.Y, axis2.Location.Z, 1); if (maps != null) maps.TryAdd(axis2.EntityLabel, transform); return (XbimMatrix3D)transform; }
/// <summary> /// Compares two matrices for equality within a certain margin of error /// </summary> /// <param name="a">a First matrix</param> /// <param name="b">b Second matrix</param> /// <returns>True if a is equivalent to b</returns> public static bool Equal(XbimMatrix3D a, XbimMatrix3D b) { return(Math.Abs(a.M11 - b.M11) < FloatEpsilon && Math.Abs(a.M12 - b.M12) < FloatEpsilon && Math.Abs(a.M13 - b.M13) < FloatEpsilon && Math.Abs(a.M14 - b.M14) < FloatEpsilon && Math.Abs(a.M21 - b.M21) < FloatEpsilon && Math.Abs(a.M22 - b.M22) < FloatEpsilon && Math.Abs(a.M23 - b.M23) < FloatEpsilon && Math.Abs(a.M24 - b.M34) < FloatEpsilon && Math.Abs(a.M31 - b.M31) < FloatEpsilon && Math.Abs(a.M32 - b.M32) < FloatEpsilon && Math.Abs(a.M33 - b.M33) < FloatEpsilon && Math.Abs(a.M34 - b.M34) < FloatEpsilon && Math.Abs(a.OffsetX - b.OffsetX) < FloatEpsilon && Math.Abs(a.OffsetY - b.OffsetY) < FloatEpsilon && Math.Abs(a.OffsetZ - b.OffsetZ) < FloatEpsilon && Math.Abs(a.M44 - b.M44) < FloatEpsilon); }
public static XbimPoint3D Multiply(XbimPoint3D p, XbimMatrix3D m) { var x = p.X; var y = p.Y; var z = p.Z; XbimPoint3D pRet = new XbimPoint3D(m.M11 * x + m.M21 * y + m.M31 * z + m.OffsetX, m.M12 * x + m.M22 * y + m.M32 * z + m.OffsetY, m.M13 * x + m.M23 * y + m.M33 * z + m.OffsetZ ); if (m.IsAffine) return pRet; double affineRatio = x * m.M14 + y * m.M24 + z * m.M34 + m.M44; x = pRet.X / affineRatio; y = pRet.Y / affineRatio; z = pRet.Z / affineRatio; return new XbimPoint3D(x, y, z); }
public static XbimMatrix3D CreateWorld(XbimVector3D position, XbimVector3D forward, XbimVector3D up) { // prepare vectors forward.Normalized(); XbimVector3D vector = forward * -1; XbimVector3D vector2 = XbimVector3D.CrossProduct(up, vector); vector2.Normalized(); XbimVector3D vector3 = XbimVector3D.CrossProduct(vector, vector2); // prepare matrix XbimMatrix3D result = new XbimMatrix3D( vector2.X, vector2.Y, vector2.Z, 0.0, vector3.X, vector3.Y, vector3.Z, 0.0, vector.X, vector.Y, vector.Z, 0.0, position.X, position.Y, position.Z, 0.0); return(result); }
// Microsoft.Xna.Framework.Matrix public static XbimMatrix3D CreateLookAt(XbimVector3D cameraPosition, XbimVector3D cameraTarget, XbimVector3D cameraUpVector) { // prepare vectors XbimVector3D vector = cameraPosition - cameraTarget; vector.Normalized(); XbimVector3D vector2 = XbimVector3D.CrossProduct(cameraUpVector, vector); vector2.Normalized(); XbimVector3D vector3 = XbimVector3D.CrossProduct(vector, vector2); // prepare matrix XbimMatrix3D result = new XbimMatrix3D( vector2.X, vector3.X, vector.X, 0.0, vector2.Y, vector3.Y, vector.Y, 0.0, vector2.Z, vector3.Z, vector.Z, 0.0, -XbimVector3D.DotProduct(vector2, cameraPosition), -XbimVector3D.DotProduct(vector3, cameraPosition), -XbimVector3D.DotProduct(vector, cameraPosition), 1.0); return(result); }
/// <summary> /// Compares two matrices for equality within a certain margin of error /// </summary> /// <param name="a">a First matrix</param> /// <param name="b">b Second matrix</param> /// <returns>True if a is equivalent to b</returns> public static bool Equal(XbimMatrix3D a, XbimMatrix3D b) { return(System.Object.ReferenceEquals(a, b) || ( Math.Abs(a.M11 - b.M11) < FLOAT_EPSILON && Math.Abs(a.M12 - b.M12) < FLOAT_EPSILON && Math.Abs(a.M13 - b.M13) < FLOAT_EPSILON && Math.Abs(a.M14 - b.M14) < FLOAT_EPSILON && Math.Abs(a.M21 - b.M21) < FLOAT_EPSILON && Math.Abs(a.M22 - b.M22) < FLOAT_EPSILON && Math.Abs(a.M23 - b.M23) < FLOAT_EPSILON && Math.Abs(a.M24 - b.M34) < FLOAT_EPSILON && Math.Abs(a.M31 - b.M31) < FLOAT_EPSILON && Math.Abs(a.M32 - b.M32) < FLOAT_EPSILON && Math.Abs(a.M33 - b.M33) < FLOAT_EPSILON && Math.Abs(a.M34 - b.M34) < FLOAT_EPSILON && Math.Abs(a.OffsetX - b.OffsetX) < FLOAT_EPSILON && Math.Abs(a.OffsetY - b.OffsetY) < FLOAT_EPSILON && Math.Abs(a.OffsetZ - b.OffsetZ) < FLOAT_EPSILON && Math.Abs(a.M44 - b.M44) < FLOAT_EPSILON )); }
/// <summary> /// Transforms a bounding rect so that it is still axis aligned /// </summary> /// <param name="rect3d"></param> /// <param name="m"></param> /// <returns></returns> static public XbimRect3D TransformBy(XbimRect3D rect3d, XbimMatrix3D m) { XbimPoint3D min = rect3d.Min; XbimPoint3D max = rect3d.Max; XbimVector3D up = m.Up; XbimVector3D right = m.Right; XbimVector3D backward = m.Backward; var xa = right * min.X; var xb = right * max.X; var ya = up * min.Y; var yb = up * max.Y; var za = backward * min.Z; var zb = backward * max.Z; return(new XbimRect3D( XbimVector3D.Min(xa, xb) + XbimVector3D.Min(ya, yb) + XbimVector3D.Min(za, zb) + m.Translation, XbimVector3D.Max(xa, xb) + XbimVector3D.Max(ya, yb) + XbimVector3D.Max(za, zb) + m.Translation )); }
public void TransformSolidRectangularProfileDef() { using (var m = XbimModel.CreateTemporaryModel()) { using (var txn = m.BeginTransaction()) { var profile = IfcModelBuilder.MakeRectangleHollowProfileDef(m, 20, 10, 1); var extrude = IfcModelBuilder.MakeExtrudedAreaSolid(m, profile, 40); var solid = _xbimGeometryCreator.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"); } } } }
public static XbimPoint3D Multiply(XbimPoint3D p, XbimMatrix3D m) { var x = p.X; var y = p.Y; var z = p.Z; XbimPoint3D pRet = new XbimPoint3D(m.M11 * x + m.M21 * y + m.M31 * z + m.OffsetX, m.M12 * x + m.M22 * y + m.M32 * z + m.OffsetY, m.M13 * x + m.M23 * y + m.M33 * z + m.OffsetZ ); if (!m.IsAffine) { double AffineRatio = x * m.M14 + y * m.M24 + z * m.M34 + m.M44; pRet.X /= AffineRatio; pRet.Y /= AffineRatio; pRet.Z /= AffineRatio; } return(pRet); }
public static XbimPoint3D Multiply(XbimPoint3D p, XbimMatrix3D m) { var x = p.X; var y = p.Y; var z = p.Z; XbimPoint3D pRet = new XbimPoint3D(m.M11 * x + m.M21 * y + m.M31 * z + m.OffsetX, m.M12 * x + m.M22 * y + m.M32 * z + m.OffsetY, m.M13 * x + m.M23 * y + m.M33 * z + m.OffsetZ ); if (!m.IsAffine) { double AffineRatio = x * m.M14 + y * m.M24 + z * m.M34 + m.M44; pRet.X /= AffineRatio; pRet.Y /= AffineRatio; pRet.Z /= AffineRatio; } return pRet; }
private static XbimMatrix3D CreateRotation(double angle, XbimVector3D axis) { XbimMatrix3D ret = XbimMatrix3D.Identity; if (angle == 0 || (axis.X == 0 && axis.Y == 0 && axis.Z == 0)) { return(ret); } double xx, yy, zz, xy, yz, zx, xs, ys, zs, one_c, s, c; s = Math.Sin(angle); c = Math.Cos(angle); double x = axis.X; double y = axis.Y; double z = axis.Z; // simple cases if (x == 0) { if (y == 0) { if (z != 0) { // rotate only around z-axis ret.M11 = c; ret.M22 = c; if (z < 0) { ret.M21 = -s; ret.M12 = s; } else { ret.M21 = s; ret.M12 = -s; } return(ret); } } else if (z == 0) { // rotate only around y-axis ret.M11 = c; ret.M33 = c; if (y < 0) { ret.M31 = s; ret.M13 = -s; } else { ret.M31 = -s; ret.M13 = s; } return(ret); } } else if (y == 0) { if (z == 0) { // rotate only around x-axis ret.M22 = c; ret.M33 = c; if (x < 0) { ret.M32 = -s; ret.M23 = s; } else { ret.M32 = s; ret.M23 = -s; } return(ret); } } // Beginning of general axisa to matrix conversion var dot = x * x + y * y + z * z; if (dot > 1.0001 || dot < 0.99999) { var mag = Math.Sqrt(dot); x /= mag; y /= mag; z /= mag; } xx = x * x; yy = y * y; zz = z * z; xy = x * y; yz = y * z; zx = z * x; xs = x * s; ys = y * s; zs = z * s; one_c = 1 - c; ret.M11 = ((one_c * xx) + c); ret.M21 = ((one_c * xy) + zs); ret.M31 = ((one_c * zx) - ys); ret.M12 = ((one_c * xy) - zs); ret.M22 = ((one_c * yy) + c); ret.M32 = ((one_c * yz) + xs); ret.M13 = ((one_c * zx) + ys); ret.M23 = ((one_c * yz) - xs); ret.M33 = ((one_c * zz) + c); return(ret); }
/// <summary> /// Creates a new instance of a mat4 /// </summary> /// <param name="mat">Single[16] containing values to initialize with</param> /// <returns>New mat4New mat4</returns> public static XbimMatrix3D Copy(XbimMatrix3D m) { return new XbimMatrix3D(m.M11 , m.M12 , m.M13, m.M14 , m.M21 , m.M22 , m.M23, m.M24 , m.M31 , m.M32 , m.M33, m.M34 , m.OffsetX , m.OffsetY , m.OffsetZ , m.M44); }
public static XbimMatrix3D CreateWorld(XbimVector3D position, XbimVector3D forward, XbimVector3D up) { // prepare vectors forward.Normalize(); XbimVector3D vector = forward * -1; XbimVector3D vector2 = XbimVector3D.CrossProduct(up, vector); vector2.Normalize(); XbimVector3D vector3 = XbimVector3D.CrossProduct(vector, vector2); // prepare matrix XbimMatrix3D result = new XbimMatrix3D( vector2.X, vector2.Y, vector2.Z, 0.0, vector3.X, vector3.Y, vector3.Z, 0.0, vector.X, vector.Y, vector.Z, 0.0, position.X, position.Y, position.Z, 0.0); return result; }
// Microsoft.Xna.Framework.Matrix public static XbimMatrix3D CreateLookAt(XbimVector3D cameraPosition, XbimVector3D cameraTarget, XbimVector3D cameraUpVector) { // prepare vectors XbimVector3D vector = cameraPosition - cameraTarget; vector.Normalize(); XbimVector3D vector2 = XbimVector3D.CrossProduct(cameraUpVector, vector); vector2.Normalize(); XbimVector3D vector3 = XbimVector3D.CrossProduct(vector, vector2); // prepare matrix XbimMatrix3D result = new XbimMatrix3D( vector2.X, vector3.X, vector.X, 0.0, vector2.Y, vector3.Y, vector.Y, 0.0, vector2.Z, vector3.Z, vector.Z, 0.0, -XbimVector3D.DotProduct(vector2, cameraPosition), -XbimVector3D.DotProduct(vector3, cameraPosition), -XbimVector3D.DotProduct(vector, cameraPosition), 1.0); return result; }
/// <summary> /// Decomposes a matrix into a scale, rotation, and translation. /// </summary> /// <param name="scale">When the method completes, contains the scaling component of the decomposed matrix.</param> /// <param name="rotation">When the method completes, contains the rtoation component of the decomposed matrix.</param> /// <param name="translation">When the method completes, contains the translation component of the decomposed matrix.</param> /// <remarks> /// This method is designed to decompose an SRT transformation matrix only. /// </remarks> public bool Decompose(out XbimVector3D scale, out XbimQuaternion rotation, out XbimVector3D translation) { //Source: Unknown // References: http://www.gamedev.net/community/forums/topic.asp?topic_id=441695 // via https://code.google.com/p/sharpdx/source/browse/Source/SharpDX/Matrix.cs?r=9f9e209b1be04f06f294bc6d72b06055ad6abdcc //Get the translation. translation = new XbimVector3D(); translation.X = this._offsetX; translation.Y = this._offsetY; translation.Z = this._offsetZ; //Scaling is the length of the rows. scale = new XbimVector3D(); scale.X = Math.Sqrt((M11 * M11) + (M12 * M12) + (M13 * M13)); scale.Y = Math.Sqrt((M21 * M21) + (M22 * M22) + (M23 * M23)); scale.Z = Math.Sqrt((M31 * M31) + (M32 * M32) + (M33 * M33)); //If any of the scaling factors are zero, than the rotation matrix can not exist. // double ZeroTolerance = 0.000003; if (Math.Abs(scale.X) < ZeroTolerance || Math.Abs(scale.Y) < ZeroTolerance || Math.Abs(scale.Z) < ZeroTolerance) { rotation = new XbimQuaternion(); // defaults to identity return false; } //The rotation is the left over matrix after dividing out the scaling. XbimMatrix3D rotationmatrix = new XbimMatrix3D(); rotationmatrix.M11 = M11 / scale.X; rotationmatrix.M12 = M12 / scale.X; rotationmatrix.M13 = M13 / scale.X; rotationmatrix.M21 = M21 / scale.Y; rotationmatrix.M22 = M22 / scale.Y; rotationmatrix.M23 = M23 / scale.Y; rotationmatrix.M31 = M31 / scale.Z; rotationmatrix.M32 = M32 / scale.Z; rotationmatrix.M33 = M33 / scale.Z; rotationmatrix.M44 = 1; XbimQuaternion.RotationMatrix(ref rotationmatrix, out rotation); return true; }
internal void SetCenterInMeters(XbimVector3D modelTranslation) { var translation = XbimMatrix3D.CreateTranslation(modelTranslation * OneMeter); var scaling = XbimMatrix3D.CreateScale(1/OneMeter); Transfrom = translation * scaling; }
public void Add(string mesh, Type productType, int productLabel, int geometryLabel, XbimMatrix3D? transform, short modelId) { Add(mesh, IfcMetaData.IfcTypeId(productType), productLabel, geometryLabel, transform, modelId); }
/// <summary> /// Transforms a bounding rect so that it is still axis aligned /// </summary> /// <param name="rect3d"></param> /// <param name="m"></param> /// <returns></returns> static public XbimRect3D TransformBy(XbimRect3D rect3d, XbimMatrix3D m) { XbimPoint3D min = rect3d.Min; XbimPoint3D max = rect3d.Max; XbimVector3D up = m.Up; XbimVector3D right = m.Right; XbimVector3D backward = m.Backward; var xa = right * min.X; var xb = right * max.X; var ya = up * min.Y; var yb = up * max.Y; var za = backward * min.Z; var zb = backward * max.Z; return new XbimRect3D( XbimVector3D.Min(xa, xb) + XbimVector3D.Min(ya, yb) + XbimVector3D.Min(za, zb) + m.Translation, XbimVector3D.Max(xa, xb) + XbimVector3D.Max(ya, yb) + XbimVector3D.Max(za, zb) + m.Translation ); }
private bool IncludePoint(XbimPoint3D Point, XbimMatrix3D Matrix) { XbimPoint3D t = XbimPoint3D.Multiply(Point, Matrix); return IncludePoint(t); }
public static void Read(this MeshGeometry3D m3D, string shapeData, XbimMatrix3D? transform = null) { transform = null; RotateTransform3D qrd = new RotateTransform3D(); Matrix3D? matrix3D = null; if (transform.HasValue) { XbimQuaternion xq = transform.Value.GetRotationQuaternion(); qrd.Rotation = new QuaternionRotation3D(new Quaternion(xq.X, xq.Y, xq.Z, xq.W)); matrix3D = transform.Value.ToMatrix3D(); } using (StringReader sr = new StringReader(shapeData)) { int version = 1; List<Point3D> vertexList = new List<Point3D>(512); //holds the actual unique positions of the vertices in this data set in the mesh List<Vector3D> normalList = new List<Vector3D>(512); //holds the actual unique normals of the vertices in this data set in the mesh List<Point3D> positions = new List<Point3D>(1024); //holds the actual positions of the vertices in this data set in the mesh List<Vector3D> normals = new List<Vector3D>(1024); //holds the actual normals of the vertices in this data set in the mesh List<int> triangleIndices = new List<int>(2048); String line; // Read and display lines from the data until the end of // the data is reached. while ((line = sr.ReadLine()) != null) { string[] tokens = line.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); if (tokens.Length > 0) //we need a command { string command = tokens[0].Trim().ToUpper(); switch (command) { case "P": vertexList = new List<Point3D>(512); normalList = new List<Vector3D>(512); if (tokens.Length > 0) version = Int32.Parse(tokens[1]); break; case "V": //process vertices for (int i = 1; i < tokens.Length; i++) { string[] xyz = tokens[i].Split(','); Point3D p = new Point3D(Convert.ToDouble(xyz[0], CultureInfo.InvariantCulture), Convert.ToDouble(xyz[1], CultureInfo.InvariantCulture), Convert.ToDouble(xyz[2], CultureInfo.InvariantCulture)); if (matrix3D.HasValue) p = matrix3D.Value.Transform(p); vertexList.Add(p); } break; case "N": //processes normals for (int i = 1; i < tokens.Length; i++) { string[] xyz = tokens[i].Split(','); Vector3D v = new Vector3D(Convert.ToDouble(xyz[0], CultureInfo.InvariantCulture), Convert.ToDouble(xyz[1], CultureInfo.InvariantCulture), Convert.ToDouble(xyz[2], CultureInfo.InvariantCulture)); normalList.Add(v); } break; case "T": //process triangulated meshes Vector3D currentNormal = new Vector3D(0,0,0); //each time we start a new mesh face we have to duplicate the vertices to ensure that we get correct shading of planar and non planar faces var writtenVertices = new Dictionary<int, int>(); for (int i = 1; i < tokens.Length; i++) { string[] indices = tokens[i].Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); if (indices.Length != 3) throw new Exception("Invalid triangle definition"); for (int t = 0; t < 3; t++) { string[] indexNormalPair = indices[t].Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries); if (indexNormalPair.Length > 1) //we have a normal defined { if (version == 1) { string normalStr = indexNormalPair[1].Trim(); switch (normalStr) { case "F": //Front currentNormal = new Vector3D(0, -1, 0); break; case "B": //Back currentNormal = new Vector3D(0, 1, 0); break; case "L": //Left currentNormal = new Vector3D(-1, 0, 0); break; case "R": //Right currentNormal = new Vector3D(1, 0, 0); break; case "U": //Up currentNormal = new Vector3D(0, 0, 1); break; case "D": //Down currentNormal = new Vector3D(0, 0, -1); break; default: //it is an index number int normalIndex = int.Parse(indexNormalPair[1]); currentNormal = normalList[normalIndex]; break; } } else //we have support for packed normals { var packedNormal = new XbimPackedNormal(ushort.Parse(indexNormalPair[1])); var n = packedNormal.Normal; currentNormal = new Vector3D(n.X, n.Y, n.Z); } if (matrix3D.HasValue) { currentNormal = qrd.Transform(currentNormal); } } //now add the index int index = int.Parse(indexNormalPair[0]); int alreadyWrittenAt; //in case it is the first mesh if (!writtenVertices.TryGetValue(index, out alreadyWrittenAt)) //if we haven't written it in this mesh pass, add it again unless it is the first one which we know has been written { //all vertices will be unique and have only one normal writtenVertices.Add(index, positions.Count); triangleIndices.Add(positions.Count + m3D.TriangleIndices.Count); positions.Add(vertexList[index]); normals.Add(currentNormal); } else //just add the index reference { if(normals[alreadyWrittenAt] == currentNormal) triangleIndices.Add(alreadyWrittenAt); else //we need another { triangleIndices.Add(positions.Count + m3D.TriangleIndices.Count); positions.Add(vertexList[index]); normals.Add(currentNormal); } } } } break; case "F": //skip faces for now, can be used to draw edges break; default: throw new Exception("Invalid Geometry Command"); } } } m3D.Positions = new Point3DCollection(m3D.Positions.Concat(positions)); //we do this for wpf performance issues m3D.Normals = new Vector3DCollection(m3D.Normals.Concat(normals)); //we do this for wpf performance issues m3D.TriangleIndices = new Int32Collection(m3D.TriangleIndices.Concat(triangleIndices)); //we do this for wpf performance issues } }
public BoundingBox TransformBy(XbimMatrix3D m) { return new BoundingBox(m.Transform(PointMin), m.Transform(PointMax)); }
/// <summary> /// Reads an ascii string of Xbim mesh geometry data /// </summary> /// <param name="data"></param> /// <returns></returns> public bool Read(String data, XbimMatrix3D? trans = null) { var version = 2; //we are at at least verson 2 now var q = new XbimQuaternion(); if (trans.HasValue) q = trans.Value.GetRotationQuaternion(); using (var sr = new StringReader(data)) { var vertexList = new List<XbimPoint3D>(); //holds the actual positions of the vertices in this data set in the mesh var normalList = new List<XbimVector3D>(); //holds the actual normals of the vertices in this data set in the mesh String line; // Read and display lines from the data until the end of // the data is reached. while ((line = sr.ReadLine()) != null) { var tokens = line.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); if (tokens.Length > 1) //we need a command and some data { var command = tokens[0].Trim().ToUpper(); switch (command) { case "P": version = Int32.Parse(tokens[1]); var pointCount = 512; //var faceCount = 128; //var triangleCount = 256; var normalCount = 512; if (tokens.Length > 1) pointCount = Int32.Parse(tokens[2]); // if (tokens.Length > 2) faceCount = Int32.Parse(tokens[3]); // if (tokens.Length > 3) triangleCount = Int32.Parse(tokens[4]); //version 2 of the string format uses packed normals if (version < 2 && tokens.Length > 4) normalCount = Int32.Parse(tokens[5]); vertexList = new List<XbimPoint3D>(pointCount); normalList = new List<XbimVector3D>(normalCount); break; case "V": //process vertices for (var i = 1; i < tokens.Length; i++) { var xyz = tokens[i].Split(','); var p = new XbimPoint3D(Convert.ToDouble(xyz[0], CultureInfo.InvariantCulture), Convert.ToDouble(xyz[1], CultureInfo.InvariantCulture), Convert.ToDouble(xyz[2], CultureInfo.InvariantCulture)); if (trans.HasValue) p = trans.Value.Transform(p); vertexList.Add(p); } break; case "N": //processes normals for (var i = 1; i < tokens.Length; i++) { var xyz = tokens[i].Split(','); var v = new XbimVector3D(Convert.ToDouble(xyz[0], CultureInfo.InvariantCulture), Convert.ToDouble(xyz[1], CultureInfo.InvariantCulture), Convert.ToDouble(xyz[2], CultureInfo.InvariantCulture)); normalList.Add(v); } break; case "T": //process triangulated meshes var currentNormal = XbimVector3D.Zero; //each time we start a new mesh face we have to duplicate the vertices to ensure that we get correct shading of planar and non planar faces var writtenVertices = new Dictionary<int, int>(); for (var i = 1; i < tokens.Length; i++) { var triangleIndices = tokens[i].Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); if (triangleIndices.Length != 3) throw new Exception("Invalid triangle definition"); for (var t = 0; t < 3; t++) { var indexNormalPair = triangleIndices[t].Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries); if (indexNormalPair.Length > 1) //we have a normal defined { var normalStr = indexNormalPair[1].Trim(); if (version < 2) { switch (normalStr) { case "F": //Front currentNormal = new XbimVector3D(0, -1, 0); break; case "B": //Back currentNormal = new XbimVector3D(0, 1, 0); break; case "L": //Left currentNormal = new XbimVector3D(-1, 0, 0); break; case "R": //Right currentNormal = new XbimVector3D(1, 0, 0); break; case "U": //Up currentNormal = new XbimVector3D(0, 0, 1); break; case "D": //Down currentNormal = new XbimVector3D(0, 0, -1); break; default: //it is an index number var normalIndex = int.Parse(indexNormalPair[1]); currentNormal = normalList[normalIndex]; break; } } else { var normalIndex = ushort.Parse(indexNormalPair[1]); var packedNormal = new XbimPackedNormal(normalIndex); currentNormal = packedNormal.Normal; } if (trans.HasValue) { XbimVector3D v; XbimQuaternion.Transform(ref currentNormal, ref q, out v); currentNormal = v; } } //now add the index var index = int.Parse(indexNormalPair[0]); int alreadyWrittenAt; if (!writtenVertices.TryGetValue(index, out alreadyWrittenAt)) //if we haven't written it in this mesh pass, add it again unless it is the first one which we know has been written { //all vertices will be unique and have only one normal writtenVertices.Add(index, PositionCount); TriangleIndices.Add(PositionCount); Positions.Add(vertexList[index]); Normals.Add(currentNormal); } else //just add the index reference { TriangleIndices.Add(alreadyWrittenAt); } } } break; case "F": break; default: throw new Exception("Invalid Geometry Command"); } } } } return true; }
public void Add(string mesh, short productTypeId, int productLabel, int geometryLabel, XbimMatrix3D? transform, short modelId) { lock (meshLock) { var frag = new XbimMeshFragment(PositionCount, TriangleIndexCount, productTypeId, productLabel, geometryLabel, modelId); Read(mesh, transform); frag.EndPosition = PositionCount - 1; frag.EndTriangleIndex = TriangleIndexCount - 1; _meshes.Add(frag); } }
public static XbimMeshGeometry3D MakeBoundingBox(XbimRect3D r3D, XbimMatrix3D transform) { XbimMeshGeometry3D mesh = new XbimMeshGeometry3D(8); XbimPoint3D p0 = transform.Transform(r3D.Location); XbimPoint3D p1 = p0; p1.X += r3D.SizeX; XbimPoint3D p2 = p1; p2.Z += r3D.SizeZ; XbimPoint3D p3 = p2; p3.X -= r3D.SizeX; XbimPoint3D p4 = p3; p4.Y += r3D.SizeY; XbimPoint3D p5 = p4; p5.Z -= r3D.SizeZ; XbimPoint3D p6 = p5; p6.X += r3D.SizeX; XbimPoint3D p7 = p6; p7.Z += r3D.SizeZ; mesh.Positions.Add(p0); mesh.Positions.Add(p1); mesh.Positions.Add(p2); mesh.Positions.Add(p3); mesh.Positions.Add(p4); mesh.Positions.Add(p5); mesh.Positions.Add(p6); mesh.Positions.Add(p7); mesh.TriangleIndices.Add(3); mesh.TriangleIndices.Add(0); mesh.TriangleIndices.Add(2); mesh.TriangleIndices.Add(0); mesh.TriangleIndices.Add(1); mesh.TriangleIndices.Add(2); mesh.TriangleIndices.Add(4); mesh.TriangleIndices.Add(5); mesh.TriangleIndices.Add(3); mesh.TriangleIndices.Add(5); mesh.TriangleIndices.Add(0); mesh.TriangleIndices.Add(3); mesh.TriangleIndices.Add(7); mesh.TriangleIndices.Add(6); mesh.TriangleIndices.Add(4); mesh.TriangleIndices.Add(6); mesh.TriangleIndices.Add(5); mesh.TriangleIndices.Add(4); mesh.TriangleIndices.Add(2); mesh.TriangleIndices.Add(1); mesh.TriangleIndices.Add(7); mesh.TriangleIndices.Add(1); mesh.TriangleIndices.Add(6); mesh.TriangleIndices.Add(7); mesh.TriangleIndices.Add(4); mesh.TriangleIndices.Add(3); mesh.TriangleIndices.Add(7); mesh.TriangleIndices.Add(3); mesh.TriangleIndices.Add(2); mesh.TriangleIndices.Add(7); mesh.TriangleIndices.Add(6); mesh.TriangleIndices.Add(1); mesh.TriangleIndices.Add(5); mesh.TriangleIndices.Add(1); mesh.TriangleIndices.Add(0); mesh.TriangleIndices.Add(5); return mesh; }
/// <summary> /// Reads a triangulated model from an array of bytes and adds the mesh to the current state /// </summary> /// <param name="m3D"></param> /// <param name="mesh">byte array of XbimGeometryType.PolyhedronBinary Data</param> /// <param name="transform">Transforms the mesh to the new position if not null</param> public static void Read(this MeshGeometry3D m3D, byte[] mesh, XbimMatrix3D? transform = null) { int indexBase = m3D.Positions.Count; var qrd = new RotateTransform3D(); Matrix3D? matrix3D = null; if (transform.HasValue) { var xq = transform.Value.GetRotationQuaternion(); var quaternion = new Quaternion(xq.X, xq.Y, xq.Z, xq.W); if (!quaternion.IsIdentity) qrd.Rotation = new QuaternionRotation3D(quaternion); else qrd = null; matrix3D = transform.Value.ToMatrix3D(); } using (var ms = new MemoryStream(mesh)) { using (var br = new BinaryReader(ms)) { // ReSharper disable once UnusedVariable var version = br.ReadByte(); //stream format version var numVertices = br.ReadInt32(); var numTriangles = br.ReadInt32(); var uniqueVertices = new List<Point3D>(numVertices); var vertices = new List<Point3D>(numVertices * 4); //approx the size var triangleIndices = new List<Int32>(numTriangles*3); var normals = new List<Vector3D>(numVertices * 4); for (var i = 0; i < numVertices; i++) { double x = br.ReadSingle(); double y = br.ReadSingle(); double z = br.ReadSingle(); var p = new Point3D(x, y, z); if (matrix3D.HasValue) p = matrix3D.Value.Transform(p); uniqueVertices.Add(p); } var numFaces = br.ReadInt32(); for (var i = 0; i < numFaces; i++) { var numTrianglesInFace = br.ReadInt32(); if (numTrianglesInFace == 0) continue; var isPlanar = numTrianglesInFace > 0; numTrianglesInFace = Math.Abs(numTrianglesInFace); if (isPlanar) { var normal = br.ReadPackedNormal().Normal; var wpfNormal = new Vector3D(normal.X, normal.Y, normal.Z); if (qrd!=null) //transform the normal if we have to wpfNormal = qrd.Transform(wpfNormal); var uniqueIndices = new Dictionary<int, int>(); for (var j = 0; j < numTrianglesInFace; j++) { for (int k = 0; k < 3; k++) { int idx = ReadIndex(br, numVertices); int writtenIdx; if (!uniqueIndices.TryGetValue(idx, out writtenIdx)) //we haven't got it, so add it { writtenIdx = vertices.Count; vertices.Add(uniqueVertices[idx]); uniqueIndices.Add(idx, writtenIdx); //add a matching normal normals.Add(wpfNormal); } triangleIndices.Add(indexBase + writtenIdx); } } } else { var uniqueIndices = new Dictionary<int, int>(); for (var j = 0; j < numTrianglesInFace; j++) { for (int k = 0; k < 3; k++) { int idx = ReadIndex(br, numVertices); var normal = br.ReadPackedNormal().Normal; int writtenIdx; var wpfNormal = new Vector3D(normal.X, normal.Y, normal.Z); if (qrd != null) //transform the normal if we have to wpfNormal = qrd.Transform(wpfNormal); if (!uniqueIndices.TryGetValue(idx, out writtenIdx)) //we haven't got it, so add it { writtenIdx = vertices.Count; vertices.Add(uniqueVertices[idx]); uniqueIndices.Add(idx, writtenIdx); normals.Add(wpfNormal); } else { if (normals[writtenIdx] != wpfNormal) //deal with normals that vary at a node { writtenIdx = vertices.Count; vertices.Add(uniqueVertices[idx]); normals.Add(wpfNormal); } } triangleIndices.Add(indexBase + writtenIdx); } } } } m3D.Positions = new Point3DCollection(m3D.Positions.Concat(vertices)); m3D.TriangleIndices = new Int32Collection(m3D.TriangleIndices.Concat(triangleIndices)); m3D.Normals = new Vector3DCollection(m3D.Normals.Concat(normals)); } // if(m3D.CanFreeze) m3D.Freeze(); //freeze the mesh to improve performance } }
/// <summary> /// Adds the geometry to the mesh for the given product, returns the mesh fragment details /// </summary> /// <param name="geometryModel">Geometry to add</param> /// <param name="product">The product the geometry represents (this may be a partial representation)</param> /// <param name="transform">Transform the geometry to a new location or rotation</param> /// <param name="deflection">Deflection for triangulating curves, if null default defelction for the model is used</param> public XbimMeshFragment Add(IXbimGeometryModel geometryModel, IfcProduct product, XbimMatrix3D transform, double? deflection = null, short modelId = 0) { return geometryModel.MeshTo(this, product, transform, deflection ?? product.ModelOf.ModelFactors.DeflectionTolerance); }
/// <summary> /// Warning: This function assumes no rotation is used for the tranform. /// </summary> /// <param name="composed">The NON-ROTATING transform to apply</param> /// <returns>the transformed bounding box.</returns> public XbimRect3D Transform(XbimMatrix3D composed) { var min = this.Min * composed; var max = this.Max * composed; return new XbimRect3D(min, max); }
/// <summary> /// Builds a windows Matrix3D from an ObjectPlacement /// Conversion fo c++ function CartesianTransform::ConvertMatrix3D from CartesianTransform.cpp /// </summary> /// <param name="objPlacement">IfcObjectPlacement object</param> /// <returns>Matrix3D</returns> protected XbimMatrix3D ConvertMatrix3D(IfcObjectPlacement objPlacement) { if(objPlacement is IfcLocalPlacement) { IfcLocalPlacement locPlacement = (IfcLocalPlacement)objPlacement; if (locPlacement.RelativePlacement is IfcAxis2Placement3D) { IfcAxis2Placement3D axis3D = (IfcAxis2Placement3D)locPlacement.RelativePlacement; XbimVector3D ucsXAxis = new XbimVector3D(axis3D.RefDirection.DirectionRatios[0], axis3D.RefDirection.DirectionRatios[1], axis3D.RefDirection.DirectionRatios[2]); XbimVector3D ucsZAxis = new XbimVector3D(axis3D.Axis.DirectionRatios[0], axis3D.Axis.DirectionRatios[1], axis3D.Axis.DirectionRatios[2]); ucsXAxis.Normalize(); ucsZAxis.Normalize(); XbimVector3D ucsYAxis = XbimVector3D.CrossProduct(ucsZAxis, ucsXAxis); ucsYAxis.Normalize(); XbimPoint3D ucsCentre = axis3D.Location.XbimPoint3D(); XbimMatrix3D ucsTowcs = new XbimMatrix3D(ucsXAxis.X, ucsXAxis.Y, ucsXAxis.Z, 0, ucsYAxis.X, ucsYAxis.Y, ucsYAxis.Z, 0, ucsZAxis.X, ucsZAxis.Y, ucsZAxis.Z, 0, ucsCentre.X, ucsCentre.Y, ucsCentre.Z , 1); if (locPlacement.PlacementRelTo != null) { return XbimMatrix3D.Multiply(ucsTowcs, ConvertMatrix3D(locPlacement.PlacementRelTo)); } else return ucsTowcs; } else //must be 2D { throw new NotImplementedException("Support for Placements other than 3D not implemented"); } } else //probably a Grid { throw new NotImplementedException("Support for Placements other than Local not implemented"); } }
public static void Read(this XbimMeshGeometry3D m3D, byte[] mesh, XbimMatrix3D? transform = null) { var indexBase = m3D.Positions.Count; var qrd = new XbimQuaternion(); XbimMatrix3D? matrix3D = null; if (transform.HasValue) { qrd = transform.Value.GetRotationQuaternion(); matrix3D = transform.Value; } using (var ms = new MemoryStream(mesh)) { using (var br = new BinaryReader(ms)) { // ReSharper disable once UnusedVariable var version = br.ReadByte(); //stream format version var numVertices = br.ReadInt32(); var numTriangles = br.ReadInt32(); var uniqueVertices = new List<XbimPoint3D>(numVertices); var vertices = new List<XbimPoint3D>(numVertices * 4); //approx the size var triangleIndices = new List<int>(numTriangles * 3); var normals = new List<XbimVector3D>(numVertices * 4); for (var i = 0; i < numVertices; i++) { double x = br.ReadSingle(); double y = br.ReadSingle(); double z = br.ReadSingle(); var p = new XbimPoint3D(x, y, z); if (matrix3D.HasValue) p = matrix3D.Value.Transform(p); uniqueVertices.Add(p); } var numFaces = br.ReadInt32(); for (var i = 0; i < numFaces; i++) { var numTrianglesInFace = br.ReadInt32(); if (numTrianglesInFace == 0) continue; var isPlanar = numTrianglesInFace > 0; numTrianglesInFace = Math.Abs(numTrianglesInFace); if (isPlanar) { var normal = br.ReadPackedNormal().Normal; if (!qrd.IsIdentity()) { var baseVal = new XbimVector3D(normal.X, normal.Y, normal.Z); XbimQuaternion.Transform(ref baseVal, ref qrd, out normal); } var uniqueIndices = new Dictionary<int, int>(); for (var j = 0; j < numTrianglesInFace; j++) { for (var k = 0; k < 3; k++) { var idx = ReadIndex(br, numVertices); int writtenIdx; if (!uniqueIndices.TryGetValue(idx, out writtenIdx)) //we haven't got it, so add it { writtenIdx = vertices.Count; vertices.Add(uniqueVertices[idx]); uniqueIndices.Add(idx, writtenIdx); //add a matching normal normals.Add(normal); } triangleIndices.Add(indexBase + writtenIdx); } } } else { var uniqueIndices = new Dictionary<int, int>(); for (var j = 0; j < numTrianglesInFace; j++) { for (var k = 0; k < 3; k++) { var idx = ReadIndex(br, numVertices); var normal = br.ReadPackedNormal().Normal; int writtenIdx; if (!uniqueIndices.TryGetValue(idx, out writtenIdx)) //we haven't got it, so add it { writtenIdx = vertices.Count; vertices.Add(uniqueVertices[idx]); uniqueIndices.Add(idx, writtenIdx); if (!qrd.IsIdentity()) { var baseVal = new XbimVector3D(normal.X, normal.Y, normal.Z); XbimQuaternion.Transform(ref baseVal, ref qrd, out normal); } normals.Add(normal); } triangleIndices.Add(indexBase + writtenIdx); } } } } m3D.Positions = m3D.Positions.Concat(vertices).ToList(); m3D.TriangleIndices = m3D.TriangleIndices.Concat(triangleIndices).ToList(); m3D.Normals = m3D.Normals.Concat(normals).ToList(); } } }
public static XbimVector3D Multiply(XbimVector3D vec, XbimMatrix3D m) { var x = vec.X; var y = vec.Y; var z = vec.Z; return new XbimVector3D (m.M11 * x + m.M21 * y + m.M31 * z , m.M12 * x + m.M22 * y + m.M32 * z , m.M13 * x + m.M23 * y + m.M33 * z ); }
/// <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.Normalize(); ucsAxisZ.Normalize(); //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; }
public static XbimMatrix3D operator *(XbimMatrix3D a, XbimMatrix3D b) { return(XbimMatrix3D.Multiply(a, b)); }