/// <summary> /// Returns the position of the tangent, in element's pixel space. /// </summary> /// <param name="keyFrame">Keyframe that the tangent belongs to.</param> /// <param name="type">Which tangent to retrieve the position for.</param> /// <returns>Position of the tangent, relative to the this GUI element's origin, in pixels.</returns> private Vector2I GetTangentPosition(KeyFrame keyFrame, TangentType type) { Vector2I position = CurveToPixelSpace(new Vector2(keyFrame.time, keyFrame.value)); Vector2 normal; if (type == TangentType.In) { normal = -EdAnimationCurve.TangentToNormal(keyFrame.inTangent); } else { normal = EdAnimationCurve.TangentToNormal(keyFrame.outTangent); } // X/Y ranges aren't scaled 1:1, adjust normal accordingly normal.x /= GetRange(); normal.y /= yRange; normal = Vector2.Normalize(normal); // Convert normal (in percentage) to pixel values Vector2I offset = new Vector2I((int)(normal.x * TANGENT_LINE_DISTANCE), (int)(-normal.y * TANGENT_LINE_DISTANCE)); return(position + offset); }
/// <summary> /// Returns the tangents between the active CircularArc3d instance complete circle and another one. /// </summary> /// <remarks> /// Tangents start points are on the object to which this method applies, end points on the one passed as argument. /// Tangents are always returned in the same order: outer tangents before inner tangents, and for both, /// the tangent on the left side of the line from this circular arc center to the other one before the one on the right side. /// </remarks> /// <param name="arc">The instance to which this method applies.</param> /// <param name="other">The CircularArc3d to which searched for tangents.</param> /// <param name="flags">An enum value specifying which type of tangent is returned.</param> /// <returns>An array of LineSegment3d representing the tangents (maybe 2 or 4) or null if there is none.</returns> /// <exception cref="Autodesk.AutoCAD.Runtime.Exception"> /// eNonCoplanarGeometry is thrown if the objects do not lies on the same plane.</exception> public static LineSegment3d[] GetTangentsTo(this CircularArc3d arc, CircularArc3d other, TangentType flags) { // check if circles lies on the same plane Vector3d normal = arc.Normal; Matrix3d WCS2OCS = Matrix3d.WorldToPlane(normal); double elevation = arc.Center.TransformBy(WCS2OCS).Z; if (!(normal.IsParallelTo(other.Normal) && Math.Abs(elevation - other.Center.TransformBy(WCS2OCS).Z) < Tolerance.Global.EqualPoint)) throw new Autodesk.AutoCAD.Runtime.Exception( Autodesk.AutoCAD.Runtime.ErrorStatus.NonCoplanarGeometry); Plane plane = new Plane(Point3d.Origin, normal); Matrix3d OCS2WCS = Matrix3d.PlaneToWorld(plane); CircularArc2d ca2d1 = new CircularArc2d(arc.Center.Convert2d(plane), arc.Radius); CircularArc2d ca2d2 = new CircularArc2d(other.Center.Convert2d(plane), other.Radius); LineSegment2d[] lines2d = ca2d1.GetTangentsTo(ca2d2, flags); if (lines2d == null) return null; LineSegment3d[] result = new LineSegment3d[lines2d.Length]; for (int i = 0; i < lines2d.Length; i++) { LineSegment2d ls2d = lines2d[i]; result[i] = new LineSegment3d(ls2d.StartPoint.Convert3d(normal, elevation), ls2d.EndPoint.Convert3d(normal, elevation)); } return result; }
public override void Read(BinaryStream bs) { BinaryReader Read = bs.Read; Magic = Read.String(5); Version = Read.UShort(); MeshUsage = Read.Byte(); Bounds = Read.Type <Box3>(); TangentType = (TangentType)Read.Byte(); TangentSplit = (Read.Byte() == 1); Vertices = bs.Read.TypeList <Vector3>(Read.Int()); if (Read.Int() != 0) { throw new Exception("uh oh, this mesh has vertex lod positions"); } Normals = Read.TypeList <Normal>(Read.Int()); TextureUVs = Read.TypeList <UV>(Read.Int()); NormalUVs = Read.TypeList <UV>(Read.Int()); Tangents = Read.TypeList <Tangent>(Read.Int()); VertexColors = Read.UIntList(Read.Int()); FaceIndex = Read.UIntList(Read.Int()); Faces = Read.TypeList <Face>(Read.Int()); Bones = Read.TypeList <Bone>(Read.Int()); Links = Read.TypeList <Link>(Read.Int()); BoneWeights = Read.TypeList <BoneWeight>(Read.Int()); Hardpoints = Read.TypeList <Hardpoint>(Read.Int()); int referenceMeshFileNameLength = Read.Int(); if (referenceMeshFileNameLength > 0) { ReferenceMeshFileName = Read.String(); } ReferenceMeshFileTime = Read.ULong(); ReferenceMeshType = (MeshType)Read.Byte(); BaseVariantDiffs = Read.TypeList <BaseVariantDiff>(Read.Int()); ConformWeights = Read.TypeList <ConformWeight>(Read.Int()); MaterialSections = Read.TypeList <MaterialSection>(Read.Int()); Console.WriteLine(Hardpoints.Count); }
/// <summary> /// Checks if the tangent should be displayed, depending on the active tangent mode. /// </summary> /// <param name="mode">Tangent mode for the keyframe.</param> /// <param name="type">Which tangent to check for.</param> /// <returns>True if the tangent should be displayed.</returns> private bool IsTangentDisplayed(TangentMode mode, TangentType type) { if (mode == TangentMode.Auto) { return(false); } else if (mode == TangentMode.Free) { return(true); } if (type == TangentType.In) { return(mode.HasFlag(TangentMode.InFree)); } else { return(mode.HasFlag(TangentMode.OutFree)); } }
/// <summary> /// Returns the tangents between the active CircularArc3d instance complete circle and another one. /// </summary> /// <remarks> /// Tangents start points are on the object to which this method applies, end points on the one passed as argument. /// Tangents are always returned in the same order: outer tangents before inner tangents, and for both, /// the tangent on the left side of the line from this circular arc center to the other one before the one on the right side. /// </remarks> /// <param name="arc">The instance to which this method applies.</param> /// <param name="other">The CircularArc3d to which searched for tangents.</param> /// <param name="flags">An enum value specifying which type of tangent is returned.</param> /// <returns>An array of LineSegment3d representing the tangents (maybe 2 or 4) or null if there is none.</returns> /// <exception cref="Autodesk.AutoCAD.Runtime.Exception"> /// eNonCoplanarGeometry is thrown if the objects do not lies on the same plane.</exception> public static LineSegment3d[]? GetTangentsTo( [NotNull] this CircularArc3d arc, [NotNull] CircularArc3d other, TangentType flags) { // check if circles lies on the same plane var normal = arc.Normal; var WCS2OCS = Matrix3d.WorldToPlane(normal); var elevation = arc.Center.TransformBy(WCS2OCS).Z; if (!(normal.IsParallelTo(other.Normal) && Math.Abs(elevation - other.Center.TransformBy(WCS2OCS).Z) < Tolerance.Global.EqualPoint)) { throw new Autodesk.AutoCAD.Runtime.Exception( Autodesk.AutoCAD.Runtime.ErrorStatus.NonCoplanarGeometry); } var plane = new Plane(Point3d.Origin, normal); var ca2d1 = new CircularArc2d(arc.Center.Convert2d(plane), arc.Radius); var ca2d2 = new CircularArc2d(other.Center.Convert2d(plane), other.Radius); var lines2d = ca2d1.GetTangentsTo(ca2d2, flags); if (lines2d == null) { return(null); } var result = new LineSegment3d[lines2d.Length]; for (var i = 0; i < lines2d.Length; i++) { var ls2d = lines2d[i]; result[i] = new LineSegment3d(ls2d.StartPoint.Convert3d(normal, elevation), ls2d.EndPoint.Convert3d(normal, elevation)); } return(result); }
public TangentRef(KeyframeRef keyframeRef, TangentType type) { this.keyframeRef = keyframeRef; this.type = type; }
public static LineSegment2d[] GetTangentsTo( [NotNull] this CircularArc2d arc, [NotNull] CircularArc2d other, TangentType flags) { // check if a circle is inside the other var dist = arc.Center.GetDistanceTo(other.Center); if (dist - Math.Abs(arc.Radius - other.Radius) <= Tolerance.Global.EqualPoint) { return(null); } // check if circles overlap var overlap = arc.Radius + other.Radius >= dist; if (overlap && flags == TangentType.Inner) { return(null); } CircularArc2d tmp1; Point2d[] inters; Vector2d vec1, vec2, vec = other.Center - arc.Center; int i, j; var result = new LineSegment2d[(int)flags == 3 && !overlap ? 4 : 2]; // outer tangents if ((flags & TangentType.Outer) > 0) { if (Math.Abs(arc.Radius - other.Radius) < 0.001) { var perp = new Line2d(arc.Center, vec.GetPerpendicularVector()); inters = arc.IntersectWith(perp); if (inters == null) { return(null); } vec1 = (inters[0] - arc.Center).GetNormal(); i = vec.X * vec1.Y - vec.Y - vec1.X > 0 ? 0 : 1; j = i ^ 1; result[i] = new LineSegment2d(inters[0], inters[0] + vec); result[j] = new LineSegment2d(inters[1], inters[1] + vec); } else { var center = arc.Radius < other.Radius ? other.Center : arc.Center; tmp1 = new CircularArc2d(center, Math.Abs(arc.Radius - other.Radius)); var tmp2 = new CircularArc2d(arc.Center + vec / 2.0, dist / 2.0); inters = tmp1.IntersectWith(tmp2); if (inters == null) { return(null); } vec1 = (inters[0] - center).GetNormal(); vec2 = (inters[1] - center).GetNormal(); i = vec.X * vec1.Y - vec.Y - vec1.X > 0 ? 0 : 1; j = i ^ 1; result[i] = new LineSegment2d(arc.Center + vec1 * arc.Radius, other.Center + vec1 * other.Radius); result[j] = new LineSegment2d(arc.Center + vec2 * arc.Radius, other.Center + vec2 * other.Radius); } } // inner tangents if ((flags & TangentType.Inner) > 0 && !overlap) { var ratio = arc.Radius / (arc.Radius + other.Radius) / 2.0; tmp1 = new CircularArc2d(arc.Center + vec * ratio, dist * ratio); inters = arc.IntersectWith(tmp1); if (inters == null) { return(null); } vec1 = (inters[0] - arc.Center).GetNormal(); vec2 = (inters[1] - arc.Center).GetNormal(); i = vec.X * vec1.Y - vec.Y - vec1.X > 0 ? 2 : 3; j = i == 2 ? 3 : 2; result[i] = new LineSegment2d(arc.Center + vec1 * arc.Radius, other.Center + vec1.Negate() * other.Radius); result[j] = new LineSegment2d(arc.Center + vec2 * arc.Radius, other.Center + vec2.Negate() * other.Radius); } return(result); }
/// <summary> /// Returns the tangents between the active CircularArc2d instance complete circle and another one. /// </summary> /// <remarks> /// Tangents start points are on the object to which this method applies, end points on the one passed as argument. /// Tangents are always returned in the same order: outer tangents before inner tangents, and for both, /// the tangent on the left side of the line from this circular arc center to the other one before the other one. /// </remarks> /// <param name="arc">The instance to which this method applies.</param> /// <param name="other">The CircularArc2d to which searched for tangents.</param> /// <param name="flags">An enum value specifying which type of tangent is returned.</param> /// <returns>An array of LineSegment2d representing the tangents (maybe 2 or 4) or null if there is none.</returns> public static LineSegment2d[] GetTangentsTo(this CircularArc2d arc, CircularArc2d other, TangentType flags) { // check if a circle is inside the other double dist = arc.Center.GetDistanceTo(other.Center); if (dist - Math.Abs(arc.Radius - other.Radius) <= Tolerance.Global.EqualPoint) return null; // check if circles overlap bool overlap = arc.Radius + other.Radius >= dist; if (overlap && flags == TangentType.Inner) return null; CircularArc2d tmp1, tmp2; Point2d[] inters; Vector2d vec1, vec2, vec = other.Center - arc.Center; int i, j; LineSegment2d[] result = new LineSegment2d[(int)flags == 3 && !overlap ? 4 : 2]; // outer tangents if ((flags & TangentType.Outer) > 0) { if (arc.Radius == other.Radius) { Line2d perp = new Line2d(arc.Center, vec.GetPerpendicularVector()); inters = arc.IntersectWith(perp); if (inters == null) return null; vec1 = (inters[0] - arc.Center).GetNormal(); vec2 = (inters[1] - arc.Center).GetNormal(); i = vec.X * vec1.Y - vec.Y - vec1.X > 0 ? 0 : 1; j = i ^ 1; result[i] = new LineSegment2d(inters[0], inters[0] + vec); result[j] = new LineSegment2d(inters[1], inters[1] + vec); } else { Point2d center = arc.Radius < other.Radius ? other.Center : arc.Center; tmp1 = new CircularArc2d(center, Math.Abs(arc.Radius - other.Radius)); tmp2 = new CircularArc2d(arc.Center + vec / 2.0, dist / 2.0); inters = tmp1.IntersectWith(tmp2); if (inters == null) return null; vec1 = (inters[0] - center).GetNormal(); vec2 = (inters[1] - center).GetNormal(); i = vec.X * vec1.Y - vec.Y - vec1.X > 0 ? 0 : 1; j = i ^ 1; result[i] = new LineSegment2d(arc.Center + vec1 * arc.Radius, other.Center + vec1 * other.Radius); result[j] = new LineSegment2d(arc.Center + vec2 * arc.Radius, other.Center + vec2 * other.Radius); } } // inner tangents if ((flags & TangentType.Inner) > 0 && !overlap) { double ratio = (arc.Radius / (arc.Radius + other.Radius)) / 2.0; tmp1 = new CircularArc2d(arc.Center + vec * ratio, dist * ratio); inters = arc.IntersectWith(tmp1); if (inters == null) return null; vec1 = (inters[0] - arc.Center).GetNormal(); vec2 = (inters[1] - arc.Center).GetNormal(); i = vec.X * vec1.Y - vec.Y - vec1.X > 0 ? 2 : 3; j = i == 2 ? 3 : 2; result[i] = new LineSegment2d(arc.Center + vec1 * arc.Radius, other.Center + vec1.Negate() * other.Radius); result[j] = new LineSegment2d(arc.Center + vec2 * arc.Radius, other.Center + vec2.Negate() * other.Radius); } return result; }
/// <summary> /// Returns the tangents between the active CircularArc3d instance complete circle and another one. /// </summary> /// <remarks> /// Tangents start points are on the object to which this method applies, end points on the one passed as argument. /// Tangents are always returned in the same order: outer tangents before inner tangents, and for both, /// the tangent on the left side of the line from this circular arc center to the other one before the one on the right /// side. /// </remarks> /// <param name="arc">The instance to which this method applies.</param> /// <param name="other">The CircularArc3d to which searched for tangents.</param> /// <param name="flags">An enum value specifying which type of tangent is returned.</param> /// <returns>An array of LineSegment3d representing the tangents (maybe 2 or 4) or null if there is none.</returns> /// <exception cref="Autodesk.AutoCAD.Runtime.Exception"> /// eNonCoplanarGeometry is thrown if the objects do not lies on the same plane. /// </exception> public static LineSegment3d[] GetTangentsTo(this CircularArc3d arc, CircularArc3d other, TangentType flags) { // check if circles lies on the same plane var normal = arc.Normal; var wcs2Ocs = Matrix3d.WorldToPlane(normal); var elevation = arc.Center.TransformBy(wcs2Ocs).Z; if (!(normal.IsParallelTo(other.Normal) && Math.Abs(elevation - other.Center.TransformBy(wcs2Ocs).Z) < Tolerance.Global.EqualPoint)) { throw new Exception( ErrorStatus.NonCoplanarGeometry); } var plane = new Plane(Point3d.Origin, normal); _ = Matrix3d.PlaneToWorld(plane); var ca2D1 = new CircularArc2d(arc.Center.Convert2d(plane), arc.Radius); var ca2D2 = new CircularArc2d(other.Center.Convert2d(plane), other.Radius); var lines2D = ca2D1.GetTangentsTo(ca2D2, flags); if (lines2D == null) { return(null); } var result = new LineSegment3d[lines2D.Length]; for (var i = 0; i < lines2D.Length; i++) { var ls2D = lines2D[i]; result[i] = new LineSegment3d(ls2D.StartPoint.Convert3D(normal, elevation), ls2D.EndPoint.Convert3D(normal, elevation)); } return(result); }
/// <summary> /// Checks if the tangent should be displayed, depending on the active tangent mode. /// </summary> /// <param name="mode">Tangent mode for the keyframe.</param> /// <param name="type">Which tangent to check for.</param> /// <returns>True if the tangent should be displayed.</returns> private bool IsTangentDisplayed(TangentMode mode, TangentType type) { if (mode == TangentMode.Auto) return false; else if (mode == TangentMode.Free) return true; if (type == TangentType.In) return mode.HasFlag(TangentMode.InFree); else return mode.HasFlag(TangentMode.OutFree); }
/// <summary> /// Returns the position of the tangent, in element's pixel space. /// </summary> /// <param name="keyFrame">Keyframe that the tangent belongs to.</param> /// <param name="type">Which tangent to retrieve the position for.</param> /// <returns>Position of the tangent, relative to the this GUI element's origin, in pixels.</returns> private Vector2I GetTangentPosition(KeyFrame keyFrame, TangentType type) { Vector2I position = CurveToPixelSpace(new Vector2(keyFrame.time, keyFrame.value)); Vector2 normal; if (type == TangentType.In) normal = -EdAnimationCurve.TangentToNormal(keyFrame.inTangent); else normal = EdAnimationCurve.TangentToNormal(keyFrame.outTangent); // X/Y ranges aren't scaled 1:1, adjust normal accordingly normal.x /= GetRange(); normal.y /= yRange; normal = Vector2.Normalize(normal); // Convert normal (in percentage) to pixel values Vector2I offset = new Vector2I((int)(normal.x * TANGENT_LINE_DISTANCE), (int)(-normal.y * TANGENT_LINE_DISTANCE)); return position + offset; }