/// <summary>
/// This method will find out a route to avoid the obstruction.
/// </summary>
/// <param name="pipe">Pipe to resolve</param>
/// <param name="section">Pipe's one obstruction</param>
/// <returns>A route which can avoid the obstruction</returns>
private Line FindRoute(Pipe pipe, Section section)
{
// Perpendicular direction minimal length.
double minLength = pipe.Diameter * 2;
// Parallel direction jump step.
double jumpStep = pipe.Diameter;
// Calculate the directions in which to find the solution.
List <Autodesk.Revit.DB.XYZ> dirs = new List <Autodesk.Revit.DB.XYZ>();
Autodesk.Revit.DB.XYZ crossDir = null;
foreach (ReferenceWithContext gref in section.Refs)
{
Element elem = m_rvtDoc.GetElement(gref.GetReference());
Line locationLine = (elem.Location as LocationCurve).Curve as Line;
Autodesk.Revit.DB.XYZ refDir = locationLine.GetEndPoint(1) - locationLine.GetEndPoint(0);
refDir = refDir.Normalize();
if (refDir.IsAlmostEqualTo(section.PipeCenterLineDirection) || refDir.IsAlmostEqualTo(-section.PipeCenterLineDirection))
{
continue;
}
crossDir = refDir.CrossProduct(section.PipeCenterLineDirection);
dirs.Add(crossDir.Normalize());
break;
}
// When all the obstruction are parallel with the centerline of the pipe,
// We can't calculate the direction from the vector.Cross method.
if (dirs.Count == 0)
{
// Calculate perpendicular directions with dir in four directions.
List <Autodesk.Revit.DB.XYZ> perDirs = PerpendicularDirs(section.PipeCenterLineDirection, 4);
dirs.Add(perDirs[0]);
dirs.Add(perDirs[1]);
}
Line foundLine = null;
while (null == foundLine)
{
// Extend the section interval by jumpStep.
section.Inflate(0, jumpStep);
section.Inflate(1, jumpStep);
// Find solution in the given directions.
for (int i = 0; null == foundLine && i < dirs.Count; i++)
{
// Calculate the intersections.
List <ReferenceWithContext> obs1 = m_detector.Obstructions(section.Start, dirs[i]);
List <ReferenceWithContext> obs2 = m_detector.Obstructions(section.End, dirs[i]);
// Filter out the intersection result.
Filter(pipe, obs1);
Filter(pipe, obs2);
// Find out the minimal intersections in two opposite direction.
ReferenceWithContext[] mins1 = GetClosestSectionsToOrigin(obs1);
ReferenceWithContext[] mins2 = GetClosestSectionsToOrigin(obs2);
// Find solution in the given direction and its opposite direction.
for (int j = 0; null == foundLine && j < 2; j++)
{
if (mins1[j] != null && Math.Abs(mins1[j].Proximity) < minLength ||
mins2[j] != null && Math.Abs(mins2[j].Proximity) < minLength)
{
continue;
}
// Calculate the maximal height that the parallel line can be reached.
double maxHight = 1000 * pipe.Diameter;
if (mins1[j] != null && mins2[j] != null)
{
maxHight = Math.Min(Math.Abs(mins1[j].Proximity), Math.Abs(mins2[j].Proximity));
}
else if (mins1[j] != null)
{
maxHight = Math.Abs(mins1[j].Proximity);
}
else if (mins2[j] != null)
{
maxHight = Math.Abs(mins2[j].Proximity);
}
Autodesk.Revit.DB.XYZ dir = (j == 1) ? dirs[i] : -dirs[i];
// Calculate the parallel line which can avoid obstructions.
foundLine = FindParallelLine(pipe, section, dir, maxHight);
}
}
}
return(foundLine);
}