/// <summary> /// Compute the angle between two edges /// </summary> /// <param name="edgeA">The 1st edge</param> /// <param name="edgeB">The 2nd edge</param> /// <returns>The angle of the 2 edges</returns> private double AngleBetweenEdges(Edge edgeA, Edge edgeB) { Autodesk.Revit.DB.XYZ vectorA = null; Autodesk.Revit.DB.XYZ vectorB = null; // find coincident vertices Autodesk.Revit.DB.XYZ A_0 = edgeA.Evaluate(0); Autodesk.Revit.DB.XYZ A_1 = edgeA.Evaluate(1); Autodesk.Revit.DB.XYZ B_0 = edgeB.Evaluate(0); Autodesk.Revit.DB.XYZ B_1 = edgeB.Evaluate(1); if (A_0.IsAlmostEqualTo(B_0)) { vectorA = edgeA.ComputeDerivatives(0).BasisX.Normalize(); vectorB = edgeA.ComputeDerivatives(0).BasisX.Normalize(); } else if (A_0.IsAlmostEqualTo(B_1)) { vectorA = edgeA.ComputeDerivatives(0).BasisX.Normalize(); vectorB = edgeB.ComputeDerivatives(1).BasisX.Normalize(); } else if (A_1.IsAlmostEqualTo(B_0)) { vectorA = edgeA.ComputeDerivatives(1).BasisX.Normalize(); vectorB = edgeB.ComputeDerivatives(0).BasisX.Normalize(); } else if (A_1.IsAlmostEqualTo(B_1)) { vectorA = edgeA.ComputeDerivatives(1).BasisX.Normalize(); vectorB = edgeB.ComputeDerivatives(1).BasisX.Normalize(); } if (A_1.IsAlmostEqualTo(B_0) || A_0.IsAlmostEqualTo(B_1)) { vectorA = vectorA.Negate(); } if (null == vectorA || null == vectorB) { return(0d); } double angle = Math.Acos(vectorA.DotProduct(vectorB)); return(angle); }
/// <summary> /// Project a point on a face /// </summary> /// <param name="xyzArray">the face points, them fix a face </param> /// <param name="point">the point</param> /// <returns>the projected point on this face</returns> static private Autodesk.Revit.DB.XYZ Project(List <XYZ> xyzArray, Autodesk.Revit.DB.XYZ point) { Autodesk.Revit.DB.XYZ a = xyzArray[0] - xyzArray[1]; Autodesk.Revit.DB.XYZ b = xyzArray[0] - xyzArray[2]; Autodesk.Revit.DB.XYZ c = point - xyzArray[0]; Autodesk.Revit.DB.XYZ normal = (a.CrossProduct(b)); try { normal = normal.Normalize(); } catch (Exception) { normal = Autodesk.Revit.DB.XYZ.Zero; } Autodesk.Revit.DB.XYZ retProjectedPoint = point - (normal.DotProduct(c)) * normal; return(retProjectedPoint); }
/// <summary> /// OK button click event /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void buttonOK_Click(object sender, EventArgs e) { DeleteLines(); if (!UpdateData(false)) { return; } m_outputInfo.Clear(); m_stopWatch.Start(); Transaction transaction = new Transaction(m_doc, "RayTraceBounce"); transaction.Start(); m_LineCount = 0; m_RayCount = 0; // Start Find References By Direction Autodesk.Revit.DB.XYZ startpt = m_origin; m_outputInfo.Add("Start Find References By Direction: "); for (int ctr = 1; ctr <= rayLimit; ctr++) { ReferenceIntersector referenceIntersector = new ReferenceIntersector(m_view); IList <ReferenceWithContext> references = referenceIntersector.Find(startpt, m_direction); m_rClosest = null; FindClosestReference(references); if (m_rClosest == null) { string info = "Ray " + ctr + " aborted. No closest face reference found. "; m_outputInfo.Add(info); if (ctr == 1) { TaskDialog.Show("Revit", info); } break; } else { Reference reference = m_rClosest.GetReference(); Element referenceElement = m_doc.GetElement(reference); GeometryObject referenceObject = referenceElement.GetGeometryObjectFromReference(reference); Autodesk.Revit.DB.XYZ endpt = reference.GlobalPoint; if (startpt.IsAlmostEqualTo(endpt)) { m_outputInfo.Add("Start and end points are equal. Ray " + ctr + " aborted\n" + startpt.X + ", " + startpt.Y + ", " + startpt.Z); break; } else { MakeLine(startpt, endpt, m_direction, "bounce"); m_RayCount = m_RayCount + 1; string info = "Intersected Element Type: [" + referenceElement.GetType().ToString() + "] ElementId: [" + referenceElement.Id.IntegerValue.ToString(); m_face = referenceObject as Face; if (m_face.MaterialElementId != ElementId.InvalidElementId) { Material materialElement = m_doc.GetElement(m_face.MaterialElementId) as Material; info += "] Face MaterialElement Name: [" + materialElement.Name + "] Shininess: [" + materialElement.Shininess; } else { info += "] Face.MaterialElement is null [" + referenceElement.Category.Name; } info += "]"; m_outputInfo.Add(info); Autodesk.Revit.DB.UV endptUV = reference.UVPoint; Autodesk.Revit.DB.XYZ FaceNormal = m_face.ComputeDerivatives(endptUV).BasisZ; // face normal where ray hits FaceNormal = m_rClosest.GetInstanceTransform().OfVector(FaceNormal); // transformation to get it in terms of document coordinates instead of the parent symbol Autodesk.Revit.DB.XYZ directionMirrored = m_direction - 2 * m_direction.DotProduct(FaceNormal) * FaceNormal; //http://www.fvastro.org/presentations/ray_tracing.htm m_direction = directionMirrored; // get ready to shoot the next ray startpt = endpt; } } } transaction.Commit(); m_stopWatch.Stop(); TimeSpan ts = m_stopWatch.Elapsed; string elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}", ts.Hours, ts.Minutes, ts.Seconds, ts.Milliseconds / 10); m_outputInfo.Add(elapsedTime + "\n" + "Lines = " + m_LineCount + "\n" + "Rays = " + m_RayCount); m_stopWatch.Reset(); OutputInformation(); }
private static void GetPolygonPlane(IReadOnlyList <RVT.XYZ> polygon, out RVT.XYZ normal, out double dist, out double area) { normal = RVT.XYZ.Zero; dist = area = 0.0; var n = polygon.Count; var rc = (2 < n); if (3 == n) { var a = polygon[0]; var b = polygon[1]; var c = polygon[2]; var v = b - a; normal = v.CrossProduct(c - a); dist = normal.DotProduct(a); } else if (4 == n) { var a = polygon[0]; var b = polygon[1]; var c = polygon[2]; var d = polygon[3]; var normalX = (c.Y - a.Y) * (d.Z - b.Z) + (c.Z - a.Z) * (b.Y - d.Y); var normalY = (c.Z - a.Z) * (d.X - b.X) + (c.X - a.X) * (b.Z - d.Z); var normalZ = (c.X - a.X) * (d.Y - b.Y) + (c.Y - a.Y) * (b.X - d.X); normal = new RVT.XYZ(normalX, normalY, normalZ); dist = 0.25 * (normal.X * (a.X + b.X + c.X + d.X) + normal.Y * (a.Y + b.Y + c.Y + d.Y) + normal.Z * (a.Z + b.Z + c.Z + d.Z)); } else if (4 < n) { RVT.XYZ a; var b = polygon[n - 2]; var c = polygon[n - 1]; var s = RVT.XYZ.Zero; for (var i = 0; i < n; ++i) { a = b; b = c; c = polygon[i]; var normalX = normal.X + b.Y * (c.Z - a.Z); var normalY = normal.Y + b.Z * (c.X - a.X); var normalZ = normal.Z + b.X * (c.Y - a.Y); normal = new RVT.XYZ(normalX, normalY, normalZ); s += c; } dist = s.DotProduct(normal) / n; } if (rc) { // // the polygon area is half of the length // of the non-normalized normal vector of the plane: // var length = normal.GetLength(); rc = !IsZero(length); if (rc) { normal /= length; dist /= length; area = 0.5 * length; } } }