//
// (C) Copyright 2003-2019 by Autodesk, Inc.
//
// Permission to use, copy, modify, and distribute this software in
// object code form for any purpose and without fee is hereby granted,
// provided that the above copyright notice appears in all copies and
// that both that copyright notice and the limited warranty and
// restricted rights notice below appear in all supporting
// documentation.
//
// AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS.
// AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF
// MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE. AUTODESK, INC.
// DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE
// UNINTERRUPTED OR ERROR FREE.
//
// Use, duplication, or disclosure by the U.S. Government is subject to
// restrictions set forth in FAR 52.227-19 (Commercial Computer
// Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii)
// (Rights in Technical Data and Computer Software), as applicable.
//
using System;
using System.Collections.Generic;
using System.Text;
using Autodesk.Revit.DB;
namespace Revit.SDK.Samples.CreateViewSection.CS
{
///
/// The helper class which give some operation about point and vector.
/// The point and vector are both presented by Autodesk.Revit.DB.XYZ structure.
///
public class XYZMath
{
// Private Members
const Double PRECISION = 0.0000000001; // Define a precision of double data
// Methods
///
/// Find the middle point of the line.
///
/// the start point of the line
/// the end point of the line
/// the middle point of the line
public static Autodesk.Revit.DB.XYZ FindMidPoint(Autodesk.Revit.DB.XYZ first, Autodesk.Revit.DB.XYZ second)
{
double x = (first.X + second.X) / 2;
double y = (first.Y + second.Y) / 2;
double z = (first.Z + second.Z) / 2;
Autodesk.Revit.DB.XYZ midPoint = new Autodesk.Revit.DB.XYZ (x, y, z);
return midPoint;
}
///
/// Find the distance between two points
///
/// the first point
/// the first point
/// the distance of two points
public static double FindDistance(Autodesk.Revit.DB.XYZ first, Autodesk.Revit.DB.XYZ second)
{
double x = first.X - second.X;
double y = first.Y - second.Y;
double z = first.Z - second.Z;
return Math.Sqrt(x * x + y * y + z * z);
}
///
/// Find the direction vector from first point to second point
///
/// the first point
/// the second point
/// the direction vector
public static Autodesk.Revit.DB.XYZ FindDirection(Autodesk.Revit.DB.XYZ first, Autodesk.Revit.DB.XYZ second)
{
double x = second.X - first.X;
double y = second.Y - first.Y;
double z = second.Z - first.Z;
double distance = FindDistance(first, second);
Autodesk.Revit.DB.XYZ direction = new Autodesk.Revit.DB.XYZ (x / distance, y / distance, z / distance);
return direction;
}
///
/// Find the right direction vector,
/// which is the same meaning of RightDirection property in View class
///
/// the view direction vector
/// the right direction vector
public static Autodesk.Revit.DB.XYZ FindRightDirection(Autodesk.Revit.DB.XYZ viewDirection)
{
// Because this example only allow the beam to be horizontal,
// the created viewSection should be vertical,
// the same thing can also be found when the user select wall or floor.
// So only need to turn 90 degree around Z axes will get Right Direction.
double x = -viewDirection.Y;
double y = viewDirection.X;
double z = viewDirection.Z;
Autodesk.Revit.DB.XYZ direction = new Autodesk.Revit.DB.XYZ (x, y, z);
return direction;
}
///
/// Find the up direction vector,
/// which is the same meaning of UpDirection property in View class
///
/// the view direction vector
/// the up direction vector
public static Autodesk.Revit.DB.XYZ FindUpDirection(Autodesk.Revit.DB.XYZ viewDirection)
{
// Because this example only allow the beam to be horizontal,
// the created viewSection should be vertical,
// the same thing can also be found when the user select wall or floor.
// So UpDirection should be z axes.
Autodesk.Revit.DB.XYZ direction = new Autodesk.Revit.DB.XYZ (0, 0, 1);
return direction;
}
///
/// Find the middle point of a profile.
/// This method is used to find out middle point of the selected wall or floor.
///
/// the array of curve which form the profile
/// the middle point of the profile
public static Autodesk.Revit.DB.XYZ FindMiddlePoint(CurveArray curveArray)
{
// First form a point array which include all the end points of the curves
List array = new List();
foreach (Curve curve in curveArray)
{
Autodesk.Revit.DB.XYZ first = curve.GetEndPoint(0);
Autodesk.Revit.DB.XYZ second = curve.GetEndPoint(1);
array.Add(first);
array.Add(second);
}
// Second find the max and min value of three coordinate
double maxX = array[0].X; // the max x coordinate in the array
double minX = array[0].X; // the min x coordinate in the array
double maxY = array[0].Y; // the max y coordinate in the array
double minY = array[0].Y; // the min y coordinate in the array
double maxZ = array[0].Z; // the max z coordinate in the array
double minZ = array[0].Z; // the min z coordinate in the array
foreach (Autodesk.Revit.DB.XYZ curve in array)
{
if (maxX < curve.X)
{
maxX = curve.X;
}
if (minX > curve.X)
{
minX = curve.X;
}
if (maxY < curve.Y)
{
maxY = curve.Y;
}
if (minY > curve.Y)
{
minY = curve.Y;
}
if (maxZ < curve.Z)
{
maxZ = curve.Z;
}
if (minZ > curve.Z)
{
minZ = curve.Z;
}
}
// Third form the middle point using the average of max and min values
double x = (maxX + minX) / 2;
double y = (maxY + minY) / 2;
double z = (maxZ + minZ) / 2;
Autodesk.Revit.DB.XYZ midPoint = new Autodesk.Revit.DB.XYZ (x, y, z);
return midPoint;
}
///
/// Find the view direction vector,
/// which is the same meaning of ViewDirection property in View class
///
/// the curve array which form wall's AnalyticalModel
/// the view direction vector
public static Autodesk.Revit.DB.XYZ FindWallViewDirection(CurveArray curveArray)
{
Autodesk.Revit.DB.XYZ direction = new Autodesk.Revit.DB.XYZ ();
foreach (Curve curve in curveArray)
{
Autodesk.Revit.DB.XYZ startPoint = curve.GetEndPoint(0);
Autodesk.Revit.DB.XYZ endPoint = curve.GetEndPoint(1);
double distanceX = startPoint.X - endPoint.X;
double distanceY = startPoint.Y - endPoint.Y;
if(-PRECISION > distanceX || PRECISION < distanceX
|| -PRECISION > distanceY || PRECISION < distanceY)
{
Autodesk.Revit.DB.XYZ first = new Autodesk.Revit.DB.XYZ (startPoint.X, startPoint.Y, 0);
Autodesk.Revit.DB.XYZ second = new Autodesk.Revit.DB.XYZ (endPoint.X, endPoint.Y, 0);
direction = FindDirection(first, second);
break;
}
}
return direction;
}
///
/// Find the view direction vector,
/// which is the same meaning of ViewDirection property in View class
///
/// the curve array which form floor's AnalyticalModel
/// the view direction vector
public static Autodesk.Revit.DB.XYZ FindFloorViewDirection(CurveArray curveArray)
{
// Because the floor is always on the level,
// so each curve can give the direction information.
Curve curve = curveArray.get_Item(0);
Autodesk.Revit.DB.XYZ first = curve.GetEndPoint(0);
Autodesk.Revit.DB.XYZ second = curve.GetEndPoint(1);
return FindDirection(first, second);
}
}
}