public virtual Angle SmallestAngleBetween(ILinear line) { var angle = this.NormalVector.SmallestAngleBetween(line); var complement = Unit.RightAngle - angle; return(complement.ProperAngle()); }
/// <summary> /// Projects the point onto the line. /// </summary> public Point ProjectOntoLine(ILinear projectOnto) { var vector = this - projectOnto.BasePoint; var scalarProjection = vector.ScalarProjection(projectOnto.Direction); return(projectOnto.GetPointAlongLine(scalarProjection)); }
private static double[,] GetMatrix(ILinear axis, Angle angle) { var rotationUnitVector = axis.Direction; double unitX = rotationUnitVector.X; double unitY = rotationUnitVector.Y; double unitZ = rotationUnitVector.Z; Angle theta = angle; double sinTheta = Sine(theta); double cosTheta = Cosine(theta); double entry00 = cosTheta + unitX * unitX * (1 - cosTheta); double entry01 = unitX * unitY * (1 - cosTheta) - unitZ * sinTheta; double entry02 = unitX * unitZ * (1 - cosTheta) + unitY * sinTheta; double entry10 = unitY * unitX * (1 - cosTheta) + unitZ * sinTheta; double entry11 = cosTheta + unitY * unitY * (1 - cosTheta); double entry12 = unitY * unitZ * (1 - cosTheta) - unitX * sinTheta; double entry20 = unitZ * unitX * (1 - cosTheta) - unitY * sinTheta; double entry21 = unitZ * unitY * (1 - cosTheta) + unitX * sinTheta; double entry22 = cosTheta + unitZ * unitZ * (1 - cosTheta); var matrix = new double[, ] { { entry00, entry01, entry02, 0 }, { entry10, entry11, entry12, 0 }, { entry20, entry21, entry22, 0 }, { 0, 0, 0, 1 }, }; matrix.ConjugateByTranslation(axis.BasePoint.VectorFromOrigin); return(matrix); }
public static Plane FromCoplanarLines(ILinear linear1, ILinear linear2) { var line1 = new Line(linear1); var line2 = new Line(linear2); var normal = Normal(); return(new Plane(line1.BasePoint, normal)); Direction Normal() { if (line1 == line2) { throw new ArgumentException("The passed lines cannot be the same."); } if (line1.IsParallelTo(line2)) { var directionBetween = line1.BasePoint.DirectionTo(line2.BasePoint); return(line1.Direction.CrossProduct(directionBetween)); } if (line1.IsCoplanarWith(line2)) { return(line1.Direction.CrossProduct(line2.Direction)); } throw new ArgumentException("The passed lines are not on the same plane."); } }
/// <summary> /// Returns true if the passed line is in the same plane as this one, AKA if it intersects or is parallel to the other line /// </summary> /// <param name="passedLine"></param> /// <returns></returns> public static bool IsCoplanarWith(this ILinear thisLine, ILinear otherLine) { if (thisLine.BasePoint.Z == otherLine.BasePoint.Z && thisLine.Direction.Z < 0.01 && otherLine.Direction.Z < 0.01) { return(true); } var point1Line1 = new[] { thisLine.BasePoint.X.InInches(), thisLine.BasePoint.Y.InInches(), thisLine.BasePoint.Z.InInches() }; var anotherPointOnLine1 = thisLine.GetPointAlongLine(1 * Unit.Inches); var point2Line1 = new [] { anotherPointOnLine1.X.InInches(), anotherPointOnLine1.Y.InInches(), anotherPointOnLine1.Z.InInches() }; var point1Line2 = new [] { otherLine.BasePoint.X.InInches(), otherLine.BasePoint.Y.InInches(), otherLine.BasePoint.Z.InInches() }; var anotherPointOnLine2 = otherLine.GetPointAlongLine(2 * Unit.Inches); var point2Line2 = new [] { anotherPointOnLine2.X.InInches(), anotherPointOnLine2.Y.InInches(), anotherPointOnLine2.Z.InInches() }; var pointsMatrix = new double[4, 4]; pointsMatrix.SetRow(0, point1Line1); pointsMatrix.SetRow(1, point2Line1); pointsMatrix.SetRow(2, point1Line2); pointsMatrix.SetRow(3, point2Line2); pointsMatrix.SetColumn(3, new double[] { 1, 1, 1, 1 }); var determinant = Math.Abs(pointsMatrix.Determinant()); // Tolerance is suspect given that the determinant has dimensions of (in.^4) return(determinant * Unit.Inches == Unit.ZeroDistance); }
public static Point GetPointAlongLine(this ILinear thisLine, Distance distance) { Distance newX = thisLine.BasePoint.X + distance * thisLine.Direction.X; Distance newY = thisLine.BasePoint.Y + distance * thisLine.Direction.Y; Distance newZ = thisLine.BasePoint.Z + distance * thisLine.Direction.Z; return(new Point(newX, newY, newZ)); }
public static Angle CounterClockwiseAngleTo(this ILinear thisLine, ILinear otherLine, ILinear referenceNormal = null) { if (referenceNormal == null) { referenceNormal = Line.ZAxis; } return(thisLine.Direction.CounterClockwiseAngleTo(otherLine.Direction, referenceNormal.Direction)); }
/// <summary> /// Makes a Perpendicular Line to this line that is in the passed plane with the same base point as this line /// this assumes the line is in the plane /// </summary> public static Line MakePerpendicularLineInGivenPlane(this ILinear thisLine, Plane planeToMakePerpendicularLineIn) { if (planeToMakePerpendicularLineIn.IsParallelTo(thisLine)) { //rotate it 90 degrees in the nornal of the plane and it will be perpendicular to the original return(new Line(thisLine).Rotate(new Rotation(new Vector(thisLine.BasePoint, planeToMakePerpendicularLineIn.NormalVector), Unit.RightAngle))); } else { throw new ArgumentException("The given line is not in the given plane"); } }
private static (double DistanceAlongLine1, double DistanceAlongLine2) DistanceAlongEachLineOfClosestApproach ( ILinear line1, ILinear line2 ) { var d1 = line1.Direction.Normalized; var d2 = line2.Direction.Normalized; var d1_cross_d2 = d1.CrossProduct(d2); var o2_minus_o1 = (line2.BasePoint - line1.BasePoint).ToVectorInInches(); var normSquared = d1_cross_d2.NormSquared(); var sharedCrossProduct = d1_cross_d2.CrossProduct(o2_minus_o1); var t1 = d2.DotProduct(sharedCrossProduct) / normSquared; var t2 = d1.DotProduct(sharedCrossProduct) / normSquared; return(t1, t2); }
public Rotation(ILinear axisOfRotation, Angle rotationAngle) : this(GetMatrix(axisOfRotation, rotationAngle)) { }
// public /// <summary> /// Determines whether or not the two lines are perpindicular to each other, up to a given tolerance. /// </summary> /// <returns></returns> public static bool IsPerpendicularTo(ILinear thisLine, ILinear otherLine, Angle tolerance) { var angle = thisLine.SmallestAngleBetween(otherLine); return(angle.EqualsWithinTolerance(Unit.RightAngle, tolerance)); }
public Distance SignedDistanceAlong(ILinear line) => new Line(line).Contains(this) ? ProjectedSignedDistanceAlong(line) : throw new ArgumentOutOfRangeException(nameof(line), "The point should be on the line");
/// <summary> /// Sorts out and returns only the lines in this list that are parallel to the passed Line /// </summary> /// <param name="passedLines">passed List of Lines</param> /// <param name="lineToCheckIfParallelTo">passed List of Lines</param> /// <returns>returns a List of Lines of only the Lines that are parallel to the passed line</returns> public static List <Line> OnlyLinesParallelTo(this IList <Line> passedLines, ILinear lineToCheckIfParallelTo) { return(passedLines.Where(l => l.IsParallelTo(lineToCheckIfParallelTo)).ToList()); }
/// <summary> /// Default copy constructor /// </summary> public Line(ILinear toCopy) : this(toCopy.Direction, toCopy.BasePoint) { }
/// <summary> /// Returns the smaller of the two angles between these lines. /// </summary> public static Angle SmallestAngleBetween(this ILinear thisLine, ILinear otherLine) { return(thisLine.Direction.SmallestAngleBetween(otherLine.Direction)); }
public static Line AsLine(this ILinear linear) => new Line(linear);
public static Plane PlaneThroughLineInDirectionOf(this ILinear thisLine, Direction direction) { return(Plane.FromCoplanarLines(thisLine, new Line(thisLine.BasePoint, direction))); }
public Rotation(Angle rotationAngle, ILinear axisOfRotation = null) : this(GetMatrix(axisOfRotation ?? Line.ZAxis, rotationAngle)) { }
protected static void InterpolateAttributeMaps <KeyType>( AttributeMapCollection <KeyType> original, AttributeMapCollection <KeyType> clone, Dictionary <KeyType, List <KeyValuePair <float, KeyType> > > keyNewToOlds ) { /* For all original attribute maps */ foreach (KeyValuePair <string, object> kvp in original.AttributeMaps) { string mapName = kvp.Key; object oldMap = kvp.Value; // real type is Dictionary<KeyType, ValueType> object newMap; Type mapValueType = oldMap.GetType().GetGenericArguments()[1]; if (mapName == "corner_indices") { continue; } Type mapKeyType = oldMap.GetType().GetGenericArguments()[0]; #if false Debug.WriteLine("Attribute map name : " + mapName); Debug.WriteLine("Attribute map key type : " + mapKeyType.ToString()); Debug.WriteLine("Attribute map value type : " + mapValueType.ToString()); #endif if (clone.AttributeMaps.ContainsKey(mapName) == true) { //Debug.WriteLine("!"); } newMap = System.Activator.CreateInstance(oldMap.GetType()); clone.AttributeMaps[mapName] = newMap; IDictionary oldMapDictionary = (IDictionary)oldMap; IDictionary newMapDictionary = (IDictionary)newMap; #if false Debug.WriteLine("Attribute map count : " + oldMapDictionary.Count); #endif /* For each new object in keyNewToOlds.Keys */ foreach (var kvp2 in keyNewToOlds) { KeyType newKey = kvp2.Key; List <KeyValuePair <float, KeyType> > oldKeys = kvp2.Value; // Compute sum of weights, for normalizing float sumWeights = 0.0f; foreach (var kvp3 in oldKeys) { KeyType oldKey = kvp3.Value; if (oldMapDictionary.Contains(oldKey)) { sumWeights += kvp3.Key; } } if (sumWeights == 0.0f) { continue; } object newValue = System.Activator.CreateInstance(mapValueType); if (newValue is ILinear) { ILinear newLinearValue = (ILinear)newValue; foreach (var kvp3 in oldKeys) { float weight = kvp3.Key; KeyType oldKey = kvp3.Value; object oldValue; if (oldMapDictionary.Contains(oldKey)) { oldValue = oldMapDictionary[oldKey]; // TODO MUSTIFIX oldValue = null ILinear oldLinearValue = (ILinear)oldValue; newLinearValue.PlusWeightTimesOther(weight / sumWeights, oldLinearValue); } else { oldValue = null; } } newMapDictionary[newKey] = newLinearValue; } else if (newValue is float) { float newFloatValue = (float)newValue; foreach (var kvp3 in oldKeys) { float weight = kvp3.Key; KeyType oldKey = kvp3.Value; if (oldMapDictionary.Contains(oldKey)) { object oldValue = oldMapDictionary[oldKey]; float oldFloatValue = (float)oldValue; newFloatValue += (weight / sumWeights) * oldFloatValue; } else { //Debug.WriteLine("!"); } } newMapDictionary[newKey] = newFloatValue; } else { //Debug.WriteLine("!"); } } } }
/// <summary> /// Creates a Plane that contains the passed point and line. /// Note: The point should not lie on the line. /// </summary> public static Plane FromPointAndLine(Point point1, ILinear linear) { return(Plane.FromCoplanarLines(new Line(point1, linear.BasePoint), linear)); }
/// <summary> /// Creates a new line with the same direction but different base /// Useful for turning vectors, and segments back into lines. /// </summary> public Line(Point newBasePoint, ILinear line) : this(line.Direction, newBasePoint) { }
/// <summary> /// Returns whether or not the giving line is perpendicular to this plane /// </summary> /// <param name="passedLine"></param> /// <returns></returns> public bool IsPerpendicularTo(ILinear passedLine) { //check to see if it is parallel to the normal vector and if it is then it is perpendicular to the plane because the plane is //by definition perpendicular to the normal return(this.NormalVector.IsParallelTo(passedLine)); }
public ILinear PlusWeightTimesOther(float weight, ILinear other) { this += weight * (Vector4)other; return(this); }
protected override IList <object> Pick(MouseEventArgs e) { bool multiSelect = DragOverThreshold; List <object> paths = new List <object>(); HitRecord[] hits; if (multiSelect) {// frustum pick RectangleF rect = MakeRect(FirstMousePoint, CurrentMousePoint); hits = GameEngine.FrustumPick(SurfaceId, Camera.ViewMatrix, Camera.ProjectionMatrix, rect); } else {// ray pick Ray3F rayW = GetWorldRay(CurrentMousePoint); hits = GameEngine.RayPick(Camera.ViewMatrix, Camera.ProjectionMatrix, rayW, false); } // create unique list of hits HashSet <ulong> instanceSet = new HashSet <ulong>(); List <HitRecord> uniqueHits = new List <HitRecord>(); // build 'path' objects for each hit record. foreach (HitRecord hit in hits) { bool added = instanceSet.Add(hit.instanceId); if (added) { uniqueHits.Add(hit); } } HitRecord firstHit = new HitRecord(); // build 'path' objects for each hit record. foreach (HitRecord hit in uniqueHits) { NativeObjectAdapter nobj = GameEngine.GetAdapterFromId(hit.instanceId); DomNode dom = nobj.DomNode; object hitPath = Util.AdaptDomPath(dom); object obj = DesignView.PickFilter.Filter(hitPath, e); if (obj != null) { if (paths.Count == 0) { firstHit = hit; } var newPath = obj as AdaptablePath <object> ?? Util.AdaptDomPath((DomNode)obj); paths.Add(newPath); } } if (multiSelect == false && paths.Count > 0) { var path = paths[0]; ISelectionContext selection = DesignView.Context.As <ISelectionContext>(); ILinear linear = path.As <ILinear>(); if (linear != null && Control.ModifierKeys == System.Windows.Forms.Keys.Shift && selection.SelectionContains(path)) { ITransactionContext trans = DesignView.Context.As <ITransactionContext>(); trans.DoTransaction( delegate { linear.InsertPoint(firstHit.index, firstHit.hitPt.X, firstHit.hitPt.Y, firstHit.hitPt.Z); }, "insert control point".Localize() ); } } return(paths); }
public Distance ProjectedSignedDistanceAlong(ILinear line) { var basePoint = line.BasePoint; return((this - basePoint).ScalarProjection(line.Direction)); }
/// <summary> /// Determines if two lines are parallel up to a custom angular tolerance. /// That is, if the lines are within that angle of each other the lines are considered "parallel" /// </summary> public static bool IsParallelTo(this ILinear thisLine, ILinear otherLine, Angle tolerance) { var angle = thisLine.SmallestAngleBetween(otherLine); return(angle.EqualsWithinTolerance(Unit.ZeroAngle, tolerance)); }
public Plane(ILinear normal) { this.NormalLine = new Line(normal); }
/// <summary> /// Returns whether or not the two lines are perpendicular to each other /// </summary> /// <param name="passedLine"></param> /// <returns></returns> public static bool IsPerpendicularTo([NotNull] this ILinear thisLine, [NotNull] ILinear otherLine) { return(thisLine.SmallestAngleBetween(otherLine) == Unit.RightAngle); }
protected override IList <object> Pick(MouseEventArgs e) { bool multiSelect = DragOverThreshold; List <object> paths = new List <object>(); Picking.HitRecord[] hits; if (multiSelect) {// frustum pick RectangleF rect = MakeRect(FirstMousePoint, CurrentMousePoint); var frustum = XLEBridgeUtils.Utils.MakeFrustumMatrix(Utils.AsCameraDesc(Camera), rect, ClientSize); hits = Picking.FrustumPick( GameEngine.GetEngineDevice(), Adapter.SceneManager, Adapter.TechniqueContext, frustum, Utils.AsCameraDesc(Camera), ClientSize, Picking.Flags.Objects | Picking.Flags.Helpers); } else {// ray pick Ray3F rayW = GetWorldRay(CurrentMousePoint); hits = Picking.RayPick( GameEngine.GetEngineDevice(), Adapter.SceneManager, Adapter.TechniqueContext, rayW, Utils.AsCameraDesc(Camera), ClientSize, Picking.Flags.Terrain | Picking.Flags.Objects | Picking.Flags.Helpers); } if (hits == null) { return(new List <object>()); } // create unique list of hits HashSet <ulong> instanceSet = new HashSet <ulong>(); var uniqueHits = new List <Picking.HitRecord>(); // build 'path' objects for each hit record. foreach (var hit in hits) { bool added = instanceSet.Add(hit.instanceId); if (added) { uniqueHits.Add(hit); } } var firstHit = new Picking.HitRecord(); // build 'path' objects for each hit record. foreach (var hit in uniqueHits) { var nativeIdMapping = Globals.MEFContainer.GetExportedValue <INativeIdMapping>(); var nobj = nativeIdMapping.GetAdapter(hit.documentId, hit.instanceId).As <DomNodeAdapter>(); if (nobj == null) { continue; } DomNode dom = nobj.DomNode; object hitPath = Util.AdaptDomPath(dom); object obj = DesignView.PickFilter.Filter(hitPath, e); if (obj != null) { if (paths.Count == 0) { firstHit = hit; } var newPath = obj as AdaptablePath <object> ?? Util.AdaptDomPath((DomNode)obj); paths.Add(newPath); } } if (multiSelect == false && paths.Count > 0) { var path = paths[0]; ISelectionContext selection = DesignView.Context.As <ISelectionContext>(); ILinear linear = path.As <ILinear>(); if (linear != null && Control.ModifierKeys == System.Windows.Forms.Keys.Shift && selection.SelectionContains(path)) { ITransactionContext trans = DesignView.Context.As <ITransactionContext>(); trans.DoTransaction( delegate { linear.InsertPoint(firstHit.index, firstHit.hitPt.X, firstHit.hitPt.Y, firstHit.hitPt.Z); }, "insert control point".Localize() ); } } return(paths); }
public Vector OrthogonalProjection(ILinear line) { return(ProjectOntoPlane(new Plane(line))); }