public static Elements.Floor[] FloorsFromRevitFloor(ADSK.Document doc, ADSK.Floor revitFloor) { var profiles = GetProfilesOfTopFacesOfFloor(doc, revitFloor); var thickness = revitFloor.LookupParameter("Thickness")?.AsDouble(); var floors = new List <Elements.Floor>(); foreach (var profile in profiles) { var zMove = profile.Perimeter.Vertices.Max(v => v.Z); var transform = new ElemGeom.Transform(0, 0, -zMove); var zeroedProfile = transform.OfProfile(profile); transform.Invert(); var floorThickness = thickness.HasValue ? Elements.Units.FeetToMeters(thickness.Value) : Elements.Units.FeetToMeters(1); // Revit floors are extrusions down, and currently Hypar floors are extrusions up, so we also must move by the floor thickness transform.Move(new Vector3(0, 0, -floorThickness)); var floor = new Elements.Floor(zeroedProfile, floorThickness, transform); floors.Add(floor); } return(floors.ToArray()); }
/// <summary> /// Does this ray intersect with the provided face? /// </summary> /// <param name="face">The Face to intersect with.</param> /// <param name="result">The intersection result.</param> /// <returns>True if an intersection occurs, otherwise false. If true, check the intersection result for the location of the intersection.</returns> internal bool Intersects(Face face, out Vector3 result) { var plane = face.Plane(); if (Intersects(plane, out Vector3 intersection)) { var boundaryPolygon = face.Outer.ToPolygon(); var transformToPolygon = new Transform(plane.Origin, plane.Normal); var transformFromPolygon = new Transform(transformToPolygon); transformFromPolygon.Invert(); var transformedPolygon = transformFromPolygon.OfPolygon(boundaryPolygon); var transformedIntersection = transformFromPolygon.OfVector(intersection); if (transformedPolygon.Contains(transformedIntersection) || transformedPolygon.Touches(transformedIntersection)) { result = intersection; return(true); } } result = default(Vector3); return(false); }
/// <summary> /// Does this ray intersect the provided polygon area? /// </summary> /// <param name="polygon">The Polygon to intersect with.</param> /// <param name="result">The intersection result.</param> /// <returns>True if an intersection occurs, otherwise false. If true, check the intersection result for the location of the intersection.</returns> public bool Intersects(Polygon polygon, out Vector3 result) { var plane = new Plane(polygon.Vertices.First(), polygon.Vertices); if (Intersects(plane, out Vector3 intersection)) { var transformToPolygon = new Transform(plane.Origin, plane.Normal); var transformFromPolygon = new Transform(transformToPolygon); transformFromPolygon.Invert(); var transformedIntersection = transformFromPolygon.OfPoint(intersection); IEnumerable <Line> curveList = polygon.Segments(); curveList = curveList.Select(l => l.TransformedLine(transformFromPolygon)); if (Polygon.Contains(curveList, transformedIntersection, out _)) { result = intersection; return(true); } } result = default(Vector3); return(false); }
/// <summary> /// Calculate a counter-clockwise plane angle between this vector and the provided vector, projected to the plane perpendicular to the provided normal. /// </summary> /// <param name="v">The vector with which to measure the angle.</param> /// <param name="normal">The normal of the plane in which you wish to calculate the angle.</param> /// <returns>Angle in degrees between 0 and 360, or NaN if the projected input vectors are invalid.</returns> public double PlaneAngleTo(Vector3 v, Vector3 normal) { var transformFromPlane = new Transform(Vector3.Origin, normal); transformFromPlane.Invert(); var thisTransformed = transformFromPlane.OfVector(this); var otherTransformed = transformFromPlane.OfVector(v); // project to Plane Vector3 a = new Vector3(thisTransformed.X, thisTransformed.Y, 0); Vector3 b = new Vector3(otherTransformed.X, otherTransformed.Y, 0); // reject very small vectors if (a.Length() < Vector3.EPSILON || b.Length() < Vector3.EPSILON) { return(double.NaN); } Vector3 aUnitized = a.Unitized(); Vector3 bUnitized = b.Unitized(); // Cos^-1(a dot b), a dot b clamped to [-1, 1] var angle = Math.Acos(Math.Max(Math.Min(aUnitized.Dot(bUnitized), 1.0), -1.0)); if (Math.Abs(angle) < Vector3.EPSILON) { return(0); } // check if should be reflex angle Vector3 aCrossB = aUnitized.Cross(bUnitized).Unitized(); if (Vector3.ZAxis.Dot(aCrossB) > 0) { return(angle * 180 / Math.PI); } else { return((Math.PI * 2 - angle) * 180 / Math.PI); } }