From 86e110472216beb2394daf646ed6f4e2353c5fb6 Mon Sep 17 00:00:00 2001 From: kike-garbo Date: Tue, 3 Sep 2024 21:45:59 +0200 Subject: [PATCH 1/5] Implemented `Arithmetic.MinMagnitude` and `Arithmetic.MaxMagnitude`. --- src/RhinoInside.Revit.External/Numerical.cs | 98 ++++++++++++++++--- .../Components/Views/Extents.cs | 8 +- .../Types/Views/ViewFrame.cs | 12 +-- .../Convert/Units/UnitScale.cs | 8 +- 4 files changed, 97 insertions(+), 29 deletions(-) diff --git a/src/RhinoInside.Revit.External/Numerical.cs b/src/RhinoInside.Revit.External/Numerical.cs index 9dc80d5c3..580e65fbe 100644 --- a/src/RhinoInside.Revit.External/Numerical.cs +++ b/src/RhinoInside.Revit.External/Numerical.cs @@ -121,6 +121,37 @@ internal static double Magnitude(double value) { return Math.Abs(value); } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double MinMagnitude(double x, double y) + { +#if NET5_0_OR_GREATER + return Math.MinMagnitude(x, y); +#else + double ax = Math.Abs(x); + double ay = Math.Abs(y); + + return ax < ay ? x : + ax == ay ? (IsNegativeZero(x) ? -0.0 : y) : + double.IsNaN(ax) ? x : y; + +#endif + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double MaxMagnitude(double x, double y) + { +#if NET5_0_OR_GREATER + return Math.MaxMagnitude(x, y); +#else + double ax = Math.Abs(x); + double ay = Math.Abs(y); + + return ax > ay ? x : + ax == ay ? (IsPositiveZero(x) ? +0.0 : y) : + double.IsNaN(ax) ? x : y; +#endif + } #endregion #region Interval @@ -131,12 +162,10 @@ internal static double Magnitude(double value) /// The value to compare with . /// if is less than ; otherwise /// - /// This requires inputs to not be propagated back to the caller and for -0.0 to be treated as less than +0.0. + /// This requires inputs to be propagated back to the caller and for -0.0 to be treated as less than +0.0. /// - public static double Min(double x, double y) => - x < y ? x : - x == y ? (IsNegativeZero(x) ? -0.0 : y) : - double.IsNaN(y) ? x : y ; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double Min(double x, double y) => Math.Min(x, y); /// /// Computes the max point of the interval [, ]. @@ -145,12 +174,10 @@ public static double Min(double x, double y) => /// The value to compare with . /// if is grater than ; otherwise /// - /// This requires inputs to not be propagated back to the caller and for -0.0 to be treated as less than +0.0. + /// This requires inputs to be propagated back to the caller and for -0.0 to be treated as less than +0.0. /// - public static double Max(double x, double y) => - x > y ? x : - x == y ? (IsPositiveZero(x) ? +0.0 : y) : - double.IsNaN(y) ? x : y ; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double Max(double x, double y) => Math.Max(x, y); /// /// Computes the mean point of the interval [, ]. @@ -165,17 +192,17 @@ public static double Mean(double x, double y) { if (x == y) return x; - var X = Math.Abs(x); - var Y = Math.Abs(y); + var ax = Math.Abs(x); + var ay = Math.Abs(y); //// Avoids oveflow - //if (X <= double.MaxValue / 2 && Y <= double.MaxValue / 2) + //if (ax <= double.MaxValue * 0.5 && ay <= double.MaxValue * 0.5) // return (x + y) * 0.5; - if (X < Constant.Upsilon) + if (ax < Constant.Upsilon) return x + (y * 0.5); - if (Y < Constant.Upsilon) + if (ay < Constant.Upsilon) return (x * 0.5) + y; return (x * 0.5) + (y * 0.5); @@ -227,11 +254,52 @@ public static double Mix(double x, double y, double t) /// The lower bound of the result. /// The upper bound of the result. /// Clamped or if equals . + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static double Clamp(double value, double min, double max) { return value < min ? min : max < value ? max : value; } #endregion + + #region Number + /// + /// Computes the min point of the interval [, ]. + /// + /// The value to compare with . + /// The value to compare with . + /// if is less than ; otherwise + /// + /// This requires inputs to not be propagated back to the caller and for -0.0 to be treated as less than +0.0. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double MinNumber(double x, double y) => +#if NET5_0_OR_GREATER + double.MinNumber(x, y); +#else + x < y ? x : + x == y ? (IsNegativeZero(x) ? -0.0 : y) : + double.IsNaN(y) ? x : y ; +#endif + + /// + /// Computes the max point of the interval [, ]. + /// + /// The value to compare with . + /// The value to compare with . + /// if is grater than ; otherwise + /// + /// This requires inputs to not be propagated back to the caller and for -0.0 to be treated as less than +0.0. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double MaxNumber(double x, double y) => +#if NET5_0_OR_GREATER + double.MaxNumber(x, y); +#else + x > y ? x : + x == y ? (IsPositiveZero(x) ? +0.0 : y) : + double.IsNaN(y) ? x : y ; +#endif + #endregion } /// diff --git a/src/RhinoInside.Revit.GH/Components/Views/Extents.cs b/src/RhinoInside.Revit.GH/Components/Views/Extents.cs index 57ee54a56..cc9e06ad3 100644 --- a/src/RhinoInside.Revit.GH/Components/Views/Extents.cs +++ b/src/RhinoInside.Revit.GH/Components/Views/Extents.cs @@ -237,17 +237,17 @@ static void GetViewRangeOffsets(ARDB.View view, out double backOffset, out doubl { case ARDB.View3D view3D: if (view3D.IsPerspective) - frontOffset = Arithmetic.Min(frontOffset, view3D.CropBox.Max.Z); + frontOffset = Arithmetic.MinNumber(frontOffset, view3D.CropBox.Max.Z); break; case ARDB.ViewPlan viewPlan: var interval = viewPlan.GetViewRangeInterval(); - backOffset = Arithmetic.Max(backOffset, interval.Left.Bound - view.Origin.Z); - frontOffset = Arithmetic.Min(frontOffset, interval.Right.Bound - view.Origin.Z); + backOffset = Arithmetic.MaxNumber(backOffset, interval.Left.Bound - view.Origin.Z); + frontOffset = Arithmetic.MinNumber(frontOffset, interval.Right.Bound - view.Origin.Z); break; case ARDB.ViewSection viewSection: - frontOffset = Arithmetic.Min(frontOffset, viewSection.CropBox.Max.Z); + frontOffset = Arithmetic.MinNumber(frontOffset, viewSection.CropBox.Max.Z); break; } } diff --git a/src/RhinoInside.Revit.GH/Types/Views/ViewFrame.cs b/src/RhinoInside.Revit.GH/Types/Views/ViewFrame.cs index b59598c14..0698b0c72 100644 --- a/src/RhinoInside.Revit.GH/Types/Views/ViewFrame.cs +++ b/src/RhinoInside.Revit.GH/Types/Views/ViewFrame.cs @@ -436,16 +436,16 @@ public override bool CastTo(ref Q target) public Point3d Min => new Point3d ( - Arithmetic.Min( Value.FrustumLeft, Bound[AxisX].T0), - Arithmetic.Min( Value.FrustumBottom, Bound[AxisY].T0), - Arithmetic.Min(-Value.FrustumFar, Bound[AxisZ].T0) + Arithmetic.MinNumber( Value.FrustumLeft, Bound[AxisX].T0), + Arithmetic.MinNumber( Value.FrustumBottom, Bound[AxisY].T0), + Arithmetic.MinNumber(-Value.FrustumFar, Bound[AxisZ].T0) ); public Point3d Max => new Point3d ( - Arithmetic.Max( Value.FrustumRight, Bound[AxisX].T1), - Arithmetic.Max( Value.FrustumTop, Bound[AxisY].T1), - Arithmetic.Max(-Value.FrustumNear, Bound[AxisZ].T1) + Arithmetic.MaxNumber( Value.FrustumRight, Bound[AxisX].T1), + Arithmetic.MaxNumber( Value.FrustumTop, Bound[AxisY].T1), + Arithmetic.MaxNumber(-Value.FrustumNear, Bound[AxisZ].T1) ); internal ARDB.BoundingBoxXYZ ToBoundingBoxXYZ(bool ensurePositiveY = false) diff --git a/src/RhinoInside.Revit/Convert/Units/UnitScale.cs b/src/RhinoInside.Revit/Convert/Units/UnitScale.cs index 4d77ea6c5..a426dcd0b 100644 --- a/src/RhinoInside.Revit/Convert/Units/UnitScale.cs +++ b/src/RhinoInside.Revit/Convert/Units/UnitScale.cs @@ -8,6 +8,8 @@ namespace RhinoInside.Revit.Convert.Units { + using Numerical; + [DebuggerDisplay("{Antecedent} ∶ {Consequent} ({Quotient})")] readonly struct Ratio : IEquatable { @@ -391,10 +393,7 @@ public static double Convert(double value, UnitScale from, UnitScale to) var den = f * T; // Multiply value by resulting ratio considering magnitude. - if (Math.Abs(num) < Math.Abs(value)) - return num * (value / den); - else - return value * (num / den); + return Arithmetic.MinMagnitude(num, value) * (Arithmetic.MaxMagnitude(num, value) / den); } public override string ToString() => Name ?? ((UnitSystem) this).ToString(); @@ -458,6 +457,7 @@ internal static void SetUnitScale(RhinoDoc doc, ActiveSpace space, UnitScale val } doc.ModelSpaceHatchScale *= scaleFactor; + doc.Linetypes.LinetypeScale *= scaleFactor; foreach (var style in doc.DimStyles) { From 39b7402620e28ee7183752c8f4c7a076fd9a274e Mon Sep 17 00:00:00 2001 From: kike-garbo Date: Wed, 4 Sep 2024 19:13:00 +0200 Subject: [PATCH 2/5] Added `Types.ModelText` wrapper. --- .../Types/Element.Activator.cs | 1 + .../Types/Model/ModelText.cs | 62 +++++++++++++++++++ 2 files changed, 63 insertions(+) create mode 100644 src/RhinoInside.Revit.GH/Types/Model/ModelText.cs diff --git a/src/RhinoInside.Revit.GH/Types/Element.Activator.cs b/src/RhinoInside.Revit.GH/Types/Element.Activator.cs index a66c25e58..d3547d79d 100644 --- a/src/RhinoInside.Revit.GH/Types/Element.Activator.cs +++ b/src/RhinoInside.Revit.GH/Types/Element.Activator.cs @@ -313,6 +313,7 @@ public static Element FromReference(ARDB.Document doc, ARDB.Reference reference) { typeof(ARDB.CombinableElement), (element)=> new CombinableElement (element as ARDB.CombinableElement) }, { typeof(ARDB.GeomCombination), (element)=> new GeomCombination (element as ARDB.GeomCombination) }, { typeof(ARDB.GenericForm), (element)=> new GenericForm (element as ARDB.GenericForm) }, + { typeof(ARDB.ModelText), (element)=> new ModelText (element as ARDB.ModelText) }, { typeof(ARDB.DatumPlane), (element)=> new DatumPlane (element as ARDB.DatumPlane) }, { typeof(ARDB.Level), (element)=> new Level (element as ARDB.Level) }, diff --git a/src/RhinoInside.Revit.GH/Types/Model/ModelText.cs b/src/RhinoInside.Revit.GH/Types/Model/ModelText.cs new file mode 100644 index 000000000..f6fb4daa9 --- /dev/null +++ b/src/RhinoInside.Revit.GH/Types/Model/ModelText.cs @@ -0,0 +1,62 @@ +using System; +using Rhino.Geometry; +using ARDB = Autodesk.Revit.DB; + +namespace RhinoInside.Revit.GH.Types +{ + using Convert.Geometry; + using External.DB.Extensions; + + [Kernel.Attributes.Name("Model Text")] + public class ModelText : GeometricElement + { + protected override Type ValueType => typeof(ARDB.ModelText); + public new ARDB.ModelText Value => base.Value as ARDB.ModelText; + + public ModelText() : base() { } + public ModelText(ARDB.ModelText modelText) : base(modelText) { } + + #region Location + public override Plane Location + { + get + { + if (Value is ARDB.ModelText modelText) + { + using (var options = new ARDB.Options { DetailLevel = ARDB.ViewDetailLevel.Undefined }) + { + var geometry = modelText.get_Geometry(options); + if (geometry.TryGetLocation(out var gO, out var gX, out var gY)) + { + var xform = ARDB.Transform.Identity; + xform.SetAlignCoordSystem + ( + ARDB.XYZ.Zero, External.DB.UnitXYZ.BasisX, External.DB.UnitXYZ.BasisY, External.DB.UnitXYZ.BasisZ, + gO, gX, gY, gX.CrossProduct(gY).ToUnitXYZ() + ); + + var box = geometry.GetBoundingBox(xform); + + var origin = (box.GetCenter() - box.Transform.BasisZ * 0.5 * (box.Max.Z - box.Min.Z)); + switch (modelText.HorizontalAlignment) + { + case ARDB.HorizontalAlign.Left: origin = box.GetCorners()[3]; break; + case ARDB.HorizontalAlign.Right: origin = box.GetCorners()[2]; break; + case ARDB.HorizontalAlign.Center: origin = (box.GetCorners()[3] + box.GetCorners()[2]) * 0.5; break; + } + + return new Plane(origin.ToPoint3d(), box.Transform.BasisX.ToVector3d(), box.Transform.BasisY.ToVector3d()); + } + } + + var bbox = BoundingBox; + if (bbox.IsValid) + return new Plane(BoundingBox.Center, Vector3d.XAxis, Vector3d.YAxis); + } + + return NaN.Plane; + } + } + #endregion + } +} From e54ad6ee2d2e8345289bef8ef4f4129ff48c5e60 Mon Sep 17 00:00:00 2001 From: kike-garbo Date: Wed, 4 Sep 2024 19:15:56 +0200 Subject: [PATCH 3/5] Moved some files to Model folder. --- src/RhinoInside.Revit.GH/Types/{ => Model}/CombinableElement.cs | 0 src/RhinoInside.Revit.GH/Types/{ => Model}/CurveElement.cs | 0 src/RhinoInside.Revit.GH/Types/{ => Model}/Group.cs | 0 src/RhinoInside.Revit.GH/Types/{ => Model}/SketchPlane.cs | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename src/RhinoInside.Revit.GH/Types/{ => Model}/CombinableElement.cs (100%) rename src/RhinoInside.Revit.GH/Types/{ => Model}/CurveElement.cs (100%) rename src/RhinoInside.Revit.GH/Types/{ => Model}/Group.cs (100%) rename src/RhinoInside.Revit.GH/Types/{ => Model}/SketchPlane.cs (100%) diff --git a/src/RhinoInside.Revit.GH/Types/CombinableElement.cs b/src/RhinoInside.Revit.GH/Types/Model/CombinableElement.cs similarity index 100% rename from src/RhinoInside.Revit.GH/Types/CombinableElement.cs rename to src/RhinoInside.Revit.GH/Types/Model/CombinableElement.cs diff --git a/src/RhinoInside.Revit.GH/Types/CurveElement.cs b/src/RhinoInside.Revit.GH/Types/Model/CurveElement.cs similarity index 100% rename from src/RhinoInside.Revit.GH/Types/CurveElement.cs rename to src/RhinoInside.Revit.GH/Types/Model/CurveElement.cs diff --git a/src/RhinoInside.Revit.GH/Types/Group.cs b/src/RhinoInside.Revit.GH/Types/Model/Group.cs similarity index 100% rename from src/RhinoInside.Revit.GH/Types/Group.cs rename to src/RhinoInside.Revit.GH/Types/Model/Group.cs diff --git a/src/RhinoInside.Revit.GH/Types/SketchPlane.cs b/src/RhinoInside.Revit.GH/Types/Model/SketchPlane.cs similarity index 100% rename from src/RhinoInside.Revit.GH/Types/SketchPlane.cs rename to src/RhinoInside.Revit.GH/Types/Model/SketchPlane.cs From 7cfd2e0f4badec89d420d79076708ee021395fe6 Mon Sep 17 00:00:00 2001 From: kike-garbo Date: Wed, 4 Sep 2024 19:17:25 +0200 Subject: [PATCH 4/5] Fix on `Element.IsEquivalent` extension method. When a null is provided. --- src/RhinoInside.Revit.External/DB/Extensions/Element.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/RhinoInside.Revit.External/DB/Extensions/Element.cs b/src/RhinoInside.Revit.External/DB/Extensions/Element.cs index d4f8ec7a4..f2cca457c 100644 --- a/src/RhinoInside.Revit.External/DB/Extensions/Element.cs +++ b/src/RhinoInside.Revit.External/DB/Extensions/Element.cs @@ -48,7 +48,7 @@ public static bool IsEquivalent(this Element self, Element other) if (ReferenceEquals(self, other)) return true; - if (!self.IsValidObject || !other.IsValidObject) + if (!(self?.IsValidObject is true) || !(other?.IsValidObject is true)) return false; if (self?.Id != other?.Id) From 76e70af7aa6be33f5cdb495363545512816fa207 Mon Sep 17 00:00:00 2001 From: kike-garbo Date: Wed, 4 Sep 2024 19:22:03 +0200 Subject: [PATCH 5/5] Moved some files to HostObjects folder. --- src/RhinoInside.Revit.GH/Types/{ => HostObjects}/Opening.cs | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/RhinoInside.Revit.GH/Types/{ => HostObjects}/Opening.cs (100%) diff --git a/src/RhinoInside.Revit.GH/Types/Opening.cs b/src/RhinoInside.Revit.GH/Types/HostObjects/Opening.cs similarity index 100% rename from src/RhinoInside.Revit.GH/Types/Opening.cs rename to src/RhinoInside.Revit.GH/Types/HostObjects/Opening.cs