/// <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++) { IList<ReferenceWithContext> references = m_doc.FindReferencesWithContextByDirection(startpt, m_direction, m_view); 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) { MessageBox.Show(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.get_Element(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(); }
/// <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++) { IList <ReferenceWithContext> references = m_doc.FindReferencesWithContextByDirection(startpt, m_direction, m_view); 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) { MessageBox.Show(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.get_Element(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(); }
/// <summary> /// Find the first intersection with a face /// </summary> /// <param name="references"></param> /// <returns></returns> public Autodesk.Revit.DB.ReferenceWithContext FindClosestReference(IList<ReferenceWithContext> references) { double face_prox = Double.PositiveInfinity; double edge_prox = Double.PositiveInfinity; foreach (ReferenceWithContext r in references) { Reference reference = r.GetReference(); Element referenceElement = m_doc.GetElement(reference); GeometryObject referenceGeometryObject = referenceElement.GetGeometryObjectFromReference(reference); m_face = null; m_face = referenceGeometryObject as Face; Edge edge = null; edge = referenceGeometryObject as Edge; if (m_face != null) { if ((r.Proximity < face_prox)&& (r.Proximity > epsilon)) { m_rClosest = r; face_prox = Math.Abs(r.Proximity); } } else if (edge != null) { if ((r.Proximity < edge_prox) && (r.Proximity > epsilon)) { edge_prox = Math.Abs(r.Proximity); } } } if (edge_prox <= face_prox) { // stop bouncing if there is an edge at least as close as the nearest face - there is no single angle of reflection for a ray striking a line m_outputInfo.Add("there is an edge at least as close as the nearest face - there is no single angle of reflection for a ray striking a line"); m_rClosest = null; } return m_rClosest; }