- 
      0
      2
      2
    
- 
          1
          0
          7
        
- 1c961c8b-9745-4a92-a43d-080de1ead765
- Shaded
- 1
- 
              100;150;0;0
            
- 
              100;0;150;0
            
- 635273898765795129
- elastica_curve_examples - Copy.ghx
- 0
- 
                  -102
                  40
                
- 1
- 0
- 0
- 149
- c552a431-af5b-46a9-a8a4-0fcbc27ef596
- Group
- 1
- 
                      150;170;135;255
                    
- A group of Grasshopper objects
- d013dc08-a8cd-4383-aa4a-7e9f0b202f67
- 19d4e5e6-a3fb-4e4d-b426-93c0b41f974c
- ce2f14ec-483c-4899-a8cb-784a62168957
- b2a67d0f-c66e-46a9-8efd-f7442d233d5d
- 32bb1a9f-9575-4b8c-8a60-a65a7b9dd15f
- 98102773-859e-4cf3-83a5-41f68379af66
- d68f5884-1ed1-4bd5-ab64-b7040370d59b
- 8cd6ad76-7f71-4948-8c5e-9a3e2549985f
- d53a1087-053a-44d5-b485-68a8b5d09ce4
- cc8dfb80-5022-4b13-83c9-a787888900e8
- 072c5f2f-5efd-4587-8eb9-f4eacb6f59a9
- 25d0b3b4-fc42-4433-a4bf-e70bfa828143
- 5137ef09-783f-4981-a9ec-aa4f2fc8e019
- 225afdb2-480f-435b-a1cb-84170b3afd2f
- 20228f31-e357-4d65-8747-46e12348391c
- 7c2a1ac2-4916-4aa3-9b0a-566a67f36e60
- 95f9fd7f-37dc-4bd8-8105-7301ef052bdd
- 17
- 07a70634-4e1a-4226-b5d3-17b0a4e0f460
- Group
- 079bd9bd-54a0-41d4-98af-db999015f63d
- VB Script
-   Private Function IsSet(ByVal param As String) As Boolean  ' Check if an input parameter has data
    Dim i As Integer = Component.Params.IndexOfInputParam(param)
    If i > -1 Then
      Return Component.Params.Input.ElementAt(i).DataType > 1  ' input parameter DataType of 1 means it's not receiving input (internal or external)
    Else
      Msg("error", "Input parameter '" & param & "' not found")
      Return False
    End If
  End Function
  Private Sub Msg(ByVal type As String, ByVal msg As String)  ' Output an error, warning, or informational message
    Select Case type
      Case "error"
        Component.AddRuntimeMessage(GH_RuntimeMessageLevel.Error, msg)
        Print("Error: " & msg)
      Case "warning"
        Component.AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, msg)
        Print("Warning: " & msg)
      Case "info"
        Component.AddRuntimeMessage(GH_RuntimeMessageLevel.Remark, msg)
        Print(msg)
    End Select
  End Sub
  ' Solve for the m parameter from length and width (reference {1} equation (34), except b = width and K(k) and E(k) should be K(m) and E(m))
  Private Function SolveMFromLenWid(ByVal L As Double, ByVal w As Double) As Double
    If w = 0 Then
      Return Defined.M_ZERO_W  ' for the boundry condition width = 0, bypass the function and return the known m value
    End If
    Dim n As Integer = 1 ' Iteration counter (quit if >MAXIT)
    Dim lower As Double = 0 ' m must be within this range
    Dim upper As Double = 1
    Dim m As Double
    Dim cwl As Double
    Do While (upper - lower) > Defined.MAXERR AndAlso (n) < Defined.MAXIT ' Repeat until range narrow enough or MAXIT
      m = (upper + lower) / 2
      cwl = 2 * EllipticE(m) / EllipticK(m) - 1  ' calculate w/L with the test value of m
      If cwl < w / L Then  ' compares the calculated w/L with the actual w/L then narrows the range of possible m
        upper = m
      Else
        lower = m
      End If
      n += 1
    Loop
    Return m
  End Function
  ' Solve for the m parameter from length and height (reference {1} equation (33), except K(k) should be K(m) and k = sqrt(m))
  ' Note that it's actually possible to find 2 valid values for m (hence 2 width values) at certain height values
  Private Function SolveMFromLenHt(ByVal L As Double, ByVal h As Double) As List(Of Double)
    Dim n As Integer = 1 ' Iteration counter (quit if >MAXIT)
    Dim lower As Double = 0 ' m must be within this range
    Dim upper As Double = 1
    Dim twoWidths As Boolean = h / L >= Defined.DOUBLE_W_HL_RATIO And h / L < Defined.MAX_HL_RATIO  ' check to see if h/L is within the range where 2 solutions for the width are possible
    Dim m As Double
    Dim mult_m As New List(Of Double)
    Dim chl As Double
    If twoWidths Then
      ' find the first of two possible solutions for m with the following limits:
      lower = Defined.M_DOUBLE_W  ' see constants at bottom of script
      upper = Defined.M_MAXHEIGHT  ' see constants at bottom of script
      Do While (upper - lower) > Defined.MAXERR AndAlso (n) < Defined.MAXIT ' Repeat until range narrow enough or MAXIT
        m = (upper + lower) / 2
        chl = Math.Sqrt(m) / EllipticK(m)  ' calculate h/L with the test value of m
        If chl > h / L Then  ' compares the calculated h/L with the actual h/L then narrows the range of possible m
          upper = m
        Else
          lower = m
        End If
        n += 1
      Loop
      mult_m.Add(m)
      ' then find the second of two possible solutions for m with the following limits:
      lower = Defined.M_MAXHEIGHT  ' see constants at bottom of script
      upper = 1
      Do While (upper - lower) > Defined.MAXERR AndAlso (n) < Defined.MAXIT ' Repeat until range narrow enough or MAXIT
        m = (upper + lower) / 2
        chl = Math.Sqrt(m) / EllipticK(m)  ' calculate h/L with the test value of m
        If chl < h / L Then  ' compares the calculated h/L with the actual h/L then narrows the range of possible m
          upper = m
        Else
          lower = m
        End If
        n += 1
      Loop
      If m <= Defined.M_MAX Then  ' return this m parameter only if it falls within the maximum useful value (above which the curve breaks down)
        mult_m.Add(m)
      End If
    Else
      ' find the one possible solution for the m parameter
      upper = Defined.M_DOUBLE_W  ' limit the upper end of the search to the maximum value of m for which only one solution exists
      Do While (upper - lower) > Defined.MAXERR AndAlso (n) < Defined.MAXIT ' Repeat until range narrow enough or MAXIT
        m = (upper + lower) / 2
        chl = Math.Sqrt(m) / EllipticK(m)  ' calculate h/L with the test value of m
        If chl > h / L Then  ' compares the calculated h/L with the actual h/L then narrows the range of possible m
          upper = m
        Else
          lower = m
        End If
        n += 1
      Loop
      mult_m.Add(m)
    End If
    Return mult_m
  End Function
  ' Solve for the m parameter from width and height (derived from reference {1} equations (33) and (34) with same notes as above)
  Private Function SolveMFromWidHt(ByVal w As Double, ByVal h As Double) As Double
    Dim n As Integer = 1 ' Iteration counter (quit if >MAXIT)
    Dim lower As Double = 0 ' m must be within this range
    Dim upper As Double = 1
    Dim m As Double
    Dim cwh As Double
    Do While (upper - lower) > Defined.MAXERR AndAlso (n) < Defined.MAXIT ' Repeat until range narrow enough or MAXIT
      m = (upper + lower) / 2
      cwh = (2 * EllipticE(m) - EllipticK(m)) / Math.Sqrt(m)  ' calculate w/h with the test value of m
      If cwh < w / h Then  ' compares the calculated w/h with the actual w/h then narrows the range of possible m
        upper = m
      Else
        lower = m
      End If
      n += 1
    Loop
    Return m
  End Function
  ' Calculate length based on height and an m parameter, derived from reference {1} equation (33), except K(k) should be K(m) and k = sqrt(m)
  Private Function Cal_L(ByVal h As Double, ByVal m As Double) As Double
    Return h * EllipticK(m) / Math.Sqrt(m)
  End Function
  ' Calculate width based on length and an m parameter, derived from reference {1} equation (34), except b = width and K(k) and E(k) should be K(m) and E(m)
  Private Function Cal_W(ByVal L As Double, ByVal m As Double) As Double
    Return L * (2 * EllipticE(m) / EllipticK(m) - 1)
  End Function
  ' Calculate height based on length and an m parameter, from reference {1} equation (33), except K(k) should be K(m) and k = sqrt(m)
  Private Function Cal_H(ByVal L As Double, ByVal m As Double) As Double
    Return L * Math.Sqrt(m) / EllipticK(m)
  End Function
  ' Calculate the unique m parameter based on a start tangent angle, from reference {2}, just above equation (9a), that states k = Sin(angle / 2 + Pi / 4),
  ' but as m = k^2 and due to this script's need for an angle rotated 90° versus the one in reference {1}, the following formula is the result
  ' New note: verified by reference {4}, pg. 78 at the bottom
  Private Function Cal_M(ByVal a As Double) As Double
    Return (1 - Math.Cos(a)) / 2  ' equal to Sin^2(a/2) too
  End Function
  ' Calculate start tangent angle based on an m parameter, derived from above formula
  Private Function Cal_A(ByVal m As Double) As Double
    Return Math.Acos(1 - 2 * m)
  End Function
  ' This is the heart of this script, taking the found (or specified) length, width, and angle values along with the found m parameter to create
  ' a list of points that approximate the shape or form of the elastica. It works by finding the x and y coordinates (which are reversed versus
  ' the original equations (12a) and (12b) from reference {2} due to the 90° difference in orientation) based on the tangent angle along the curve.
  ' See reference {2} for more details on how they derived it. Note that to simplify things, the algorithm only calculates the points for half of the
  ' curve, then mirrors those points along the y-axis.
  Private Function FindBendForm(ByVal L As Double, ByVal w As Double, ByVal m As Double, ByVal ang As Double, ByVal refPln As Plane) As List(Of Point3d)
    L = L / 2  ' because the below algorithm is based on the formulas in reference {2} for only half of the curve
    w = w / 2  ' same
    If ang = 0 Then  ' if angle (and height) = 0, then simply return the start and end points of the straight line
      Dim out As New List(Of Point3d)
      out.Add(refPln.PointAt(w, 0, 0))
      out.Add(refPln.PointAt(-w, 0, 0))
      Return out
    End If
    Dim x As Double
    Dim y As Double
    Dim halfCurvePts As New List(Of Point3d)
    Dim fullCurvePts As New List(Of Point3d)
    Dim translatedPts As New List(Of Point3d)
    ang -= Math.PI / 2  ' a hack to allow this algorithm to work, since the original curve in paper {2} was rotated 90°
    Dim angB As Double = ang + (-Math.PI / 2 - ang) / Defined.CURVEDIVS  ' angB is the 'lowercase theta' which should be in formula {2}(12b) as the interval
    ' start [a typo...see equation(3)]. It's necessary to start angB at ang + [interval] instead of just ang due to integration failing at angB = ang
    halfCurvePts.Add(New Point3d(w, 0, 0))  ' start with this known initial point, as integration will fail when angB = ang
    ' each point {x, y} is calculated from the tangent angle, angB, that occurs at each point (which is why this iterates from ~ang to -pi/2, the known end condition)
    Do While Math.Round(angB, Defined.ROUNDTO) >= Math.Round(-Math.PI / 2, Defined.ROUNDTO)
      y = (Math.Sqrt(2) * Math.Sqrt(Math.Sin(ang) - Math.Sin(angB)) * (w + L)) / (2 * EllipticE(m))  ' note that x and y are swapped vs. (12a) and (12b)
      x = (L / (Math.Sqrt(2) * EllipticK(m))) * Simpson(angB, -Math.PI / 2, 500, ang)  ' calculate the Simpson approximation of the integral (function f below)
      ' over the interval angB ('lowercase theta') to -pi/2. side note: is 500 too few iterations for the Simson algorithm?
      If Math.Round(x, Defined.ROUNDTO) = 0 Then x = 0
      halfCurvePts.Add(New Point3d(x, y, 0))
      angB += (-Math.PI / 2 - ang) / Defined.CURVEDIVS  ' onto the next tangent angle
    Loop
    ' After finding the x and y values for half of the curve, add the {-x, y} values for the rest of the curve
    For Each point As Point3d In halfCurvePts
      If Math.Round(point.X, Defined.ROUNDTO) = 0 Then
        If Math.Round(point.Y, Defined.ROUNDTO) = 0 Then
          fullCurvePts.Add(New Point3d(0, 0, 0))  ' special case when width = 0: when x = 0, only duplicate the point when y = 0 too
        End If
      Else
        fullCurvePts.Add(New Point3d(-point.X, point.Y, 0))
      End If
    Next
    halfCurvePts.Reverse
    fullCurvePts.AddRange(halfCurvePts)
    For Each p As Point3d In fullCurvePts
      translatedPts.Add(refPln.PointAt(p.X, p.Y, p.Z))  ' translate the points from the reference plane to the world plane
    Next
    Return translatedPts
  End Function
  ' Interpolates the points from FindBendForm to create the Elastica curve. Uses start & end tangents for greater accuracy.
  Private Function MakeCurve(ByVal pts As List(Of Point3d), ByVal ang As Double, ByVal refPln As Plane) As Curve
    If ang <> 0 Then
      Dim ts, te As New Vector3d(refPln.XAxis)
      ts.Rotate(ang, refPln.ZAxis)
      te.Rotate(-ang, refPln.ZAxis)
      Return Curve.CreateInterpolatedCurve(pts, 3, CurveKnotStyle.Chord, ts, te)  ' 3rd degree curve with 'Chord' Knot Style
    Else
      Return Curve.CreateInterpolatedCurve(pts, 3)  ' if angle (and height) = 0, then simply interpolate the straight line (no start/end tangents)
    End If
  End Function
  ' Implements the Simpson approximation for an integral of function f below
  Public Function Simpson(a As Double, b As Double, n As Integer, theta As Double) As Double 'n should be an even number
    Dim j As Integer, s1 As Double, s2 As Double, h As Double
    h = (b - a) / n
    s1 = 0
    s2 = 0
    For j = 1 To n - 1 Step 2
      s1 = s1 + fn(a + j * h, theta)
    Next j
    For j = 2 To n - 2 Step 2
      s2 = s2 + fn(a + j * h, theta)
    Next j
    Simpson = h / 3 * (fn(a, theta) + 4 * s1 + 2 * s2 + fn(b, theta))
  End Function
  ' Specific calculation for the above integration
  Public Function fn(x As Double, theta As Double) As Double
    fn = Math.Sin(x) / (Math.Sqrt(Math.Sin(theta) - Math.Sin(x)))  ' from reference {2} formula (12b)
  End Function
  ' Return the Complete Elliptic integral of the 1st kind
  ' Abramowitz and Stegun p.591, formula 17.3.11
  ' Code from http://www.codeproject.com/Articles/566614/Elliptic-integrals
  Public Function EllipticK(ByVal m As Double) As Double
    Dim sum, term, above, below As Double
    sum = 1
    term = 1
    above = 1
    below = 2
    For i As Integer = 1 To 100
      term *= above / below
      sum += Math.Pow(m, i) * Math.Pow(term, 2)
      above += 2
      below += 2
    Next
    sum *= 0.5 * Math.PI
    Return sum
  End Function
  ' Return the Complete Elliptic integral of the 2nd kind
  ' Abramowitz and Stegun p.591, formula 17.3.12
  ' Code from http://www.codeproject.com/Articles/566614/Elliptic-integrals
  Public Function EllipticE(ByVal m As Double) As Double
    Dim sum, term, above, below As Double
    sum = 1
    term = 1
    above = 1
    below = 2
    For i As Integer = 1 To 100
      term *= above / below
      sum -= Math.Pow(m, i) * Math.Pow(term, 2) / above
      above += 2
      below += 2
    Next
    sum *= 0.5 * Math.PI
    Return sum
  End Function
  Friend Partial NotInheritable Class Defined
    Private Sub New()
    End Sub
    ' Note: most of these values for m and h/L ratio were found with Wolfram Alpha and either specific intercepts (x=0) or local minima/maxima. They should be constant.
    Public Const M_SKETCHY As Double = 0.95  ' value of the m parameter where the curvature near the ends of the curve gets wonky
    Public Const M_MAX As Double = 0.993  ' maximum useful value of the m parameter, above which this algorithm for the form of the curve breaks down
    Public Const M_ZERO_W As Double = 0.826114765984970336  ' value of the m parameter when width = 0
    Public Const M_MAXHEIGHT As Double = 0.701327460663101223  ' value of the m parameter at maximum possible height of the bent rod/wire
    Public Const M_DOUBLE_W As Double = 0.180254422335013983  ' minimum value of the m parameter when two width values are possible for a given height and length
    Public Const DOUBLE_W_HL_RATIO As Double = 0.257342117984635757  ' value of the height/length ratio above which there are two possible width values
    Public Const MAX_HL_RATIO As Double = 0.403140189705650243  ' maximum possible value of the height/length ratio
    Public Const MAXERR As Double = 0.0000000001  ' error tolerance
    Public Const MAXIT As Integer = 100  ' maximum number of iterations
    Public Const ROUNDTO As Integer = 10  ' number of decimal places to round off to
    Public Const CURVEDIVS As Integer = 50  ' number of sample points for building the curve (or half-curve as it were)
  End Class
- A VB.NET scriptable component
- 
                      98
                      86
                    
- true
- d013dc08-a8cd-4383-aa4a-7e9f0b202f67
- VB Script
- VB
- true
- 0
-     ' -----------------------------------------------------------------
    ' Elastic Bending Script by Will McElwain
    ' Created February 2014
    '
    ' DESCRIPTION:
    ' This beast creates the so-called 'elastica curve', the shape a long, thin rod or wire makes when it is bent elastically (i.e. not permanently). In this case, force
    ' is assumed to only be applied horizontally (which would be in line with the rod at rest) and both ends are assumed to be pinned or hinged meaning they are free
    ' to rotate (as opposed to clamped, when the end tangent angle is fixed, usually horizontally). An interesting finding is that it doesn't matter what the material or
    ' cross-sectional area is, as long as they're uniform along the entire length. Everything makes the same shape when bent as long as it doesn't cross the threshold
    ' from elastic to plastic (permanent) deformation (I don't bother to find that limit here, but can be found if the yield stress for a material is known).
    '
    ' Key to the formulas used in this script are elliptic integrals, specifically K(m), the complete elliptic integral of the first kind, and E(m), the complete elliptic
    ' integral of the second kind. There was a lot of confusion over the 'm' and 'k' parameters for these functions, as some people use them interchangeably, but they are
    ' not the same. m = k^2 (thus k = Sqrt(m)). I try to use the 'm' parameter exclusively to avoid this confusion. Note that there is a unique 'm' parameter for every
    ' configuration/shape of the elastica curve.
    '
    ' This script tries to find that unique 'm' parameter based on the inputs. The algorithm starts with a test version of m, evaluates an expression, say 2*E(m)/K(m)-1,
    ' then compares the result to what it should be (in this case, a known width/length ratio). Iterate until the correct m is found. Once we have m, we can then calculate
    ' all of the other unknowns, then find points that lie on that curve, then interpolate those points for the actual curve. You can also use Wolfram|Alpha as I did to
    ' find the m parameter based on the equations in this script (example here: http://tiny.cc/t4tpbx for when say width=45.2 and length=67.1).
    '
    ' Other notes:
    ' * This script works with negative values for width, which will creat a self-intersecting curve (as it should). The curvature of the elastica starts to break down around
    ' m=0.95 (~154°), but this script will continue to work until M_MAX, m=0.993 (~169°). If you wish to ignore self-intersecting curves, set ignoreSelfIntersecting to True
    ' * When the only known values are length and height, it is actually possible for certain ratios of height to length to have two valid m values (thus 2 possible widths
    ' and angles). This script will return them both.
    ' * Only the first two valid parameters (of the required ones) will be used, meaning if all four are connected (length, width or a PtB, height, and angle), this script will
    ' only use length and width (or a PtB).
    ' * Depending on the magnitude of your inputs (say if they're really small, like if length < 10), you might have to increase the constant ROUNDTO at the bottom
    '
    ' REFERENCES:
    ' {1} "The elastic rod" by M.E. Pacheco Q. & E. Pina, http://www.scielo.org.mx/pdf/rmfe/v53n2/v53n2a8.pdf
    ' {2} "An experiment in nonlinear beam theory" by A. Valiente, http://www.deepdyve.com/lp/doc/I3lwnxdfGz , also here: http://tiny.cc/Valiente_AEiNBT
    ' {3} "Snap buckling, writhing and Loop formation In twisted rods" by V.G.A. GOSS, http://myweb.lsbu.ac.uk/~gossga/thesisFinal.pdf
    ' {4} "Theory of Elastic Stability" by Stephen Timoshenko, http://www.scribd.com/doc/50402462/Timoshenko-Theory-of-Elastic-Stability  (start on p. 76)
    '
    ' INPUT:
    ' PtA - First anchor point (required)
    ' PtB - Second anchor point (optional, though 2 out of the 4--length, width, height, angle--need to be specified)
    '       [note that PtB can be the same as PtA (meaning width would be zero)]
    '       [also note that if a different width is additionally specified that's not equal to the distance between PtA and PtB, then the end point will not equal PtB anymore]
    ' Pln - Plane of the bent rod/wire, which bends up in the +y direction. The line between PtA and PtB (if specified) must be parallel to the x-axis of this plane
    '
    ' ** 2 of the following 4 need to be specified **
    ' Len - Length of the rod/wire, which needs to be > 0
    ' Wid - Width between the endpoints of the curve [note: if PtB is specified in addition, and distance between PtA and PtB <> width, the end point will be relocated
    ' Ht - Height of the bent rod/wire (when negative, curve will bend downward, relative to the input plane, instead)
    ' Ang - Inner departure angle or tangent angle (in radians) at the ends of the bent rod/wire. Set up so as width approaches length (thus height approaches zero), angle approaches zero
    '
    ' * Following variables only needed for optional calculating of bending force, not for shape of curve.
    ' E - Young's modulus (modulus of elasticity) in GPa (=N/m^2) (material-specific. for example, 7075 aluminum is roughly 71.7 GPa)
    ' I - Second moment of area (or area moment of inertia) in m^4 (cross-section-specific. for example, a hollow rod
    '     would have I = pi * (outer_diameter^4 - inner_diameter^4) / 32
    ' Note: E*I is also known as flexural rigidity or bending stiffness
    '
    ' OUTPUT:
    ' out - only for debugging messages
    ' Pts - the list of points that approximate the shape of the elastica
    ' Crv - the 3rd-degree curve interpolated from those points (with accurate start & end tangents)
    ' L - the length of the rod/wire
    ' W - the distance (width) between the endpoints of the rod/wire
    ' H - the height of the bent rod/wire
    ' A - the tangent angle at the (start) end of the rod/wire
    ' F - the force needed to hold the rod/wire in a specific shape (based on the material properties & cross-section) **be sure your units for 'I' match your units for the
    ' rest of your inputs (length, width, etc.). Also note that the critical buckling load (force) that makes the rod/wire start to bend can be found at height=0
    '
    ' THANKS TO:
    ' Mårten Nettelbladt (thegeometryofbending.blogspot.com)
    ' Daniel Piker (Kangaroo plugin)
    ' David Rutten (Grasshopper guru)
    ' Euler & Bernoulli (the O.G.'s)
    '
    ' -----------------------------------------------------------------
    Dim ignoreSelfIntersecting As Boolean = False  ' set to True if you don't want to output curves where width < 0, which creates a self-intersecting curve
    Dim inCt As Integer = 0  ' count the number of required parameters that are receiving data
    Dim length As Double
    Dim width As System.Object = Nothing  ' need to set as Nothing so we can check if it has been assigned a value later
    Dim height As Double
    Dim angle As Double
    Dim m As Double
    Dim multiple_m As New List(Of Double)
    Dim AtoB As Line
    Dim flip_H As Boolean = False  ' if height is negative, this flag will be set
    Dim flip_A As Boolean = False  ' if angle is negative, this flag will be set
    If Not IsSet("Pln") Then
      Msg("error", "Base plane is not set")
      Return
    End If
    If Not IsSet("PtA") Then
      Msg("error", "Point A is not set")
      Return
    End If
    If Math.Round(Pln.DistanceTo(PtA), Defined.ROUNDTO) <> 0 Then
      Msg("error", "Point A is not on the base plane")
      Return
    End If
    Dim refPlane As Plane = Pln  ' create a reference plane = input plane and set the origin of it to PtA in case PtA isn't the origin already
    refPlane.Origin = PtA
    If IsSet("PtB") Then
      If Math.Round(Pln.DistanceTo(PtB), Defined.ROUNDTO) <> 0 Then
        Msg("error", "Point B is not on the base plane")
        Return
      End If
      AtoB = New Line(PtA, PtB)
      If AtoB.Length <> 0 And Not AtoB.Direction.IsPerpendicularTo(Pln.YAxis) Then
        Msg("error", "The line between PtA and PtB is not perpendicular to the Y-axis of the specified plane")
        Return
      End If
      inCt += 1
      If IsSet("Wid") Then Msg("info", "Wid will override the distance between PtA and PtB. If you do not want this to happen, disconnect PtB or Wid.")
      width = PtA.DistanceTo(PtB)  ' get the width (distance) between PtA and PtB
      
      Dim refPtB As Point3d
      refPlane.RemapToPlaneSpace(PtB, refPtB)
      If refPtB.X < 0 Then width = -width  ' check if PtB is to the left of PtA...if so, width is negative
    End If
    If IsSet("Len") Then inCt += 1
    If IsSet("Wid") Then inCt += 1
    If IsSet("Ht") Then inCt += 1
    If IsSet("Ang") Then inCt += 1
    If inCt > 2 Then Msg("info", "More parameters set than are required (out of length, width, height, angle). Only using the first two valid ones.")
    ' check for connected/specified inputs. note: only the first two that it comes across will be used
    If IsSet("Len") Then  ' if length is specified then...
      If Len <= 0 Then
        Msg("error", "Length cannot be negative or zero")
        Return
      End If
      If IsSet("Wid") Then  ' find height & angle based on length and specified width
        If Wid > Len Then
          Msg("error", "Width is greater than length")
          Return
        End If
        If Wid = Len Then  ' skip the solver and set the known values
          height = 0
          m = 0
          angle = 0
          width = Wid
        Else
          m = SolveMFromLenWid(Len, Wid)
          height = Cal_H(Len, m)  ' L * Sqrt(m) / K(m)
          angle = Cal_A(m)  ' Acos(1 - 2 * m)
          width = Wid
        End If
      Else If width IsNot Nothing Then  ' find height & angle based on length and calculated width (distance between PtA and PtB)
        If width > Len Then
          Msg("error", "Width is greater than length")
          Return
        End If
        If width = Len Then  ' skip the solver and set the known values
          height = 0
          m = 0
          angle = 0
        Else
          m = SolveMFromLenWid(Len, width)
          height = Cal_H(Len, m)  ' L * Sqrt(m) / K(m)
          angle = Cal_A(m)  ' Acos(1 - 2 * m)
        End If
      Else If IsSet("Ht") Then  ' find width & angle based on length and height  ** possible to return 2 results **
        If Math.Abs(Ht / Len) > Defined.MAX_HL_RATIO Then
          Msg("error", "Height not possible with given length")
          Return
        End If
        If Ht < 0 Then
          Ht = -Ht  ' if height is negative, set it to positive (for the calculations) but flip the reference plane about its x-axis
          refPlane.Transform(Transform.Mirror(New Plane(refPlane.Origin, refPlane.XAxis, refPlane.ZAxis)))
          flip_A = True
          flip_H = True
        End If
        If Ht = 0 Then  ' skip the solver and set the known values
          width = Len
          angle = 0
        Else
          multiple_m = SolveMFromLenHt(Len, Ht)  ' note that it's possible for two values of m to be found if height is close to max height
          If multiple_m.Count = 1 Then  ' if there's only one m value returned, calculate the width & angle here. we'll deal with multiple m values later
            m = multiple_m.Item(0)
            width = Cal_W(Len, m)  ' L * (2 * E(m) / K(m) - 1)
            angle = Cal_A(m)  ' Acos(1 - 2 * m)
          End If
        End If
        height = Ht
      Else If IsSet("Ang") Then  ' find width & height based on length and angle
        If Ang < 0 Then
          Ang = -Ang  ' if angle is negative, set it to positive (for the calculations) but flip the reference plane about its x-axis
          refPlane.Transform(Transform.Mirror(New Plane(refPlane.Origin, refPlane.XAxis, refPlane.ZAxis)))
          flip_A = True
          flip_H = True
        End If
        m = Cal_M(Ang)  ' (1 - Cos(a)) / 2
        If Ang = 0 Then  ' skip the solver and set the known values
          width = Len
          height = 0
        Else
          width = Cal_W(Len, m)  ' L * (2 * E(m) / K(m) - 1)
          height = Cal_H(Len, m)  ' L * Sqrt(m) / K(m)
        End If
        angle = Ang
      Else
        Msg("error", "Need to specify one more parameter in addition to length")
        Return
      End If
      length = Len
    Else If IsSet("Wid") Then  ' if width is specified then...
      If IsSet("Ht") Then  ' find length & angle based on specified width and height
        If Ht < 0 Then
          Ht = -Ht  ' if height is negative, set it to positive (for the calculations) but flip the reference plane about its x-axis
          refPlane.Transform(Transform.Mirror(New Plane(refPlane.Origin, refPlane.XAxis, refPlane.ZAxis)))
          flip_A = True
          flip_H = True
        End If
        If Ht = 0 Then  ' skip the solver and set the known values
          length = Wid
          angle = 0
        Else
          m = SolveMFromWidHt(Wid, Ht)
          length = Cal_L(Ht, m)  ' h * K(m) / Sqrt(m)
          angle = Cal_A(m)  ' Acos(1 - 2 * m)
        End If
        height = Ht
      Else If IsSet("Ang") Then  ' find length & height based on specified width and angle
        If Wid = 0 Then
          Msg("error", "Curve not possible with width = 0 and an angle as inputs")
          Return
        End If
        If Ang < 0 Then
          Ang = -Ang  ' if angle is negative, set it to positive (for the calculations) but flip the reference plane about its x-axis
          refPlane.Transform(Transform.Mirror(New Plane(refPlane.Origin, refPlane.XAxis, refPlane.ZAxis)))
          flip_A = True
          flip_H = True
        End If
        m = Cal_M(Ang)  ' (1 - Cos(a)) / 2
        If Ang = 0 Then  ' skip the solver and set the known values
          length = Wid
          height = 0
        Else
          length = Wid / (2 * EllipticE(m) / EllipticK(m) - 1)
          If length < 0 Then
            Msg("error", "Curve not possible at specified width and angle (calculated length is negative)")
            Return
          End If
          height = Cal_H(length, m)  ' L * Sqrt(m) / K(m)
        End If
        angle = Ang
      Else
        Msg("error", "Need to specify one more parameter in addition to width (Wid)")
        Return
      End If
      width = Wid
    Else If width IsNot Nothing Then  ' if width is determined by PtA and PtB then...
      If IsSet("Ht") Then  ' find length & angle based on calculated width and height
        If Ht < 0 Then
          Ht = -Ht  ' if height is negative, set it to positive (for the calculations) but flip the reference plane about its x-axis
          refPlane.Transform(Transform.Mirror(New Plane(refPlane.Origin, refPlane.XAxis, refPlane.ZAxis)))
          flip_A = True
          flip_H = True
        End If
        If Ht = 0 Then  ' skip the solver and set the known values
          length = width
          angle = 0
        Else
          m = SolveMFromWidHt(width, Ht)
          length = Cal_L(Ht, m)  ' h * K(m) / Sqrt(m)
          angle = Cal_A(m)  ' Acos(1 - 2 * m)
        End If
        height = Ht
      Else If IsSet("Ang") Then  ' find length & height based on calculated width and angle
        If width = 0 Then
          Msg("error", "Curve not possible with width = 0 and an angle as inputs")
          Return
        End If
        If Ang < 0 Then
          Ang = -Ang  ' if angle is negative, set it to positive (for the calculations) but flip the reference plane about its x-axis
          refPlane.Transform(Transform.Mirror(New Plane(refPlane.Origin, refPlane.XAxis, refPlane.ZAxis)))
          flip_A = True
          flip_H = True
        End If
        m = Cal_M(Ang)  ' (1 - Cos(a)) / 2
        If Ang = 0 Then  ' skip the solver and set the known values
          length = width
          height = 0
        Else
          length = width / (2 * EllipticE(m) / EllipticK(m) - 1)
          If length < 0 Then
            Msg("error", "Curve not possible at specified width and angle (calculated length is negative)")
            Return
          End If
          height = Cal_H(length, m)  ' L * Sqrt(m) / K(m)
        End If
        angle = Ang
      Else
        Msg("error", "Need to specify one more parameter in addition to PtA and PtB")
        Return
      End If
    Else If IsSet("Ht") Then  ' if height is specified then...
      If IsSet("Ang") Then  ' find length & width based on height and angle
        If Ht < 0 Then
          Ht = -Ht  ' if height is negative, set it to positive (for the calculations) but flip the reference plane about its x-axis
          refPlane.Transform(Transform.Mirror(New Plane(refPlane.Origin, refPlane.XAxis, refPlane.ZAxis)))
          flip_H = True
          flip_A = True
        End If
        If Ht = 0 Then
          Msg("error", "Height can't = 0 if only height and angle are specified")
          Return
        Else
          If Ang < 0 Then
            Ang = -Ang  ' if angle is negative, set it to positive (for the calculations) but flip the reference plane about its x-axis
            refPlane.Transform(Transform.Mirror(New Plane(refPlane.Origin, refPlane.XAxis, refPlane.ZAxis)))
            flip_A = Not flip_A
            flip_H = Not flip_H
          End If
          m = Cal_M(Ang)  ' (1 - Cos(a)) / 2
          If Ang = 0 Then
            Msg("error", "Angle can't = 0 if only height and angle are specified")
            Return
          Else
            length = Cal_L(Ht, m)  ' h * K(m) / Sqrt(m)
            width = Cal_W(length, m)  ' L * (2 * E(m) / K(m) - 1)
          End If
          angle = Ang
        End If
        height = Ht
      Else
        Msg("error", "Need to specify one more parameter in addition to height")
        Return
      End If
    Else If IsSet("Ang") Then
      Msg("error", "Need to specify one more parameter in addition to angle")
      Return
    Else
      Msg("error", "Need to specify two of the four parameters: length, width (or PtB), height, and angle")
      Return
    End If
    If m > Defined.M_MAX Then
      Msg("error", "Form of curve not solvable with current algorithm and given inputs")
      Return
    End If
    refPlane.Origin = refPlane.PointAt(width / 2, 0, 0)  ' adjust the origin of the reference plane so that the curve is centered about the y-axis (start of the curve is at x = -width/2)
    If multiple_m.Count > 1 Then  ' if there is more than one m value returned, calculate the width, angle, and curve for each
      Dim multi_pts As New DataTree(Of Point3d)
      Dim multi_crv As New List(Of Curve)
      Dim tmp_pts As New List(Of Point3d)
      Dim multi_W, multi_A, multi_F As New List(Of Double)
      Dim j As Integer = 0  ' used for creating a new branch (GH_Path) for storing pts which is itself a list of points
      For Each m_val As Double In multiple_m
        width = Cal_W(length, m_val) 'length * (2 * EllipticE(m_val) / EllipticK(m_val) - 1)
        
        If width < 0 And ignoreSelfIntersecting Then
          Msg("warning", "One curve is self-intersecting. To enable these, set ignoreSelfIntersecting to False")
          Continue For
        End If
        
        If m_val >= Defined.M_SKETCHY Then Msg("info", "Accuracy of the curve whose width = " & Math.Round(width, 4) & " is not guaranteed")
        
        angle = Cal_A(m_val) 'Math.Asin(2 * m_val - 1)
        refPlane.Origin = refPlane.PointAt(width / 2, 0, 0)  ' adjust the origin of the reference plane so that the curve is centered about the y-axis (start of the curve is at x = -width/2)
        
        tmp_pts = FindBendForm(length, width, m_val, angle, refPlane)
        multi_pts.AddRange(tmp_pts, New GH_Path(j))
        multi_crv.Add(MakeCurve(tmp_pts, angle, refPlane))
        
        multi_W.Add(width)
        If flip_A Then angle = -angle
        multi_A.Add(angle)
        
        E = E * 10 ^ 9  ' Young's modulus input E is in GPa, so we convert to Pa here (= N/m^2)
        multi_F.Add(EllipticK(m_val) ^ 2 * E * I / length ^ 2)  ' from reference {4} pg. 79
        
        j += 1
        refPlane.Origin = PtA  ' reset the reference plane origin to PtA for the next m_val
        'Print("length=" & length & ", width=" & width & ", height=" & height & ", angle=" & angle & ", m=" & m_val & ", k=" & Math.Sqrt(m_val) & ", w/L=" & width / length & ", h/L=" & height / length & ", w/h=" & width / height)
      Next
      ' assign the outputs
      Pts = multi_pts
      Crv = multi_crv
      L = length
      W = multi_W
      If flip_H Then height = -height
      H = height
      A = multi_A
      F = multi_F
    Else  ' only deal with the single m value
      If m >= Defined.M_SKETCHY Then Msg("info", "Accuracy of the curve at these parameters is not guaranteed")
      
      If width < 0 And ignoreSelfIntersecting Then
        Msg("error", "Curve is self-intersecting. To enable these, set ignoreSelfIntersecting to False")
        Return
      End If
      
      Pts = FindBendForm(length, width, m, angle, refPlane)
      Crv = MakeCurve(pts, angle, refPlane)
      L = length
      W = width
      If flip_H Then height = -height
      H = height
      If flip_A Then angle = -angle
      A = angle
      E = E * 10 ^ 9  ' Young's modulus input E is in GPa, so we convert to Pa here (= N/m^2)
      F = EllipticK(m) ^ 2 * E * I / length ^ 2  ' from reference {4} pg. 79. Note: the critical buckling (that makes the rod/wire start to bend) can be found at height=0 (width=length)
      'height = Math.Sqrt(((2 * Len / 5) ^ 2 - ((Wid - Len / 5) / 2) ^ 2)  ' quick approximation discovered by Mårten of 'Geometry of Bending' fame ( http://tiny.cc/it2pbx )
      'width = (Len +/- 2 * Math.Sqrt(4 * Len ^ 2 - 25 * Ht ^ 2)) / 5  ' derived from above
      'length = (2 * Math.Sqrt(15 * Ht ^ 2 + 4 * Wid ^ 2) - Wid) / 3  ' derived from above
      'Print("length=" & length & ", width=" & width & ", height=" & height & ", angle=" & angle & ", m=" & m & ", k=" & Math.Sqrt(m) & ", w/L=" & width / length & ", h/L=" & height / length & ", w/h=" & width / height)
    End If
- 
                          612
                          233
                          84
                          184
                        
- 
                          654
                          325
                        
- 9
- 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2
- 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2
- 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2
- 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2
- 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2
- 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2
- 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2
- 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2
- 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2
- 8
- 3ede854e-c753-40eb-84cb-b48008f14fd4
- 8ec86459-bf01-4409-baee-174d0d2b13d0
- 8ec86459-bf01-4409-baee-174d0d2b13d0
- 8ec86459-bf01-4409-baee-174d0d2b13d0
- 8ec86459-bf01-4409-baee-174d0d2b13d0
- 8ec86459-bf01-4409-baee-174d0d2b13d0
- 8ec86459-bf01-4409-baee-174d0d2b13d0
- 8ec86459-bf01-4409-baee-174d0d2b13d0
- true
- Script Variable PtA
- 920df659-6d29-453d-9295-577245828ba6
- PtA
- PtA
- true
- 0
- true
- 7451bc70-5fc3-43a3-bb48-ff10952414e7
- 1
- e1937b56-b1da-4c12-8bd8-e34ee81746ef
- 
                                  614
                                  235
                                  25
                                  20
                                
- 
                                  628
                                  245
                                
- true
- Script Variable PtB
- eeb8ccaa-8966-4eab-8949-3eb384a12d84
- PtB
- PtB
- true
- 0
- true
- d5104343-e872-4369-9a14-a75a852c1a15
- 1
- e1937b56-b1da-4c12-8bd8-e34ee81746ef
- 
                                  614
                                  255
                                  25
                                  20
                                
- 
                                  628
                                  265
                                
- true
- Script Variable Pln
- ee4f4d3f-f195-437b-88af-35d3a73d66ad
- Pln
- Pln
- true
- 0
- true
- df7d1e6a-049f-4594-9fb2-7dda33d26e57
- 1
- 3897522d-58e9-4d60-b38c-978ddacfedd8
- 
                                  614
                                  275
                                  25
                                  20
                                
- 
                                  628
                                  285
                                
- true
- Script Variable Len
- 999531d8-8fc7-4421-8afb-076eb4ce3f6e
- Len
- Len
- true
- 0
- true
- ce2f14ec-483c-4899-a8cb-784a62168957
- 1
- 8e991e99-5fb8-41e1-928d-1bba8fb9f7d7
- 
                                  614
                                  295
                                  25
                                  20
                                
- 
                                  628
                                  305
                                
- true
- Script Variable Wid
- 8aba3acb-d87c-46a0-aef3-179156140406
- Wid
- Wid
- true
- 0
- true
- 0
- 8e991e99-5fb8-41e1-928d-1bba8fb9f7d7
- 
                                  614
                                  315
                                  25
                                  20
                                
- 
                                  628
                                  325
                                
- true
- Script Variable Ht
- 54082c0a-ad9c-49e6-97c2-34b9d8c0e605
- Ht
- Ht
- true
- 0
- true
- 0
- 8e991e99-5fb8-41e1-928d-1bba8fb9f7d7
- 
                                  614
                                  335
                                  25
                                  20
                                
- 
                                  628
                                  345
                                
- true
- Script Variable Ang
- 998111e9-4c7d-4b27-88a9-01982081691a
- Ang
- Ang
- true
- 0
- true
- 0
- 8e991e99-5fb8-41e1-928d-1bba8fb9f7d7
- 
                                  614
                                  355
                                  25
                                  20
                                
- 
                                  628
                                  365
                                
- true
- Script Variable E
- b0ed1e4b-bad1-4910-9cd3-3178fc1a708a
- E
- E
- true
- 0
- true
- 0
- 8e991e99-5fb8-41e1-928d-1bba8fb9f7d7
- 
                                  614
                                  375
                                  25
                                  20
                                
- 
                                  628
                                  385
                                
- true
- Script Variable I
- 8058a335-90ef-4152-920c-88e68de69acc
- I
- I
- true
- 0
- true
- 0
- 8e991e99-5fb8-41e1-928d-1bba8fb9f7d7
- 
                                  614
                                  395
                                  25
                                  20
                                
- 
                                  628
                                  405
                                
- 1
- Print, Reflect and Error streams
- 17655ef3-6a9d-43b9-a699-bb23d2e2baff
- out
- out
- false
- 0
- 
                                  669
                                  235
                                  25
                                  22
                                
- 
                                  681.5
                                  246.25
                                
- Output parameter Pts
- d4f9a77d-b3a2-46c6-91de-6ce275666f2d
- Pts
- Pts
- false
- 0
- 
                                  669
                                  257
                                  25
                                  23
                                
- 
                                  681.5
                                  268.75
                                
- Output parameter Crv
- 1b8d948b-eedb-4c3c-bfba-ceaee74ff110
- Crv
- Crv
- false
- 0
- 
                                  669
                                  280
                                  25
                                  22
                                
- 
                                  681.5
                                  291.25
                                
- Output parameter L
- 0d6fe24b-f96e-4e86-bad3-d29ae034394e
- L
- L
- false
- 0
- 
                                  669
                                  302
                                  25
                                  23
                                
- 
                                  681.5
                                  313.75
                                
- Output parameter W
- 816f49f4-39a6-4705-80c7-e2a924ac1e0c
- W
- W
- false
- 0
- 
                                  669
                                  325
                                  25
                                  22
                                
- 
                                  681.5
                                  336.25
                                
- Output parameter H
- b00909dc-b385-4e3e-a3a8-9e76efdaadeb
- H
- H
- false
- 0
- 
                                  669
                                  347
                                  25
                                  23
                                
- 
                                  681.5
                                  358.75
                                
- Output parameter A
- 9632d9b7-ad5c-4b42-bc41-5bf9a4af0115
- A
- A
- false
- 0
- 
                                  669
                                  370
                                  25
                                  22
                                
- 
                                  681.5
                                  381.25
                                
- Output parameter F
- 28c91c87-29e8-4bc8-a5ff-18aadc6f0ecd
- F
- F
- false
- 0
- 
                                  669
                                  392
                                  25
                                  23
                                
- 
                                  681.5
                                  403.75
                                
- 57da07bd-ecab-415d-9d86-af36d7073abc
- Number Slider
- Numeric slider for single values
- 19d4e5e6-a3fb-4e4d-b426-93c0b41f974c
- Number Slider
- width
- false
- 0
- 
                          158
                          312
                          384
                          20
                        
- 
                          158.3465
                          312.3785
                        
- 2
- 1
- 0
- 400
- -130
- 0
- 183.21
- 57da07bd-ecab-415d-9d86-af36d7073abc
- Number Slider
- Numeric slider for single values
- ce2f14ec-483c-4899-a8cb-784a62168957
- Number Slider
- length
- false
- 0
- 
                          158
                          285
                          385
                          20
                        
- 
                          158.0028
                          285.5286
                        
- 2
- 1
- 0
- 400
- 0
- 0
- 300
- fbac3e32-f100-4292-8692-77240a42fd1a
- Point
- Contains a collection of three-dimensional points
- true
- b2a67d0f-c66e-46a9-8efd-f7442d233d5d
- Point
- Pt
- false
- d4f9a77d-b3a2-46c6-91de-6ce275666f2d
- 1
- 
                          782
                          194
                          50
                          24
                        
- 
                          807.4574
                          206.2478
                        
- 59e0b89a-e487-49f8-bab8-b5bab16be14c
- Panel
- A panel for custom notes and text values
- 32bb1a9f-9575-4b8c-8a60-a65a7b9dd15f
- Panel
- false
- 0
- 2296b093-286c-438d-aa59-465d23147f1c
- 1
- Double click to edit panel content…
- 
                          855
                          408
                          105
                          55
                        
- 0
- 0
- 0
- 
                          855.6731
                          408.6088
                        
- 
                          255;255;250;90
                        
- true
- true
- true
- false
- false
- true
- 0d77c51e-584f-44e8-aed2-c2ddf4803888
- Degrees
- Convert an angle specified in radians to degrees
- 98102773-859e-4cf3-83a5-41f68379af66
- Degrees
- Deg
- 
                          754
                          421
                          64
                          28
                        
- 
                          784
                          435
                        
- Angle in radians
- f013de98-8461-42d6-94e2-d4f473814c3f
- Radians
- R
- false
- 9632d9b7-ad5c-4b42-bc41-5bf9a4af0115
- 1
- 
                              756
                              423
                              13
                              24
                            
- 
                              764
                              435
                            
- Angle in degrees
- 2296b093-286c-438d-aa59-465d23147f1c
- Degrees
- D
- false
- 0
- 
                              799
                              423
                              17
                              24
                            
- 
                              807.5
                              435
                            
- 3581f42a-9592-4549-bd6b-1c0fc39d067b
- Construct Point
- Construct a point from {xyz} coordinates.
- d68f5884-1ed1-4bd5-ab64-b7040370d59b
- Construct Point
- Pt
- 
                          392
                          101
                          67
                          64
                        
- 
                          423
                          133
                        
- {x} coordinate
- b9e9716b-aaed-4e63-90f0-fd69bffec388
- X coordinate
- X
- false
- 0
- 
                              394
                              103
                              14
                              20
                            
- 
                              402.5
                              113
                            
- 1
- 1
- {0}
- 0
- {y} coordinate
- 961e58c0-1cd5-49a0-8fd1-0e419a2c0b34
- Y coordinate
- Y
- false
- 0
- 
                              394
                              123
                              14
                              20
                            
- 
                              402.5
                              133
                            
- 1
- 1
- {0}
- 0
- {z} coordinate
- 54bdcf81-cd9a-447c-bad3-a55fe7ef5dc1
- Z coordinate
- Z
- false
- 0
- 
                              394
                              143
                              14
                              20
                            
- 
                              402.5
                              153
                            
- 1
- 1
- {0}
- 0
- Point coordinate
- 7451bc70-5fc3-43a3-bb48-ff10952414e7
- Point
- Pt
- false
- 0
- 
                              438
                              103
                              19
                              60
                            
- 
                              447.5
                              133
                            
- 3581f42a-9592-4549-bd6b-1c0fc39d067b
- Construct Point
- Construct a point from {xyz} coordinates.
- 8cd6ad76-7f71-4948-8c5e-9a3e2549985f
- Construct Point
- Pt
- 
                          392
                          173
                          67
                          64
                        
- 
                          423
                          205
                        
- {x} coordinate
- cc48fd1f-8953-40bd-a5f6-a9a203bcabd4
- X coordinate
- X
- false
- 95f9fd7f-37dc-4bd8-8105-7301ef052bdd
- 1
- 
                              394
                              175
                              14
                              20
                            
- 
                              402.5
                              185
                            
- 1
- 1
- {0}
- 80
- {y} coordinate
- a1e74152-bea6-4daf-a4cf-bbaa027d9769
- Y coordinate
- Y
- false
- 0
- 
                              394
                              195
                              14
                              20
                            
- 
                              402.5
                              205
                            
- 1
- 1
- {0}
- 0
- {z} coordinate
- e34fa320-f5a3-4aaf-beaf-4207678e6e88
- Z coordinate
- Z
- false
- 0
- 
                              394
                              215
                              14
                              20
                            
- 
                              402.5
                              225
                            
- 1
- 1
- {0}
- 0
- Point coordinate
- d5104343-e872-4369-9a14-a75a852c1a15
- Point
- Pt
- false
- 0
- 
                              438
                              175
                              19
                              60
                            
- 
                              447.5
                              205
                            
- d5967b9f-e8ee-436b-a8ad-29fdcecf32d5
- Curve
- Contains a collection of generic curves
- d53a1087-053a-44d5-b485-68a8b5d09ce4
- Curve
- Crv
- false
- 1b8d948b-eedb-4c3c-bfba-ceaee74ff110
- 1
- 
                          782
                          236
                          50
                          24
                        
- 
                          807.4463
                          248.7776
                        
- 17b7152b-d30d-4d50-b9ef-c9fe25576fc2
- XY Plane
- World XY plane.
- true
- cc8dfb80-5022-4b13-83c9-a787888900e8
- XY Plane
- XY
- 
                          474
                          246
                          64
                          28
                        
- 
                          505
                          260
                        
- Origin of plane
- 36223dd6-39d8-43d1-85f3-16523a2c0069
- Origin
- O
- false
- 0
- 
                              476
                              248
                              14
                              24
                            
- 
                              484.5
                              260
                            
- 1
- 1
- {0}
- 
                                      0
                                      0
                                      0
                                    
- World XY plane
- df7d1e6a-049f-4594-9fb2-7dda33d26e57
- Plane
- P
- false
- 0
- 
                              520
                              248
                              16
                              24
                            
- 
                              528
                              260
                            
- a4cd2751-414d-42ec-8916-476ebf62d7fe
- Radians
- Convert an angle specified in degrees to radians
- 072c5f2f-5efd-4587-8eb9-f4eacb6f59a9
- Radians
- Rad
- 
                          478
                          365
                          64
                          28
                        
- 
                          509
                          379
                        
- Angle in degrees
- 7201253d-ef74-40ae-8173-4b941b44547b
- Degrees
- D
- false
- 25d0b3b4-fc42-4433-a4bf-e70bfa828143
- 1
- 
                              480
                              367
                              14
                              24
                            
- 
                              488.5
                              379
                            
- Angle in radians
- c64ce2fc-64f4-4ffc-abb1-8343f67d6c30
- Radians
- R
- false
- 0
- 
                              524
                              367
                              16
                              24
                            
- 
                              532
                              379
                            
- 57da07bd-ecab-415d-9d86-af36d7073abc
- Number Slider
- Numeric slider for single values
- 25d0b3b4-fc42-4433-a4bf-e70bfa828143
- Number Slider
- angle °
- false
- 0
- 
                          160
                          370
                          295
                          20
                        
- 
                          160.2554
                          370.2197
                        
- 2
- 1
- 0
- 170
- 0
- 0
- 110.7
- c98a6015-7a2f-423c-bc66-bdc505249b45
- Plane 3Pt
- Create a plane through three points.
- true
- 78631b64-b599-490f-b493-9d449559b6c0
- Plane 3Pt
- Pl 3Pt
- 
                          -129
                          197
                          66
                          64
                        
- 
                          -98
                          229
                        
- Origin point
- c03438e8-8e89-47d2-b5c9-ca10c981173e
- Point A
- A
- false
- c318333b-fa9e-426b-b869-991ed69f1b64
- 1
- 
                              -127
                              199
                              14
                              20
                            
- 
                              -118.5
                              209
                            
- X-direction point
- 88046baa-f5c6-4fbc-97be-c88ee826709d
- Point B
- B
- false
- 5252af42-8b65-437c-a487-5eac1156e2cc
- 1
- 
                              -127
                              219
                              14
                              20
                            
- 
                              -118.5
                              229
                            
- Orientation point
- 9ece8cd3-edbb-4986-9f6d-886138f5abd4
- Point C
- C
- false
- f4cf1901-0cd0-4475-9dd6-bf34f5ebc6e1
- 1
- 
                              -127
                              239
                              14
                              20
                            
- 
                              -118.5
                              249
                            
- Plane definition
- af793683-207b-4276-a8a1-cc931d61589e
- Plane
- Pl
- false
- 0
- 
                              -83
                              199
                              18
                              60
                            
- 
                              -74
                              229
                            
- 3581f42a-9592-4549-bd6b-1c0fc39d067b
- Construct Point
- Construct a point from {xyz} coordinates.
- true
- 03b41596-1093-42df-8cb9-728ff4c83a73
- Construct Point
- Pt
- 
                          -281
                          116
                          67
                          64
                        
- 
                          -250
                          148
                        
- {x} coordinate
- 46b26c29-1295-4a56-90de-e2187690ca0a
- X coordinate
- X
- false
- 39c22776-a388-46d7-abe4-caaffd8004f9
- 1
- 
                              -279
                              118
                              14
                              20
                            
- 
                              -270.5
                              128
                            
- 1
- 1
- {0}
- 0
- {y} coordinate
- 05cdff1f-dab0-4d5c-8b53-f69ce1483ebc
- Y coordinate
- Y
- false
- 108fecb2-82c4-4ef7-b31a-2d6517c32268
- 1
- 
                              -279
                              138
                              14
                              20
                            
- 
                              -270.5
                              148
                            
- 1
- 1
- {0}
- 0
- {z} coordinate
- 1cd02656-25ae-4866-8098-c3757e985576
- Z coordinate
- Z
- false
- ca67e373-c39e-4d29-980d-1c76d91a2de9
- 1
- 
                              -279
                              158
                              14
                              20
                            
- 
                              -270.5
                              168
                            
- 1
- 1
- {0}
- 0
- Point coordinate
- c318333b-fa9e-426b-b869-991ed69f1b64
- Point
- Pt
- false
- 0
- 
                              -235
                              118
                              19
                              60
                            
- 
                              -225.5
                              148
                            
- 57da07bd-ecab-415d-9d86-af36d7073abc
- Number Slider
- Numeric slider for single values
- 39c22776-a388-46d7-abe4-caaffd8004f9
- Number Slider
- false
- 0
- 
                          -594
                          112
                          260
                          20
                        
- 
                          -593.6757
                          112.793
                        
- 2
- 1
- 0
- 50
- -50
- 0
- 24.03
- 57da07bd-ecab-415d-9d86-af36d7073abc
- Number Slider
- Numeric slider for single values
- 108fecb2-82c4-4ef7-b31a-2d6517c32268
- Number Slider
- false
- 0
- 
                          -593
                          139
                          258
                          20
                        
- 
                          -592.4278
                          139.043
                        
- 2
- 1
- 0
- 50
- -50
- 0
- -17.28
- 57da07bd-ecab-415d-9d86-af36d7073abc
- Number Slider
- Numeric slider for single values
- ca67e373-c39e-4d29-980d-1c76d91a2de9
- Number Slider
- false
- 0
- 
                          -592
                          164
                          258
                          20
                        
- 
                          -591.1778
                          164.043
                        
- 2
- 1
- 0
- 50
- -50
- 0
- -9.72
- 3581f42a-9592-4549-bd6b-1c0fc39d067b
- Construct Point
- Construct a point from {xyz} coordinates.
- true
- 7d81920e-fe3b-4fcc-856a-7444755fcc4a
- Construct Point
- Pt
- 
                          -284
                          208
                          67
                          64
                        
- 
                          -253
                          240
                        
- {x} coordinate
- 5e590f17-28b6-4fcb-aeb8-acdb345f0c4b
- X coordinate
- X
- false
- abfd65c5-05aa-4b81-a108-6a5355e6816a
- 1
- 
                              -282
                              210
                              14
                              20
                            
- 
                              -273.5
                              220
                            
- 1
- 1
- {0}
- 0
- {y} coordinate
- 7d22d623-e49c-4769-b49e-88c16b2a4f4e
- Y coordinate
- Y
- false
- 81a1d1b0-c109-4a52-8403-b06d094902c8
- 1
- 
                              -282
                              230
                              14
                              20
                            
- 
                              -273.5
                              240
                            
- 1
- 1
- {0}
- 0
- {z} coordinate
- 0fafe809-64a8-4448-af4b-21caa924776e
- Z coordinate
- Z
- false
- b53d373c-ad33-4aaa-a8de-83a088e127a5
- 1
- 
                              -282
                              250
                              14
                              20
                            
- 
                              -273.5
                              260
                            
- 1
- 1
- {0}
- 0
- Point coordinate
- 5252af42-8b65-437c-a487-5eac1156e2cc
- Point
- Pt
- false
- 0
- 
                              -238
                              210
                              19
                              60
                            
- 
                              -228.5
                              240
                            
- 57da07bd-ecab-415d-9d86-af36d7073abc
- Number Slider
- Numeric slider for single values
- abfd65c5-05aa-4b81-a108-6a5355e6816a
- Number Slider
- false
- 0
- 
                          -597
                          205
                          260
                          20
                        
- 
                          -596.1757
                          205.293
                        
- 2
- 1
- 0
- 50
- -50
- 0
- 3.28
- 57da07bd-ecab-415d-9d86-af36d7073abc
- Number Slider
- Numeric slider for single values
- 81a1d1b0-c109-4a52-8403-b06d094902c8
- Number Slider
- false
- 0
- 
                          -595
                          230
                          258
                          20
                        
- 
                          -594.9278
                          230.293
                        
- 2
- 1
- 0
- 50
- -50
- 0
- 0.25
- 57da07bd-ecab-415d-9d86-af36d7073abc
- Number Slider
- Numeric slider for single values
- b53d373c-ad33-4aaa-a8de-83a088e127a5
- Number Slider
- false
- 0
- 
                          -594
                          256
                          258
                          20
                        
- 
                          -593.6778
                          256.543
                        
- 2
- 1
- 0
- 50
- -50
- 0
- 18.96
- 3581f42a-9592-4549-bd6b-1c0fc39d067b
- Construct Point
- Construct a point from {xyz} coordinates.
- true
- 759d1f2d-c1de-45b6-9548-4d3ad4b27781
- Construct Point
- Pt
- 
                          -286
                          296
                          67
                          64
                        
- 
                          -255
                          328
                        
- {x} coordinate
- 0ec6b789-6c06-4ce4-a442-c0cdb61b63ea
- X coordinate
- X
- false
- f24c7c6f-3341-48d7-b5dd-11493225c086
- 1
- 
                              -284
                              298
                              14
                              20
                            
- 
                              -275.5
                              308
                            
- 1
- 1
- {0}
- 0
- {y} coordinate
- cadc8592-52b0-4c3f-9cd8-6474d8000ca7
- Y coordinate
- Y
- false
- 2313a88f-2ff0-48dc-b09b-dee536af8862
- 1
- 
                              -284
                              318
                              14
                              20
                            
- 
                              -275.5
                              328
                            
- 1
- 1
- {0}
- 0
- {z} coordinate
- 003f761f-6321-417a-9a6f-83613eba8698
- Z coordinate
- Z
- false
- da887b2c-91f5-4fc7-b9b2-dd3c06bf079f
- 1
- 
                              -284
                              338
                              14
                              20
                            
- 
                              -275.5
                              348
                            
- 1
- 1
- {0}
- 0
- Point coordinate
- f4cf1901-0cd0-4475-9dd6-bf34f5ebc6e1
- Point
- Pt
- false
- 0
- 
                              -240
                              298
                              19
                              60
                            
- 
                              -230.5
                              328
                            
- 57da07bd-ecab-415d-9d86-af36d7073abc
- Number Slider
- Numeric slider for single values
- f24c7c6f-3341-48d7-b5dd-11493225c086
- Number Slider
- false
- 0
- 
                          -598
                          294
                          260
                          20
                        
- 
                          -597.4257
                          294.043
                        
- 2
- 1
- 0
- 50
- -50
- 0
- -7.63
- 57da07bd-ecab-415d-9d86-af36d7073abc
- Number Slider
- Numeric slider for single values
- 2313a88f-2ff0-48dc-b09b-dee536af8862
- Number Slider
- false
- 0
- 
                          -597
                          319
                          258
                          20
                        
- 
                          -596.1778
                          319.043
                        
- 2
- 1
- 0
- 50
- -50
- 0
- -14.68
- 57da07bd-ecab-415d-9d86-af36d7073abc
- Number Slider
- Numeric slider for single values
- da887b2c-91f5-4fc7-b9b2-dd3c06bf079f
- Number Slider
- false
- 0
- 
                          -595
                          345
                          258
                          20
                        
- 
                          -594.9278
                          345.293
                        
- 2
- 1
- 0
- 50
- -50
- 0
- -6.5
- 57da07bd-ecab-415d-9d86-af36d7073abc
- Number Slider
- Numeric slider for single values
- 5137ef09-783f-4981-a9ec-aa4f2fc8e019
- Number Slider
- height
- false
- 0
- 
                          159
                          339
                          384
                          20
                        
- 
                          159.0849
                          339.4185
                        
- 2
- 1
- 0
- 200
- 0
- 0
- 112.83
- 59e0b89a-e487-49f8-bab8-b5bab16be14c
- Panel
- A panel for custom notes and text values
- 225afdb2-480f-435b-a1cb-84170b3afd2f
- Panel
- false
- 0
- 0d6fe24b-f96e-4e86-bad3-d29ae034394e
- 1
- Double click to edit panel content…
- 
                          737
                          288
                          106
                          38
                        
- 0
- 0
- 0
- 
                          737.476
                          288.175
                        
- 
                          255;255;250;90
                        
- true
- true
- true
- false
- false
- true
- 59e0b89a-e487-49f8-bab8-b5bab16be14c
- Panel
- A panel for custom notes and text values
- 20228f31-e357-4d65-8747-46e12348391c
- Panel
- false
- 0
- 816f49f4-39a6-4705-80c7-e2a924ac1e0c
- 1
- Double click to edit panel content…
- 
                          856
                          313
                          105
                          55
                        
- 0
- 0
- 0
- 
                          856.035
                          313.0428
                        
- 
                          255;255;250;90
                        
- true
- true
- true
- false
- false
- true
- 59e0b89a-e487-49f8-bab8-b5bab16be14c
- Panel
- A panel for custom notes and text values
- 7c2a1ac2-4916-4aa3-9b0a-566a67f36e60
- Panel
- false
- 0
- b00909dc-b385-4e3e-a3a8-9e76efdaadeb
- 1
- Double click to edit panel content…
- 
                          736
                          348
                          108
                          38
                        
- 0
- 0
- 0
- 
                          736.4249
                          348.559
                        
- 
                          255;255;250;90
                        
- true
- true
- true
- false
- false
- true
- aaa665bd-fd6e-4ccb-8d2c-c5b33072125d
- Curvature
- Evaluate the curvature of a curve at a specified parameter.
- true
- 40932656-6c80-4daa-9ad2-8cf8b338fc8d
- Curvature
- Curvature
- 
                          1151
                          798
                          65
                          64
                        
- 
                          1182
                          830
                        
- Curve to evaluate
- ef98c1a5-25c1-49b1-b59b-6afb9264b710
- Curve
- C
- false
- 12b4fe3c-7f43-444b-be77-19b89104763b
- 1
- 
                              1153
                              800
                              14
                              30
                            
- 
                              1161.5
                              815
                            
- Parameter on curve domain to evaluate
- bb19201b-82f6-46a3-968e-8457acb1864d
- Parameter
- t
- false
- 3dad486f-e4dc-4c1a-a3e3-edd2e0fd1459
- 1
- 
                              1153
                              830
                              14
                              30
                            
- 
                              1161.5
                              845
                            
- Point on curve at {t}
- 6666272a-5753-4a2f-bade-d2d52bc5e52d
- Point
- P
- false
- 0
- 
                              1197
                              800
                              17
                              20
                            
- 
                              1205.5
                              810
                            
- Curvature vector at {t}
- aa220db5-3068-4ca2-8821-8b9c90d1979a
- Curvature
- K
- false
- 0
- 
                              1197
                              820
                              17
                              20
                            
- 
                              1205.5
                              830
                            
- Curvature circle at {t}
- 10cf8192-1856-476a-b1e6-4b0f3c70a20b
- Curvature
- C
- false
- 0
- 
                              1197
                              840
                              17
                              20
                            
- 
                              1205.5
                              850
                            
- 6b021f56-b194-4210-b9a1-6cef3b7d0848
- Evaluate Length
- Evaluate a curve at a certain factor along its length. Length factors can be supplied both in curve units and normalized units. Change the [N] parameter to toggle between the two modes.
- true
- 7a3bf5ad-d8df-4c78-ab33-33f2a1b8fdd3
- Evaluate Length
- Eval
- 
                          1057
                          823
                          64
                          64
                        
- 
                          1088
                          855
                        
- Curve to evaluate
- 315efe79-3e18-4f12-9a9f-48c3fd619f70
- Curve
- C
- false
- 12b4fe3c-7f43-444b-be77-19b89104763b
- 1
- 
                              1059
                              825
                              14
                              20
                            
- 
                              1067.5
                              835
                            
- Length factor for curve evaluation
- 2bfe1d34-4f3b-4bb0-be9e-0296d2d11a85
- Length
- L
- false
- 6f2330d2-0e46-4e09-9ac5-7b7d2a1d3954
- 1
- 
                              1059
                              845
                              14
                              20
                            
- 
                              1067.5
                              855
                            
- 1
- 1
- {0}
- 0.5
- If True, the Length factor is normalized (0.0 ~ 1.0)
- 768df78b-ea9f-4024-8585-81b6a0c10891
- Normalized
- N
- false
- 0
- 
                              1059
                              865
                              14
                              20
                            
- 
                              1067.5
                              875
                            
- 1
- 1
- {0}
- true
- Point at the specified length
- d2445ed4-e075-4562-b765-47e17a5185ca
- Point
- P
- false
- 0
- 
                              1103
                              825
                              16
                              20
                            
- 
                              1111
                              835
                            
- Tangent vector at the specified length
- 5a606323-3c66-46dd-a374-a92dc7ab1c86
- Tangent
- T
- false
- 0
- 
                              1103
                              845
                              16
                              20
                            
- 
                              1111
                              855
                            
- Curve parameter at the specified length
- 3dad486f-e4dc-4c1a-a3e3-edd2e0fd1459
- Parameter
- t
- false
- 0
- 
                              1103
                              865
                              16
                              20
                            
- 
                              1111
                              875
                            
- 23862862-049a-40be-b558-2418aacbd916
- Deconstruct Arc
- Retrieve the base plane, radius and angle domain of an arc.
- true
- 55c865ff-19b4-4378-9996-badcb44a9589
- Deconstruct Arc
- DArc
- 
                          1267
                          847
                          65
                          64
                        
- 
                          1298
                          879
                        
- Arc or Circle to deconstruct
- e0a2a9c6-de9b-4ae3-854d-8bf414396827
- Arc
- A
- false
- 10cf8192-1856-476a-b1e6-4b0f3c70a20b
- 1
- 
                              1269
                              849
                              14
                              60
                            
- 
                              1277.5
                              879
                            
- Base plane of arc or circle
- 81d935f9-4a1b-49ca-b92c-718561d9b488
- Base Plane
- B
- false
- 0
- 
                              1313
                              849
                              17
                              20
                            
- 
                              1321.5
                              859
                            
- Radius of arc or circle
- 64504e23-6a31-41c8-aef7-9ea0c21e3465
- Radius
- R
- false
- 0
- 
                              1313
                              869
                              17
                              20
                            
- 
                              1321.5
                              879
                            
- Angle domain (in radians) of arc
- 3c6d7169-cc80-4199-8fef-ce0a92463c3a
- Angle
- A
- false
- 0
- 
                              1313
                              889
                              17
                              20
                            
- 
                              1321.5
                              899
                            
- 59e0b89a-e487-49f8-bab8-b5bab16be14c
- Panel
- A panel for custom notes and text values
- a04f3471-a7fc-4cd9-b101-bb6f71dec549
- Panel
- false
- 0
- 64504e23-6a31-41c8-aef7-9ea0c21e3465
- 1
- Double click to edit panel content…
- 
                          1377
                          830
                          96
                          42
                        
- 0
- 0
- 0
- 
                          1377.688
                          830.6463
                        
- 
                          255;255;250;90
                        
- true
- true
- true
- false
- false
- true
- f12daa2f-4fd5-48c1-8ac3-5dea476912ca
- Mirror
- Mirror an object.
- 864b9457-bf65-45dc-a49e-8e972abffb2b
- Mirror
- Mirror
- 
                          1277
                          665
                          65
                          44
                        
- 
                          1308
                          687
                        
- Base geometry
- ef1ac667-f8c6-4a26-800e-9f64490f8b70
- Geometry
- G
- true
- 12b4fe3c-7f43-444b-be77-19b89104763b
- 10cf8192-1856-476a-b1e6-4b0f3c70a20b
- 2
- 
                              1279
                              667
                              14
                              20
                            
- 
                              1287.5
                              677
                            
- Mirror plane
- fb82719d-d33e-4bcc-ab84-9035150adc96
- Plane
- P
- false
- 0654eb92-001e-43e0-b38a-58a5d0d80f8e
- 1
- 
                              1279
                              687
                              14
                              20
                            
- 
                              1287.5
                              697
                            
- 1
- 1
- {0}
- 
                                      0
                                      0
                                      0
                                      0
                                      0
                                      1
                                      1
                                      0
                                      0
                                    
- Mirrored geometry
- fef45908-0b4b-4554-b56b-334d7b9a07c0
- Geometry
- G
- false
- 0
- 
                              1323
                              667
                              17
                              20
                            
- 
                              1331.5
                              677
                            
- Transformation data
- b1d2e017-d6c1-487a-925f-7e6b3170b50c
- Transform
- X
- false
- 0
- 
                              1323
                              687
                              17
                              20
                            
- 
                              1331.5
                              697
                            
- 9df5e896-552d-4c8c-b9ca-4fc147ffa022
- Expression
- Evaluate an expression
- x*2
- 8a2af1f2-b070-42bc-acff-393a560d94c6
- Expression
- Expression
- 
                          1379
                          892
                          84
                          28
                        
- 
                          1419
                          906
                        
- 1
- ba80fd98-91a1-4958-b6a7-a94e40e52bdb
- 1
- 8ec86459-bf01-4409-baee-174d0d2b13d0
- Expression variable
- 9378e904-7029-4099-9a7d-0a61740c8db5
- Variable x
- x
- true
- 64504e23-6a31-41c8-aef7-9ea0c21e3465
- 1
- 
                                  1381
                                  894
                                  12
                                  24
                                
- 
                                  1388.5
                                  906
                                
- Result of expression
- ae803c56-82b6-4b49-9bf4-1997a330a545
- Result
- R
- false
- 0
- 
                                  1445
                                  894
                                  16
                                  24
                                
- 
                                  1453
                                  906
                                
- 59e0b89a-e487-49f8-bab8-b5bab16be14c
- Panel
- A panel for custom notes and text values
- 7ff6881c-7677-4071-a632-b6c8ea1ac4d3
- Panel
- false
- 0
- ae803c56-82b6-4b49-9bf4-1997a330a545
- 1
- Double click to edit panel content…
- 
                          1489
                          887
                          96
                          42
                        
- 0
- 0
- 0
- 
                          1489.256
                          887.1902
                        
- 
                          255;255;250;90
                        
- true
- true
- true
- false
- false
- true
- 59e0b89a-e487-49f8-bab8-b5bab16be14c
- Panel
- A panel for custom notes and text values
- 0068d51d-c81e-4187-8df3-5835ab363a73
- Panel
- false
- 0
- 0
- 71.7
- 
                          486
                          1016
                          50
                          20
                        
- 0
- 0
- 0
- 
                          486.351
                          1016.602
                        
- 
                          255;255;250;90
                        
- true
- true
- true
- false
- false
- true
- 59e0b89a-e487-49f8-bab8-b5bab16be14c
- Panel
- A panel for custom notes and text values
- 65023053-5666-4c0b-b753-08fe81bad98b
- Panel
- false
- 0
- 0
- 0.09
- 
                          51
                          1103
                          50
                          20
                        
- 0
- 0
- 0
- 
                          51.64487
                          1103.176
                        
- 
                          255;255;250;90
                        
- true
- true
- true
- false
- false
- true
- 59e0b89a-e487-49f8-bab8-b5bab16be14c
- Panel
- A panel for custom notes and text values
- b958296d-1f29-45e4-a204-834500f3a2c8
- Panel
- false
- 0
- 0
- 0.0055
- 
                          50
                          1130
                          62
                          20
                        
- 0
- 0
- 0
- 
                          50.66486
                          1130.595
                        
- 
                          255;255;250;90
                        
- true
- true
- true
- false
- false
- true
- 9df5e896-552d-4c8c-b9ca-4fc147ffa022
- Expression
- Evaluate an expression
- π*(outer^4-(outer-thick)^4)/32
- c6fb6177-2d5c-4ea6-801e-f1d602a9945f
- Expression
- Expression
- 
                          197
                          1105
                          324
                          44
                        
- 
                          366
                          1127
                        
- 2
- ba80fd98-91a1-4958-b6a7-a94e40e52bdb
- ba80fd98-91a1-4958-b6a7-a94e40e52bdb
- 1
- 8ec86459-bf01-4409-baee-174d0d2b13d0
- Expression variable
- cf3ef3e5-5024-4f5c-a4c6-0baf27546401
- Variable outer
- outer
- true
- 65023053-5666-4c0b-b753-08fe81bad98b
- 1
- 
                                  199
                                  1107
                                  30
                                  20
                                
- 
                                  215.5
                                  1117
                                
- Expression variable
- 275aff5f-fca5-430e-bd77-af734dc26d01
- Variable thick
- thick
- true
- b958296d-1f29-45e4-a204-834500f3a2c8
- 1
- 
                                  199
                                  1127
                                  30
                                  20
                                
- 
                                  215.5
                                  1137
                                
- Result of expression
- c29e43b1-f147-4596-9a27-65e202efbf44
- Result
- R
- false
- 0
- 
                                  503
                                  1107
                                  16
                                  40
                                
- 
                                  511
                                  1127
                                
- 59e0b89a-e487-49f8-bab8-b5bab16be14c
- Panel
- A panel for custom notes and text values
- 61e14a85-7063-4c93-bec1-f130a2a79f94
- Panel
- false
- 0
- 20b5374e-e220-4840-8424-dcf1b57d3ad2
- 1
- Double click to edit panel content…
- 
                          744
                          1065
                          97
                          58
                        
- 0
- 0
- 0
- 
                          744.1909
                          1065.401
                        
- 
                          255;255;250;90
                        
- true
- true
- true
- false
- false
- true
- d5967b9f-e8ee-436b-a8ad-29fdcecf32d5
- Curve
- Contains a collection of generic curves
- 9ce607e3-994c-4bda-99e3-6e421454263b
- Curve
- Crv
- false
- 10cf8192-1856-476a-b1e6-4b0f3c70a20b
- 1
- 
                          1303
                          728
                          50
                          24
                        
- 
                          1328.596
                          740.7537
                        
- 7f5c6c55-f846-4a08-9c9a-cfdc285cc6fe
- Scribble
- true
- 
                      147.2881
                      1085.861
                    
- 
                      504.9157
                      1084.888
                    
- 
                      504.9566
                      1099.915
                    
- 
                      147.329
                      1100.889
                    
- A quick note
- Microsoft Sans Serif
- a2b3599b-d7ad-4dff-aca4-d6dbc30755af
- false
- Scribble
- Scribble
- 16
- area moment of inertia for a hollow rod (in m^4)
- 
                          142.2881
                          1079.888
                          367.6685
                          26.00085
                        
- 
                          147.2881
                          1085.861
                        
- 7f5c6c55-f846-4a08-9c9a-cfdc285cc6fe
- Scribble
- true
- 
                      544.7806
                      1376.747
                    
- 
                      735.764
                      1376.736
                    
- 
                      735.7651
                      1391.763
                    
- 
                      544.7817
                      1391.774
                    
- A quick note
- Microsoft Sans Serif
- 37f949de-70f1-4437-96b3-797739d591c1
- false
- Scribble
- Scribble
- 16
- One height, two solutions
- 
                          539.7806
                          1371.736
                          200.9845
                          25.03821
                        
- 
                          544.7806
                          1376.747
                        
- 079bd9bd-54a0-41d4-98af-db999015f63d
- VB Script
-   Private Function IsSet(ByVal param As String) As Boolean  ' Check if an input parameter has data
    Dim i As Integer = Component.Params.IndexOfInputParam(param)
    If i > -1 Then
      Return Component.Params.Input.ElementAt(i).DataType > 1  ' input parameter DataType of 1 means it's not receiving input (internal or external)
    Else
      Msg("error", "Input parameter '" & param & "' not found")
      Return False
    End If
  End Function
  Private Sub Msg(ByVal type As String, ByVal msg As String)  ' Output an error, warning, or informational message
    Select Case type
      Case "error"
        Component.AddRuntimeMessage(GH_RuntimeMessageLevel.Error, msg)
        Print("Error: " & msg)
      Case "warning"
        Component.AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, msg)
        Print("Warning: " & msg)
      Case "info"
        Component.AddRuntimeMessage(GH_RuntimeMessageLevel.Remark, msg)
        Print(msg)
    End Select
  End Sub
  ' Solve for the m parameter from length and width (reference {1} equation (34), except b = width and K(k) and E(k) should be K(m) and E(m))
  Private Function SolveMFromLenWid(ByVal L As Double, ByVal w As Double) As Double
    If w = 0 Then
      Return Defined.M_ZERO_W  ' for the boundry condition width = 0, bypass the function and return the known m value
    End If
    Dim n As Integer = 1 ' Iteration counter (quit if >MAXIT)
    Dim lower As Double = 0 ' m must be within this range
    Dim upper As Double = 1
    Dim m As Double
    Dim cwl As Double
    Do While (upper - lower) > Defined.MAXERR AndAlso (n) < Defined.MAXIT ' Repeat until range narrow enough or MAXIT
      m = (upper + lower) / 2
      cwl = 2 * EllipticE(m) / EllipticK(m) - 1  ' calculate w/L with the test value of m
      If cwl < w / L Then  ' compares the calculated w/L with the actual w/L then narrows the range of possible m
        upper = m
      Else
        lower = m
      End If
      n += 1
    Loop
    Return m
  End Function
  ' Solve for the m parameter from length and height (reference {1} equation (33), except K(k) should be K(m) and k = sqrt(m))
  ' Note that it's actually possible to find 2 valid values for m (hence 2 width values) at certain height values
  Private Function SolveMFromLenHt(ByVal L As Double, ByVal h As Double) As List(Of Double)
    Dim n As Integer = 1 ' Iteration counter (quit if >MAXIT)
    Dim lower As Double = 0 ' m must be within this range
    Dim upper As Double = 1
    Dim twoWidths As Boolean = h / L >= Defined.DOUBLE_W_HL_RATIO And h / L < Defined.MAX_HL_RATIO  ' check to see if h/L is within the range where 2 solutions for the width are possible
    Dim m As Double
    Dim mult_m As New List(Of Double)
    Dim chl As Double
    If twoWidths Then
      ' find the first of two possible solutions for m with the following limits:
      lower = Defined.M_DOUBLE_W  ' see constants at bottom of script
      upper = Defined.M_MAXHEIGHT  ' see constants at bottom of script
      Do While (upper - lower) > Defined.MAXERR AndAlso (n) < Defined.MAXIT ' Repeat until range narrow enough or MAXIT
        m = (upper + lower) / 2
        chl = Math.Sqrt(m) / EllipticK(m)  ' calculate h/L with the test value of m
        If chl > h / L Then  ' compares the calculated h/L with the actual h/L then narrows the range of possible m
          upper = m
        Else
          lower = m
        End If
        n += 1
      Loop
      mult_m.Add(m)
      ' then find the second of two possible solutions for m with the following limits:
      lower = Defined.M_MAXHEIGHT  ' see constants at bottom of script
      upper = 1
      Do While (upper - lower) > Defined.MAXERR AndAlso (n) < Defined.MAXIT ' Repeat until range narrow enough or MAXIT
        m = (upper + lower) / 2
        chl = Math.Sqrt(m) / EllipticK(m)  ' calculate h/L with the test value of m
        If chl < h / L Then  ' compares the calculated h/L with the actual h/L then narrows the range of possible m
          upper = m
        Else
          lower = m
        End If
        n += 1
      Loop
      If m <= Defined.M_MAX Then  ' return this m parameter only if it falls within the maximum useful value (above which the curve breaks down)
        mult_m.Add(m)
      End If
    Else
      ' find the one possible solution for the m parameter
      upper = Defined.M_DOUBLE_W  ' limit the upper end of the search to the maximum value of m for which only one solution exists
      Do While (upper - lower) > Defined.MAXERR AndAlso (n) < Defined.MAXIT ' Repeat until range narrow enough or MAXIT
        m = (upper + lower) / 2
        chl = Math.Sqrt(m) / EllipticK(m)  ' calculate h/L with the test value of m
        If chl > h / L Then  ' compares the calculated h/L with the actual h/L then narrows the range of possible m
          upper = m
        Else
          lower = m
        End If
        n += 1
      Loop
      mult_m.Add(m)
    End If
    Return mult_m
  End Function
  ' Solve for the m parameter from width and height (derived from reference {1} equations (33) and (34) with same notes as above)
  Private Function SolveMFromWidHt(ByVal w As Double, ByVal h As Double) As Double
    Dim n As Integer = 1 ' Iteration counter (quit if >MAXIT)
    Dim lower As Double = 0 ' m must be within this range
    Dim upper As Double = 1
    Dim m As Double
    Dim cwh As Double
    Do While (upper - lower) > Defined.MAXERR AndAlso (n) < Defined.MAXIT ' Repeat until range narrow enough or MAXIT
      m = (upper + lower) / 2
      cwh = (2 * EllipticE(m) - EllipticK(m)) / Math.Sqrt(m)  ' calculate w/h with the test value of m
      If cwh < w / h Then  ' compares the calculated w/h with the actual w/h then narrows the range of possible m
        upper = m
      Else
        lower = m
      End If
      n += 1
    Loop
    Return m
  End Function
  ' Calculate length based on height and an m parameter, derived from reference {1} equation (33), except K(k) should be K(m) and k = sqrt(m)
  Private Function Cal_L(ByVal h As Double, ByVal m As Double) As Double
    Return h * EllipticK(m) / Math.Sqrt(m)
  End Function
  ' Calculate width based on length and an m parameter, derived from reference {1} equation (34), except b = width and K(k) and E(k) should be K(m) and E(m)
  Private Function Cal_W(ByVal L As Double, ByVal m As Double) As Double
    Return L * (2 * EllipticE(m) / EllipticK(m) - 1)
  End Function
  ' Calculate height based on length and an m parameter, from reference {1} equation (33), except K(k) should be K(m) and k = sqrt(m)
  Private Function Cal_H(ByVal L As Double, ByVal m As Double) As Double
    Return L * Math.Sqrt(m) / EllipticK(m)
  End Function
  ' Calculate the unique m parameter based on a start tangent angle, from reference {2}, just above equation (9a), that states k = Sin(angle / 2 + Pi / 4),
  ' but as m = k^2 and due to this script's need for an angle rotated 90° versus the one in reference {1}, the following formula is the result
  ' New note: verified by reference {4}, pg. 78 at the bottom
  Private Function Cal_M(ByVal a As Double) As Double
    Return (1 - Math.Cos(a)) / 2  ' equal to Sin^2(a/2) too
  End Function
  ' Calculate start tangent angle based on an m parameter, derived from above formula
  Private Function Cal_A(ByVal m As Double) As Double
    Return Math.Acos(1 - 2 * m)
  End Function
  ' This is the heart of this script, taking the found (or specified) length, width, and angle values along with the found m parameter to create
  ' a list of points that approximate the shape or form of the elastica. It works by finding the x and y coordinates (which are reversed versus
  ' the original equations (12a) and (12b) from reference {2} due to the 90° difference in orientation) based on the tangent angle along the curve.
  ' See reference {2} for more details on how they derived it. Note that to simplify things, the algorithm only calculates the points for half of the
  ' curve, then mirrors those points along the y-axis.
  Private Function FindBendForm(ByVal L As Double, ByVal w As Double, ByVal m As Double, ByVal ang As Double, ByVal refPln As Plane) As List(Of Point3d)
    L = L / 2  ' because the below algorithm is based on the formulas in reference {2} for only half of the curve
    w = w / 2  ' same
    If ang = 0 Then  ' if angle (and height) = 0, then simply return the start and end points of the straight line
      Dim out As New List(Of Point3d)
      out.Add(refPln.PointAt(w, 0, 0))
      out.Add(refPln.PointAt(-w, 0, 0))
      Return out
    End If
    Dim x As Double
    Dim y As Double
    Dim halfCurvePts As New List(Of Point3d)
    Dim fullCurvePts As New List(Of Point3d)
    Dim translatedPts As New List(Of Point3d)
    ang -= Math.PI / 2  ' a hack to allow this algorithm to work, since the original curve in paper {2} was rotated 90°
    Dim angB As Double = ang + (-Math.PI / 2 - ang) / Defined.CURVEDIVS  ' angB is the 'lowercase theta' which should be in formula {2}(12b) as the interval
    ' start [a typo...see equation(3)]. It's necessary to start angB at ang + [interval] instead of just ang due to integration failing at angB = ang
    halfCurvePts.Add(New Point3d(w, 0, 0))  ' start with this known initial point, as integration will fail when angB = ang
    ' each point {x, y} is calculated from the tangent angle, angB, that occurs at each point (which is why this iterates from ~ang to -pi/2, the known end condition)
    Do While Math.Round(angB, Defined.ROUNDTO) >= Math.Round(-Math.PI / 2, Defined.ROUNDTO)
      y = (Math.Sqrt(2) * Math.Sqrt(Math.Sin(ang) - Math.Sin(angB)) * (w + L)) / (2 * EllipticE(m))  ' note that x and y are swapped vs. (12a) and (12b)
      x = (L / (Math.Sqrt(2) * EllipticK(m))) * Simpson(angB, -Math.PI / 2, 500, ang)  ' calculate the Simpson approximation of the integral (function f below)
      ' over the interval angB ('lowercase theta') to -pi/2. side note: is 500 too few iterations for the Simson algorithm?
      If Math.Round(x, Defined.ROUNDTO) = 0 Then x = 0
      halfCurvePts.Add(New Point3d(x, y, 0))
      angB += (-Math.PI / 2 - ang) / Defined.CURVEDIVS  ' onto the next tangent angle
    Loop
    ' After finding the x and y values for half of the curve, add the {-x, y} values for the rest of the curve
    For Each point As Point3d In halfCurvePts
      If Math.Round(point.X, Defined.ROUNDTO) = 0 Then
        If Math.Round(point.Y, Defined.ROUNDTO) = 0 Then
          fullCurvePts.Add(New Point3d(0, 0, 0))  ' special case when width = 0: when x = 0, only duplicate the point when y = 0 too
        End If
      Else
        fullCurvePts.Add(New Point3d(-point.X, point.Y, 0))
      End If
    Next
    halfCurvePts.Reverse
    fullCurvePts.AddRange(halfCurvePts)
    For Each p As Point3d In fullCurvePts
      translatedPts.Add(refPln.PointAt(p.X, p.Y, p.Z))  ' translate the points from the reference plane to the world plane
    Next
    Return translatedPts
  End Function
  ' Interpolates the points from FindBendForm to create the Elastica curve. Uses start & end tangents for greater accuracy.
  Private Function MakeCurve(ByVal pts As List(Of Point3d), ByVal ang As Double, ByVal refPln As Plane) As Curve
    If ang <> 0 Then
      Dim ts, te As New Vector3d(refPln.XAxis)
      ts.Rotate(ang, refPln.ZAxis)
      te.Rotate(-ang, refPln.ZAxis)
      Return Curve.CreateInterpolatedCurve(pts, 3, CurveKnotStyle.Chord, ts, te)  ' 3rd degree curve with 'Chord' Knot Style
    Else
      Return Curve.CreateInterpolatedCurve(pts, 3)  ' if angle (and height) = 0, then simply interpolate the straight line (no start/end tangents)
    End If
  End Function
  ' Implements the Simpson approximation for an integral of function f below
  Public Function Simpson(a As Double, b As Double, n As Integer, theta As Double) As Double 'n should be an even number
    Dim j As Integer, s1 As Double, s2 As Double, h As Double
    h = (b - a) / n
    s1 = 0
    s2 = 0
    For j = 1 To n - 1 Step 2
      s1 = s1 + fn(a + j * h, theta)
    Next j
    For j = 2 To n - 2 Step 2
      s2 = s2 + fn(a + j * h, theta)
    Next j
    Simpson = h / 3 * (fn(a, theta) + 4 * s1 + 2 * s2 + fn(b, theta))
  End Function
  ' Specific calculation for the above integration
  Public Function fn(x As Double, theta As Double) As Double
    fn = Math.Sin(x) / (Math.Sqrt(Math.Sin(theta) - Math.Sin(x)))  ' from reference {2} formula (12b)
  End Function
  ' Return the Complete Elliptic integral of the 1st kind
  ' Abramowitz and Stegun p.591, formula 17.3.11
  ' Code from http://www.codeproject.com/Articles/566614/Elliptic-integrals
  Public Function EllipticK(ByVal m As Double) As Double
    Dim sum, term, above, below As Double
    sum = 1
    term = 1
    above = 1
    below = 2
    For i As Integer = 1 To 100
      term *= above / below
      sum += Math.Pow(m, i) * Math.Pow(term, 2)
      above += 2
      below += 2
    Next
    sum *= 0.5 * Math.PI
    Return sum
  End Function
  ' Return the Complete Elliptic integral of the 2nd kind
  ' Abramowitz and Stegun p.591, formula 17.3.12
  ' Code from http://www.codeproject.com/Articles/566614/Elliptic-integrals
  Public Function EllipticE(ByVal m As Double) As Double
    Dim sum, term, above, below As Double
    sum = 1
    term = 1
    above = 1
    below = 2
    For i As Integer = 1 To 100
      term *= above / below
      sum -= Math.Pow(m, i) * Math.Pow(term, 2) / above
      above += 2
      below += 2
    Next
    sum *= 0.5 * Math.PI
    Return sum
  End Function
  Friend Partial NotInheritable Class Defined
    Private Sub New()
    End Sub
    ' Note: most of these values for m and h/L ratio were found with Wolfram Alpha and either specific intercepts (x=0) or local minima/maxima. They should be constant.
    Public Const M_SKETCHY As Double = 0.95  ' value of the m parameter where the curvature near the ends of the curve gets wonky
    Public Const M_MAX As Double = 0.993  ' maximum useful value of the m parameter, above which this algorithm for the form of the curve breaks down
    Public Const M_ZERO_W As Double = 0.826114765984970336  ' value of the m parameter when width = 0
    Public Const M_MAXHEIGHT As Double = 0.701327460663101223  ' value of the m parameter at maximum possible height of the bent rod/wire
    Public Const M_DOUBLE_W As Double = 0.180254422335013983  ' minimum value of the m parameter when two width values are possible for a given height and length
    Public Const DOUBLE_W_HL_RATIO As Double = 0.257342117984635757  ' value of the height/length ratio above which there are two possible width values
    Public Const MAX_HL_RATIO As Double = 0.403140189705650243  ' maximum possible value of the height/length ratio
    Public Const MAXERR As Double = 0.0000000001  ' error tolerance
    Public Const MAXIT As Integer = 100  ' maximum number of iterations
    Public Const ROUNDTO As Integer = 10  ' number of decimal places to round off to
    Public Const CURVEDIVS As Integer = 50  ' number of sample points for building the curve (or half-curve as it were)
  End Class
- A VB.NET scriptable component
- 
                      98
                      86
                    
- true
- 34e9c6ff-5f0a-453a-89bb-504c40c19604
- VB Script
- VB
- true
- 0
-     ' -----------------------------------------------------------------
    ' Elastic Bending Script by Will McElwain
    ' Created February 2014
    '
    ' DESCRIPTION:
    ' This beast creates the so-called 'elastica curve', the shape a long, thin rod or wire makes when it is bent elastically (i.e. not permanently). In this case, force
    ' is assumed to only be applied horizontally (which would be in line with the rod at rest) and both ends are assumed to be pinned or hinged meaning they are free
    ' to rotate (as opposed to clamped, when the end tangent angle is fixed, usually horizontally). An interesting finding is that it doesn't matter what the material or
    ' cross-sectional area is, as long as they're uniform along the entire length. Everything makes the same shape when bent as long as it doesn't cross the threshold
    ' from elastic to plastic (permanent) deformation (I don't bother to find that limit here, but can be found if the yield stress for a material is known).
    '
    ' Key to the formulas used in this script are elliptic integrals, specifically K(m), the complete elliptic integral of the first kind, and E(m), the complete elliptic
    ' integral of the second kind. There was a lot of confusion over the 'm' and 'k' parameters for these functions, as some people use them interchangeably, but they are
    ' not the same. m = k^2 (thus k = Sqrt(m)). I try to use the 'm' parameter exclusively to avoid this confusion. Note that there is a unique 'm' parameter for every
    ' configuration/shape of the elastica curve.
    '
    ' This script tries to find that unique 'm' parameter based on the inputs. The algorithm starts with a test version of m, evaluates an expression, say 2*E(m)/K(m)-1,
    ' then compares the result to what it should be (in this case, a known width/length ratio). Iterate until the correct m is found. Once we have m, we can then calculate
    ' all of the other unknowns, then find points that lie on that curve, then interpolate those points for the actual curve. You can also use Wolfram|Alpha as I did to
    ' find the m parameter based on the equations in this script (example here: http://tiny.cc/t4tpbx for when say width=45.2 and length=67.1).
    '
    ' Other notes:
    ' * This script works with negative values for width, which will creat a self-intersecting curve (as it should). The curvature of the elastica starts to break down around
    ' m=0.95 (~154°), but this script will continue to work until M_MAX, m=0.993 (~169°). If you wish to ignore self-intersecting curves, set ignoreSelfIntersecting to True
    ' * When the only known values are length and height, it is actually possible for certain ratios of height to length to have two valid m values (thus 2 possible widths
    ' and angles). This script will return them both.
    ' * Only the first two valid parameters (of the required ones) will be used, meaning if all four are connected (length, width or a PtB, height, and angle), this script will
    ' only use length and width (or a PtB).
    ' * Depending on the magnitude of your inputs (say if they're really small, like if length < 10), you might have to increase the constant ROUNDTO at the bottom
    '
    ' REFERENCES:
    ' {1} "The elastic rod" by M.E. Pacheco Q. & E. Pina, http://www.scielo.org.mx/pdf/rmfe/v53n2/v53n2a8.pdf
    ' {2} "An experiment in nonlinear beam theory" by A. Valiente, http://www.deepdyve.com/lp/doc/I3lwnxdfGz , also here: http://tiny.cc/Valiente_AEiNBT
    ' {3} "Snap buckling, writhing and Loop formation In twisted rods" by V.G.A. GOSS, http://myweb.lsbu.ac.uk/~gossga/thesisFinal.pdf
    ' {4} "Theory of Elastic Stability" by Stephen Timoshenko, http://www.scribd.com/doc/50402462/Timoshenko-Theory-of-Elastic-Stability  (start on p. 76)
    '
    ' INPUT:
    ' PtA - First anchor point (required)
    ' PtB - Second anchor point (optional, though 2 out of the 4--length, width, height, angle--need to be specified)
    '       [note that PtB can be the same as PtA (meaning width would be zero)]
    '       [also note that if a different width is additionally specified that's not equal to the distance between PtA and PtB, then the end point will not equal PtB anymore]
    ' Pln - Plane of the bent rod/wire, which bends up in the +y direction. The line between PtA and PtB (if specified) must be parallel to the x-axis of this plane
    '
    ' ** 2 of the following 4 need to be specified **
    ' Len - Length of the rod/wire, which needs to be > 0
    ' Wid - Width between the endpoints of the curve [note: if PtB is specified in addition, and distance between PtA and PtB <> width, the end point will be relocated
    ' Ht - Height of the bent rod/wire (when negative, curve will bend downward, relative to the input plane, instead)
    ' Ang - Inner departure angle or tangent angle (in radians) at the ends of the bent rod/wire. Set up so as width approaches length (thus height approaches zero), angle approaches zero
    '
    ' * Following variables only needed for optional calculating of bending force, not for shape of curve.
    ' E - Young's modulus (modulus of elasticity) in GPa (=N/m^2) (material-specific. for example, 7075 aluminum is roughly 71.7 GPa)
    ' I - Second moment of area (or area moment of inertia) in m^4 (cross-section-specific. for example, a hollow rod
    '     would have I = pi * (outer_diameter^4 - inner_diameter^4) / 32
    ' Note: E*I is also known as flexural rigidity or bending stiffness
    '
    ' OUTPUT:
    ' out - only for debugging messages
    ' Pts - the list of points that approximate the shape of the elastica
    ' Crv - the 3rd-degree curve interpolated from those points (with accurate start & end tangents)
    ' L - the length of the rod/wire
    ' W - the distance (width) between the endpoints of the rod/wire
    ' H - the height of the bent rod/wire
    ' A - the tangent angle at the (start) end of the rod/wire
    ' F - the force needed to hold the rod/wire in a specific shape (based on the material properties & cross-section) **be sure your units for 'I' match your units for the
    ' rest of your inputs (length, width, etc.). Also note that the critical buckling load (force) that makes the rod/wire start to bend can be found at height=0
    '
    ' THANKS TO:
    ' Mårten Nettelbladt (thegeometryofbending.blogspot.com)
    ' Daniel Piker (Kangaroo plugin)
    ' David Rutten (Grasshopper guru)
    ' Euler & Bernoulli (the O.G.'s)
    '
    ' -----------------------------------------------------------------
    Dim ignoreSelfIntersecting As Boolean = False  ' set to True if you don't want to output curves where width < 0, which creates a self-intersecting curve
    Dim inCt As Integer = 0  ' count the number of required parameters that are receiving data
    Dim length As Double
    Dim width As System.Object = Nothing  ' need to set as Nothing so we can check if it has been assigned a value later
    Dim height As Double
    Dim angle As Double
    Dim m As Double
    Dim multiple_m As New List(Of Double)
    Dim AtoB As Line
    Dim flip_H As Boolean = False  ' if height is negative, this flag will be set
    Dim flip_A As Boolean = False  ' if angle is negative, this flag will be set
    If Not IsSet("Pln") Then
      Msg("error", "Base plane is not set")
      Return
    End If
    If Not IsSet("PtA") Then
      Msg("error", "Point A is not set")
      Return
    End If
    If Math.Round(Pln.DistanceTo(PtA), Defined.ROUNDTO) <> 0 Then
      Msg("error", "Point A is not on the base plane")
      Return
    End If
    Dim refPlane As Plane = Pln  ' create a reference plane = input plane and set the origin of it to PtA in case PtA isn't the origin already
    refPlane.Origin = PtA
    If IsSet("PtB") Then
      If Math.Round(Pln.DistanceTo(PtB), Defined.ROUNDTO) <> 0 Then
        Msg("error", "Point B is not on the base plane")
        Return
      End If
      AtoB = New Line(PtA, PtB)
      If AtoB.Length <> 0 And Not AtoB.Direction.IsPerpendicularTo(Pln.YAxis) Then
        Msg("error", "The line between PtA and PtB is not perpendicular to the Y-axis of the specified plane")
        Return
      End If
      inCt += 1
      If IsSet("Wid") Then Msg("info", "Wid will override the distance between PtA and PtB. If you do not want this to happen, disconnect PtB or Wid.")
      width = PtA.DistanceTo(PtB)  ' get the width (distance) between PtA and PtB
      
      Dim refPtB As Point3d
      refPlane.RemapToPlaneSpace(PtB, refPtB)
      If refPtB.X < 0 Then width = -width  ' check if PtB is to the left of PtA...if so, width is negative
    End If
    If IsSet("Len") Then inCt += 1
    If IsSet("Wid") Then inCt += 1
    If IsSet("Ht") Then inCt += 1
    If IsSet("Ang") Then inCt += 1
    If inCt > 2 Then Msg("info", "More parameters set than are required (out of length, width, height, angle). Only using the first two valid ones.")
    ' check for connected/specified inputs. note: only the first two that it comes across will be used
    If IsSet("Len") Then  ' if length is specified then...
      If Len <= 0 Then
        Msg("error", "Length cannot be negative or zero")
        Return
      End If
      If IsSet("Wid") Then  ' find height & angle based on length and specified width
        If Wid > Len Then
          Msg("error", "Width is greater than length")
          Return
        End If
        If Wid = Len Then  ' skip the solver and set the known values
          height = 0
          m = 0
          angle = 0
          width = Wid
        Else
          m = SolveMFromLenWid(Len, Wid)
          height = Cal_H(Len, m)  ' L * Sqrt(m) / K(m)
          angle = Cal_A(m)  ' Acos(1 - 2 * m)
          width = Wid
        End If
      Else If width IsNot Nothing Then  ' find height & angle based on length and calculated width (distance between PtA and PtB)
        If width > Len Then
          Msg("error", "Width is greater than length")
          Return
        End If
        If width = Len Then  ' skip the solver and set the known values
          height = 0
          m = 0
          angle = 0
        Else
          m = SolveMFromLenWid(Len, width)
          height = Cal_H(Len, m)  ' L * Sqrt(m) / K(m)
          angle = Cal_A(m)  ' Acos(1 - 2 * m)
        End If
      Else If IsSet("Ht") Then  ' find width & angle based on length and height  ** possible to return 2 results **
        If Math.Abs(Ht / Len) > Defined.MAX_HL_RATIO Then
          Msg("error", "Height not possible with given length")
          Return
        End If
        If Ht < 0 Then
          Ht = -Ht  ' if height is negative, set it to positive (for the calculations) but flip the reference plane about its x-axis
          refPlane.Transform(Transform.Mirror(New Plane(refPlane.Origin, refPlane.XAxis, refPlane.ZAxis)))
          flip_A = True
          flip_H = True
        End If
        If Ht = 0 Then  ' skip the solver and set the known values
          width = Len
          angle = 0
        Else
          multiple_m = SolveMFromLenHt(Len, Ht)  ' note that it's possible for two values of m to be found if height is close to max height
          If multiple_m.Count = 1 Then  ' if there's only one m value returned, calculate the width & angle here. we'll deal with multiple m values later
            m = multiple_m.Item(0)
            width = Cal_W(Len, m)  ' L * (2 * E(m) / K(m) - 1)
            angle = Cal_A(m)  ' Acos(1 - 2 * m)
          End If
        End If
        height = Ht
      Else If IsSet("Ang") Then  ' find width & height based on length and angle
        If Ang < 0 Then
          Ang = -Ang  ' if angle is negative, set it to positive (for the calculations) but flip the reference plane about its x-axis
          refPlane.Transform(Transform.Mirror(New Plane(refPlane.Origin, refPlane.XAxis, refPlane.ZAxis)))
          flip_A = True
          flip_H = True
        End If
        m = Cal_M(Ang)  ' (1 - Cos(a)) / 2
        If Ang = 0 Then  ' skip the solver and set the known values
          width = Len
          height = 0
        Else
          width = Cal_W(Len, m)  ' L * (2 * E(m) / K(m) - 1)
          height = Cal_H(Len, m)  ' L * Sqrt(m) / K(m)
        End If
        angle = Ang
      Else
        Msg("error", "Need to specify one more parameter in addition to length")
        Return
      End If
      length = Len
    Else If IsSet("Wid") Then  ' if width is specified then...
      If IsSet("Ht") Then  ' find length & angle based on specified width and height
        If Ht < 0 Then
          Ht = -Ht  ' if height is negative, set it to positive (for the calculations) but flip the reference plane about its x-axis
          refPlane.Transform(Transform.Mirror(New Plane(refPlane.Origin, refPlane.XAxis, refPlane.ZAxis)))
          flip_A = True
          flip_H = True
        End If
        If Ht = 0 Then  ' skip the solver and set the known values
          length = Wid
          angle = 0
        Else
          m = SolveMFromWidHt(Wid, Ht)
          length = Cal_L(Ht, m)  ' h * K(m) / Sqrt(m)
          angle = Cal_A(m)  ' Acos(1 - 2 * m)
        End If
        height = Ht
      Else If IsSet("Ang") Then  ' find length & height based on specified width and angle
        If Wid = 0 Then
          Msg("error", "Curve not possible with width = 0 and an angle as inputs")
          Return
        End If
        If Ang < 0 Then
          Ang = -Ang  ' if angle is negative, set it to positive (for the calculations) but flip the reference plane about its x-axis
          refPlane.Transform(Transform.Mirror(New Plane(refPlane.Origin, refPlane.XAxis, refPlane.ZAxis)))
          flip_A = True
          flip_H = True
        End If
        m = Cal_M(Ang)  ' (1 - Cos(a)) / 2
        If Ang = 0 Then  ' skip the solver and set the known values
          length = Wid
          height = 0
        Else
          length = Wid / (2 * EllipticE(m) / EllipticK(m) - 1)
          If length < 0 Then
            Msg("error", "Curve not possible at specified width and angle (calculated length is negative)")
            Return
          End If
          height = Cal_H(length, m)  ' L * Sqrt(m) / K(m)
        End If
        angle = Ang
      Else
        Msg("error", "Need to specify one more parameter in addition to width (Wid)")
        Return
      End If
      width = Wid
    Else If width IsNot Nothing Then  ' if width is determined by PtA and PtB then...
      If IsSet("Ht") Then  ' find length & angle based on calculated width and height
        If Ht < 0 Then
          Ht = -Ht  ' if height is negative, set it to positive (for the calculations) but flip the reference plane about its x-axis
          refPlane.Transform(Transform.Mirror(New Plane(refPlane.Origin, refPlane.XAxis, refPlane.ZAxis)))
          flip_A = True
          flip_H = True
        End If
        If Ht = 0 Then  ' skip the solver and set the known values
          length = width
          angle = 0
        Else
          m = SolveMFromWidHt(width, Ht)
          length = Cal_L(Ht, m)  ' h * K(m) / Sqrt(m)
          angle = Cal_A(m)  ' Acos(1 - 2 * m)
        End If
        height = Ht
      Else If IsSet("Ang") Then  ' find length & height based on calculated width and angle
        If width = 0 Then
          Msg("error", "Curve not possible with width = 0 and an angle as inputs")
          Return
        End If
        If Ang < 0 Then
          Ang = -Ang  ' if angle is negative, set it to positive (for the calculations) but flip the reference plane about its x-axis
          refPlane.Transform(Transform.Mirror(New Plane(refPlane.Origin, refPlane.XAxis, refPlane.ZAxis)))
          flip_A = True
          flip_H = True
        End If
        m = Cal_M(Ang)  ' (1 - Cos(a)) / 2
        If Ang = 0 Then  ' skip the solver and set the known values
          length = width
          height = 0
        Else
          length = width / (2 * EllipticE(m) / EllipticK(m) - 1)
          If length < 0 Then
            Msg("error", "Curve not possible at specified width and angle (calculated length is negative)")
            Return
          End If
          height = Cal_H(length, m)  ' L * Sqrt(m) / K(m)
        End If
        angle = Ang
      Else
        Msg("error", "Need to specify one more parameter in addition to PtA and PtB")
        Return
      End If
    Else If IsSet("Ht") Then  ' if height is specified then...
      If IsSet("Ang") Then  ' find length & width based on height and angle
        If Ht < 0 Then
          Ht = -Ht  ' if height is negative, set it to positive (for the calculations) but flip the reference plane about its x-axis
          refPlane.Transform(Transform.Mirror(New Plane(refPlane.Origin, refPlane.XAxis, refPlane.ZAxis)))
          flip_H = True
          flip_A = True
        End If
        If Ht = 0 Then
          Msg("error", "Height can't = 0 if only height and angle are specified")
          Return
        Else
          If Ang < 0 Then
            Ang = -Ang  ' if angle is negative, set it to positive (for the calculations) but flip the reference plane about its x-axis
            refPlane.Transform(Transform.Mirror(New Plane(refPlane.Origin, refPlane.XAxis, refPlane.ZAxis)))
            flip_A = Not flip_A
            flip_H = Not flip_H
          End If
          m = Cal_M(Ang)  ' (1 - Cos(a)) / 2
          If Ang = 0 Then
            Msg("error", "Angle can't = 0 if only height and angle are specified")
            Return
          Else
            length = Cal_L(Ht, m)  ' h * K(m) / Sqrt(m)
            width = Cal_W(length, m)  ' L * (2 * E(m) / K(m) - 1)
          End If
          angle = Ang
        End If
        height = Ht
      Else
        Msg("error", "Need to specify one more parameter in addition to height")
        Return
      End If
    Else If IsSet("Ang") Then
      Msg("error", "Need to specify one more parameter in addition to angle")
      Return
    Else
      Msg("error", "Need to specify two of the four parameters: length, width (or PtB), height, and angle")
      Return
    End If
    If m > Defined.M_MAX Then
      Msg("error", "Form of curve not solvable with current algorithm and given inputs")
      Return
    End If
    refPlane.Origin = refPlane.PointAt(width / 2, 0, 0)  ' adjust the origin of the reference plane so that the curve is centered about the y-axis (start of the curve is at x = -width/2)
    If multiple_m.Count > 1 Then  ' if there is more than one m value returned, calculate the width, angle, and curve for each
      Dim multi_pts As New DataTree(Of Point3d)
      Dim multi_crv As New List(Of Curve)
      Dim tmp_pts As New List(Of Point3d)
      Dim multi_W, multi_A, multi_F As New List(Of Double)
      Dim j As Integer = 0  ' used for creating a new branch (GH_Path) for storing pts which is itself a list of points
      For Each m_val As Double In multiple_m
        width = Cal_W(length, m_val) 'length * (2 * EllipticE(m_val) / EllipticK(m_val) - 1)
        
        If width < 0 And ignoreSelfIntersecting Then
          Msg("warning", "One curve is self-intersecting. To enable these, set ignoreSelfIntersecting to False")
          Continue For
        End If
        
        If m_val >= Defined.M_SKETCHY Then Msg("info", "Accuracy of the curve whose width = " & Math.Round(width, 4) & " is not guaranteed")
        
        angle = Cal_A(m_val) 'Math.Asin(2 * m_val - 1)
        refPlane.Origin = refPlane.PointAt(width / 2, 0, 0)  ' adjust the origin of the reference plane so that the curve is centered about the y-axis (start of the curve is at x = -width/2)
        
        tmp_pts = FindBendForm(length, width, m_val, angle, refPlane)
        multi_pts.AddRange(tmp_pts, New GH_Path(j))
        multi_crv.Add(MakeCurve(tmp_pts, angle, refPlane))
        
        multi_W.Add(width)
        If flip_A Then angle = -angle
        multi_A.Add(angle)
        
        E = E * 10 ^ 9  ' Young's modulus input E is in GPa, so we convert to Pa here (= N/m^2)
        multi_F.Add(EllipticK(m_val) ^ 2 * E * I / length ^ 2)  ' from reference {4} pg. 79
        
        j += 1
        refPlane.Origin = PtA  ' reset the reference plane origin to PtA for the next m_val
        'Print("length=" & length & ", width=" & width & ", height=" & height & ", angle=" & angle & ", m=" & m_val & ", k=" & Math.Sqrt(m_val) & ", w/L=" & width / length & ", h/L=" & height / length & ", w/h=" & width / height)
      Next
      ' assign the outputs
      Pts = multi_pts
      Crv = multi_crv
      L = length
      W = multi_W
      If flip_H Then height = -height
      H = height
      A = multi_A
      F = multi_F
    Else  ' only deal with the single m value
      If m >= Defined.M_SKETCHY Then Msg("info", "Accuracy of the curve at these parameters is not guaranteed")
      
      If width < 0 And ignoreSelfIntersecting Then
        Msg("error", "Curve is self-intersecting. To enable these, set ignoreSelfIntersecting to False")
        Return
      End If
      
      Pts = FindBendForm(length, width, m, angle, refPlane)
      Crv = MakeCurve(pts, angle, refPlane)
      L = length
      W = width
      If flip_H Then height = -height
      H = height
      If flip_A Then angle = -angle
      A = angle
      E = E * 10 ^ 9  ' Young's modulus input E is in GPa, so we convert to Pa here (= N/m^2)
      F = EllipticK(m) ^ 2 * E * I / length ^ 2  ' from reference {4} pg. 79. Note: the critical buckling (that makes the rod/wire start to bend) can be found at height=0 (width=length)
      'height = Math.Sqrt(((2 * Len / 5) ^ 2 - ((Wid - Len / 5) / 2) ^ 2)  ' quick approximation discovered by Mårten of 'Geometry of Bending' fame ( http://tiny.cc/it2pbx )
      'width = (Len +/- 2 * Math.Sqrt(4 * Len ^ 2 - 25 * Ht ^ 2)) / 5  ' derived from above
      'length = (2 * Math.Sqrt(15 * Ht ^ 2 + 4 * Wid ^ 2) - Wid) / 3  ' derived from above
      'Print("length=" & length & ", width=" & width & ", height=" & height & ", angle=" & angle & ", m=" & m & ", k=" & Math.Sqrt(m) & ", w/L=" & width / length & ", h/L=" & height / length & ", w/h=" & width / height)
    End If
- 
                          615
                          822
                          84
                          184
                        
- 
                          657
                          914
                        
- 9
- 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2
- 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2
- 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2
- 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2
- 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2
- 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2
- 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2
- 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2
- 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2
- 8
- 3ede854e-c753-40eb-84cb-b48008f14fd4
- 8ec86459-bf01-4409-baee-174d0d2b13d0
- 8ec86459-bf01-4409-baee-174d0d2b13d0
- 8ec86459-bf01-4409-baee-174d0d2b13d0
- 8ec86459-bf01-4409-baee-174d0d2b13d0
- 8ec86459-bf01-4409-baee-174d0d2b13d0
- 8ec86459-bf01-4409-baee-174d0d2b13d0
- 8ec86459-bf01-4409-baee-174d0d2b13d0
- true
- Script Variable PtA
- e44ef3d7-d80d-4847-b3c9-7145c5d256c7
- PtA
- PtA
- true
- 0
- true
- 544607c8-b250-4465-bd1a-e6ed510b2090
- 1
- e1937b56-b1da-4c12-8bd8-e34ee81746ef
- 
                                  617
                                  824
                                  25
                                  20
                                
- 
                                  631
                                  834
                                
- true
- Script Variable PtB
- f3a5f81b-cbeb-43a5-b9d7-95ddf8329091
- PtB
- PtB
- true
- 0
- true
- 0
- e1937b56-b1da-4c12-8bd8-e34ee81746ef
- 
                                  617
                                  844
                                  25
                                  20
                                
- 
                                  631
                                  854
                                
- true
- Script Variable Pln
- 25fe63c8-a9a1-43dd-ba6c-ff444bb1bd38
- Pln
- Pln
- true
- 0
- true
- 2e367eec-73c9-49fe-931b-de57feb15198
- 1
- 3897522d-58e9-4d60-b38c-978ddacfedd8
- 
                                  617
                                  864
                                  25
                                  20
                                
- 
                                  631
                                  874
                                
- true
- Script Variable Len
- c645a879-0d63-4de2-8207-39e77ea0b36a
- Len
- Len
- true
- 0
- true
- 7e001f0c-1ecd-4198-95f7-0d0278815c2b
- 1
- 8e991e99-5fb8-41e1-928d-1bba8fb9f7d7
- 
                                  617
                                  884
                                  25
                                  20
                                
- 
                                  631
                                  894
                                
- true
- Script Variable Wid
- 563b27b8-1de0-4076-9540-f1f6287d4585
- Wid
- Wid
- true
- 0
- true
- 0
- 8e991e99-5fb8-41e1-928d-1bba8fb9f7d7
- 
                                  617
                                  904
                                  25
                                  20
                                
- 
                                  631
                                  914
                                
- true
- Script Variable Ht
- f945874f-3911-45dd-a65b-5931b59aaeda
- Ht
- Ht
- true
- 0
- true
- 0
- 8e991e99-5fb8-41e1-928d-1bba8fb9f7d7
- 
                                  617
                                  924
                                  25
                                  20
                                
- 
                                  631
                                  934
                                
- true
- Script Variable Ang
- 7cbb4f70-f9aa-4f07-bc67-aac4eaace9e1
- Ang
- Ang
- true
- 0
- true
- b2a8f43d-df9e-4385-bfbe-4e7a54acdc52
- 1
- 8e991e99-5fb8-41e1-928d-1bba8fb9f7d7
- 
                                  617
                                  944
                                  25
                                  20
                                
- 
                                  631
                                  954
                                
- true
- Script Variable E
- 757c9fbf-c87a-438c-9240-7ed119111c17
- E
- E
- true
- 0
- true
- 0068d51d-c81e-4187-8df3-5835ab363a73
- 1
- 8e991e99-5fb8-41e1-928d-1bba8fb9f7d7
- 
                                  617
                                  964
                                  25
                                  20
                                
- 
                                  631
                                  974
                                
- true
- Script Variable I
- dfba63c4-6cba-4504-bd15-6d7b03b308e0
- I
- I
- true
- 0
- true
- c29e43b1-f147-4596-9a27-65e202efbf44
- 1
- 8e991e99-5fb8-41e1-928d-1bba8fb9f7d7
- 
                                  617
                                  984
                                  25
                                  20
                                
- 
                                  631
                                  994
                                
- 1
- Print, Reflect and Error streams
- e74891fd-659b-4fdb-833d-cbae9b2064f7
- out
- out
- false
- 0
- 
                                  672
                                  824
                                  25
                                  22
                                
- 
                                  684.5
                                  835.25
                                
- Output parameter Pts
- 74a1959d-f66e-4c81-8b36-b26ed2379bb0
- Pts
- Pts
- false
- 0
- 
                                  672
                                  846
                                  25
                                  23
                                
- 
                                  684.5
                                  857.75
                                
- Output parameter Crv
- 9cf1549b-e355-4e34-8c66-56776a6693a3
- Crv
- Crv
- false
- 0
- 
                                  672
                                  869
                                  25
                                  22
                                
- 
                                  684.5
                                  880.25
                                
- Output parameter L
- 03e53700-d1d7-480a-9312-c1af517baedd
- L
- L
- false
- 0
- 
                                  672
                                  891
                                  25
                                  23
                                
- 
                                  684.5
                                  902.75
                                
- Output parameter W
- 09f794fe-078e-4e7b-840b-9d52b913b097
- W
- W
- false
- 0
- 
                                  672
                                  914
                                  25
                                  22
                                
- 
                                  684.5
                                  925.25
                                
- Output parameter H
- 2373426a-a151-4361-9f8e-d19fef664dc8
- H
- H
- false
- 0
- 
                                  672
                                  936
                                  25
                                  23
                                
- 
                                  684.5
                                  947.75
                                
- Output parameter A
- 619887fe-9427-4cea-b7fd-0b8e37ad0966
- A
- A
- false
- 0
- 
                                  672
                                  959
                                  25
                                  22
                                
- 
                                  684.5
                                  970.25
                                
- Output parameter F
- 20b5374e-e220-4840-8424-dcf1b57d3ad2
- F
- F
- false
- 0
- 
                                  672
                                  981
                                  25
                                  23
                                
- 
                                  684.5
                                  992.75
                                
- 57da07bd-ecab-415d-9d86-af36d7073abc
- Number Slider
- Numeric slider for single values
- 7e001f0c-1ecd-4198-95f7-0d0278815c2b
- Number Slider
- length
- false
- 0
- 
                          160
                          874
                          382
                          20
                        
- 
                          160.4443
                          874.5179
                        
- 2
- 1
- 0
- 400
- 0
- 0
- 145.76
- fbac3e32-f100-4292-8692-77240a42fd1a
- Point
- Contains a collection of three-dimensional points
- true
- 37000574-d15c-4f7d-92d9-b148cb8b434c
- Point
- Pt
- false
- 74a1959d-f66e-4c81-8b36-b26ed2379bb0
- 1
- 
                          784
                          791
                          50
                          24
                        
- 
                          809.0988
                          803.2372
                        
- 59e0b89a-e487-49f8-bab8-b5bab16be14c
- Panel
- A panel for custom notes and text values
- 982de226-ec32-4b13-b043-f53881d2e028
- Panel
- false
- 0
- 1487d807-5f9b-4abc-9b8d-effa22608b5d
- 1
- Double click to edit panel content…
- 
                          849
                          986
                          105
                          55
                        
- 0
- 0
- 0
- 
                          849.9546
                          986.3983
                        
- 
                          255;255;250;90
                        
- true
- true
- true
- false
- false
- true
- 0d77c51e-584f-44e8-aed2-c2ddf4803888
- Degrees
- Convert an angle specified in radians to degrees
- f53628df-d187-47f6-8939-9a7cff89ea30
- Degrees
- Deg
- 
                          764
                          997
                          64
                          28
                        
- 
                          794
                          1011
                        
- Angle in radians
- 6e9d9246-ea82-40e7-a5c7-6200a0750140
- Radians
- R
- false
- 619887fe-9427-4cea-b7fd-0b8e37ad0966
- 1
- 
                              766
                              999
                              13
                              24
                            
- 
                              774
                              1011
                            
- Angle in degrees
- 1487d807-5f9b-4abc-9b8d-effa22608b5d
- Degrees
- D
- false
- 0
- 
                              809
                              999
                              17
                              24
                            
- 
                              817.5
                              1011
                            
- 3581f42a-9592-4549-bd6b-1c0fc39d067b
- Construct Point
- Construct a point from {xyz} coordinates.
- f1c497f2-a656-46bd-97ff-e6f55517ad83
- Construct Point
- Pt
- 
                          390
                          743
                          67
                          64
                        
- 
                          421
                          775
                        
- {x} coordinate
- f274b47b-1218-4782-8247-527101e3221f
- X coordinate
- X
- false
- 0
- 
                              392
                              745
                              14
                              20
                            
- 
                              400.5
                              755
                            
- 1
- 1
- {0}
- 0
- {y} coordinate
- 8bb61e7c-9fbb-42a5-be49-c22980dcde8c
- Y coordinate
- Y
- false
- fd7d6e04-d8e1-46ec-9660-5d3b6392bb5c
- 1
- 
                              392
                              765
                              14
                              20
                            
- 
                              400.5
                              775
                            
- 1
- 1
- {0}
- -100
- {z} coordinate
- fd7813a9-1054-41ca-9f6b-83a5fd0efcce
- Z coordinate
- Z
- false
- 0
- 
                              392
                              785
                              14
                              20
                            
- 
                              400.5
                              795
                            
- 1
- 1
- {0}
- 0
- Point coordinate
- 544607c8-b250-4465-bd1a-e6ed510b2090
- Point
- Pt
- false
- 0
- 
                              436
                              745
                              19
                              60
                            
- 
                              445.5
                              775
                            
- d5967b9f-e8ee-436b-a8ad-29fdcecf32d5
- Curve
- Contains a collection of generic curves
- 12b4fe3c-7f43-444b-be77-19b89104763b
- Curve
- Crv
- false
- 9cf1549b-e355-4e34-8c66-56776a6693a3
- 1
- 
                          784
                          825
                          50
                          24
                        
- 
                          809.8876
                          837.7669
                        
- 17b7152b-d30d-4d50-b9ef-c9fe25576fc2
- XY Plane
- World XY plane.
- true
- 8cd68a99-5c0c-40f6-8f6c-c57b65a7c0fb
- XY Plane
- XY
- 
                          492
                          837
                          64
                          28
                        
- 
                          523
                          851
                        
- Origin of plane
- d599495e-da0d-4b5f-96ca-d429779f4f7e
- Origin
- O
- false
- 544607c8-b250-4465-bd1a-e6ed510b2090
- 1
- 
                              494
                              839
                              14
                              24
                            
- 
                              502.5
                              851
                            
- 1
- 1
- {0}
- 
                                      0
                                      0
                                      0
                                    
- World XY plane
- 2e367eec-73c9-49fe-931b-de57feb15198
- Plane
- P
- false
- 0
- 
                              538
                              839
                              16
                              24
                            
- 
                              546
                              851
                            
- a4cd2751-414d-42ec-8916-476ebf62d7fe
- Radians
- Convert an angle specified in degrees to radians
- 0de50cbe-99d5-4598-bc61-8cc3eacb616f
- Radians
- Rad
- 
                          481
                          954
                          64
                          28
                        
- 
                          512
                          968
                        
- Angle in degrees
- 8514650b-5a4b-4bd4-b272-4db0089c786a
- Degrees
- D
- false
- 5eda29cf-b445-43dc-9fe0-d002172bab75
- 1
- 
                              483
                              956
                              14
                              24
                            
- 
                              491.5
                              968
                            
- Angle in radians
- b2a8f43d-df9e-4385-bfbe-4e7a54acdc52
- Radians
- R
- false
- 0
- 
                              527
                              956
                              16
                              24
                            
- 
                              535
                              968
                            
- 57da07bd-ecab-415d-9d86-af36d7073abc
- Number Slider
- Numeric slider for single values
- 5eda29cf-b445-43dc-9fe0-d002172bab75
- Number Slider
- angle °
- false
- 0
- 
                          167
                          960
                          295
                          20
                        
- 
                          167.2024
                          960.4379
                        
- 2
- 1
- 0
- 170
- 0
- 0
- 60
- 59e0b89a-e487-49f8-bab8-b5bab16be14c
- Panel
- A panel for custom notes and text values
- e59fa8de-3b01-40cb-9090-35007fc19bba
- Panel
- false
- 0
- 03e53700-d1d7-480a-9312-c1af517baedd
- 1
- Double click to edit panel content…
- 
                          739
                          877
                          97
                          38
                        
- 0
- 0
- 0
- 
                          739.8782
                          877.1644
                        
- 
                          255;255;250;90
                        
- true
- true
- true
- false
- false
- true
- 59e0b89a-e487-49f8-bab8-b5bab16be14c
- Panel
- A panel for custom notes and text values
- 552a2357-924c-4919-bc11-da8244c7b3c6
- Panel
- false
- 0
- 09f794fe-078e-4e7b-840b-9d52b913b097
- 1
- Double click to edit panel content…
- 
                          850
                          902
                          105
                          55
                        
- 0
- 0
- 0
- 
                          850.7964
                          902.0322
                        
- 
                          255;255;250;90
                        
- true
- true
- true
- false
- false
- true
- 59e0b89a-e487-49f8-bab8-b5bab16be14c
- Panel
- A panel for custom notes and text values
- 7d007978-016f-4867-9bef-68c359c70508
- Panel
- false
- 0
- 2373426a-a151-4361-9f8e-d19fef664dc8
- 1
- Double click to edit panel content…
- 
                          738
                          937
                          97
                          38
                        
- 0
- 0
- 0
- 
                          738.8221
                          937.5484
                        
- 
                          255;255;250;90
                        
- true
- true
- true
- false
- false
- true
- 59e0b89a-e487-49f8-bab8-b5bab16be14c
- Panel
- A panel for custom notes and text values
- 6f2330d2-0e46-4e09-9ac5-7b7d2a1d3954
- Panel
- false
- 0
- 0
- 0.5
- 
                          988
                          843
                          50
                          20
                        
- 0
- 0
- 0
- 
                          988.351
                          843.602
                        
- 
                          255;255;250;90
                        
- true
- true
- true
- false
- false
- true
- 59e0b89a-e487-49f8-bab8-b5bab16be14c
- Panel
- A panel for custom notes and text values
- fd7d6e04-d8e1-46ec-9660-5d3b6392bb5c
- Panel
- false
- 0
- 0
- -100
- 
                          312
                          766
                          50
                          20
                        
- 0
- 0
- 0
- 
                          312.841
                          766.482
                        
- 
                          255;255;250;90
                        
- true
- true
- true
- false
- false
- true
- 8cc3a196-f6a0-49ea-9ed9-0cb343a3ae64
- XZ Plane
- World XZ plane.
- true
- 8b551e34-6c38-4a2b-9e47-c0b841fb2d47
- XZ Plane
- XZ
- 
                          1145
                          713
                          64
                          28
                        
- 
                          1176
                          727
                        
- Origin of plane
- 6e5d1c51-960b-46f9-898e-f2b11bdb8846
- Origin
- O
- false
- 544607c8-b250-4465-bd1a-e6ed510b2090
- 1
- 
                              1147
                              715
                              14
                              24
                            
- 
                              1155.5
                              727
                            
- 1
- 1
- {0}
- 
                                      0
                                      0
                                      0
                                    
- World XZ plane
- 0654eb92-001e-43e0-b38a-58a5d0d80f8e
- Plane
- P
- false
- 0
- 
                              1191
                              715
                              16
                              24
                            
- 
                              1199
                              727
                            
- 59e0b89a-e487-49f8-bab8-b5bab16be14c
- Panel
- A panel for custom notes and text values
- 95f9fd7f-37dc-4bd8-8105-7301ef052bdd
- Panel
- false
- 0
- 0
- 160
- 
                          306
                          175
                          50
                          20
                        
- 0
- 0
- 0
- 
                          306.7406
                          175.2052
                        
- 
                          255;255;250;90
                        
- true
- true
- true
- false
- false
- true
- 7f5c6c55-f846-4a08-9c9a-cfdc285cc6fe
- Scribble
- true
- 
                      -552.3402
                      73.81226
                    
- 
                      -194.0922
                      73.81226
                    
- 
                      -194.0922
                      88.8396
                    
- 
                      -552.3402
                      88.8396
                    
- A quick note
- Microsoft Sans Serif
- 501dc92a-f2db-4bb4-8054-89bd8827333b
- false
- Scribble
- Scribble
- 16
- for testing different points on an alternate plane
- 
                          -557.3402
                          68.81226
                          368.248
                          25.02734
                        
- 
                          -552.3402
                          73.81226
                        
- 7f5c6c55-f846-4a08-9c9a-cfdc285cc6fe
- Scribble
- true
- 
                      317.6904
                      47.65552
                    
- 
                      768.3664
                      47.65552
                    
- 
                      768.3664
                      71.13574
                    
- 
                      317.6904
                      71.13574
                    
- A quick note
- Microsoft Sans Serif
- 32f0e79e-6dca-4f24-9b30-17ca99e1ac07
- false
- Scribble
- Scribble
- 25
- Elastic Bending Script - Main Example
- 
                          312.6904
                          42.65552
                          460.676
                          33.48022
                        
- 
                          317.6904
                          47.65552
                        
- 7f5c6c55-f846-4a08-9c9a-cfdc285cc6fe
- Scribble
- true
- 
                      559.8143
                      683.617
                    
- 
                      913.3091
                      683.2137
                    
- 
                      913.3262
                      698.241
                    
- 
                      559.8313
                      698.6443
                    
- A quick note
- Microsoft Sans Serif
- 834f8190-7e8f-4039-8f4f-5e398c86ddfa
- false
- Scribble
- Scribble
- 16
- At 60°, minimum curve radius = height. Try 90°
- 
                          554.8143
                          678.2137
                          363.5119
                          25.43066
                        
- 
                          559.8143
                          683.617
                        
- 079bd9bd-54a0-41d4-98af-db999015f63d
- VB Script
-   Private Function IsSet(ByVal param As String) As Boolean  ' Check if an input parameter has data
    Dim i As Integer = Component.Params.IndexOfInputParam(param)
    If i > -1 Then
      Return Component.Params.Input.ElementAt(i).DataType > 1  ' input parameter DataType of 1 means it's not receiving input (internal or external)
    Else
      Msg("error", "Input parameter '" & param & "' not found")
      Return False
    End If
  End Function
  Private Sub Msg(ByVal type As String, ByVal msg As String)  ' Output an error, warning, or informational message
    Select Case type
      Case "error"
        Component.AddRuntimeMessage(GH_RuntimeMessageLevel.Error, msg)
        Print("Error: " & msg)
      Case "warning"
        Component.AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, msg)
        Print("Warning: " & msg)
      Case "info"
        Component.AddRuntimeMessage(GH_RuntimeMessageLevel.Remark, msg)
        Print(msg)
    End Select
  End Sub
  ' Solve for the m parameter from length and width (reference {1} equation (34), except b = width and K(k) and E(k) should be K(m) and E(m))
  Private Function SolveMFromLenWid(ByVal L As Double, ByVal w As Double) As Double
    If w = 0 Then
      Return Defined.M_ZERO_W  ' for the boundry condition width = 0, bypass the function and return the known m value
    End If
    Dim n As Integer = 1 ' Iteration counter (quit if >MAXIT)
    Dim lower As Double = 0 ' m must be within this range
    Dim upper As Double = 1
    Dim m As Double
    Dim cwl As Double
    Do While (upper - lower) > Defined.MAXERR AndAlso (n) < Defined.MAXIT ' Repeat until range narrow enough or MAXIT
      m = (upper + lower) / 2
      cwl = 2 * EllipticE(m) / EllipticK(m) - 1  ' calculate w/L with the test value of m
      If cwl < w / L Then  ' compares the calculated w/L with the actual w/L then narrows the range of possible m
        upper = m
      Else
        lower = m
      End If
      n += 1
    Loop
    Return m
  End Function
  ' Solve for the m parameter from length and height (reference {1} equation (33), except K(k) should be K(m) and k = sqrt(m))
  ' Note that it's actually possible to find 2 valid values for m (hence 2 width values) at certain height values
  Private Function SolveMFromLenHt(ByVal L As Double, ByVal h As Double) As List(Of Double)
    Dim n As Integer = 1 ' Iteration counter (quit if >MAXIT)
    Dim lower As Double = 0 ' m must be within this range
    Dim upper As Double = 1
    Dim twoWidths As Boolean = h / L >= Defined.DOUBLE_W_HL_RATIO And h / L < Defined.MAX_HL_RATIO  ' check to see if h/L is within the range where 2 solutions for the width are possible
    Dim m As Double
    Dim mult_m As New List(Of Double)
    Dim chl As Double
    If twoWidths Then
      ' find the first of two possible solutions for m with the following limits:
      lower = Defined.M_DOUBLE_W  ' see constants at bottom of script
      upper = Defined.M_MAXHEIGHT  ' see constants at bottom of script
      Do While (upper - lower) > Defined.MAXERR AndAlso (n) < Defined.MAXIT ' Repeat until range narrow enough or MAXIT
        m = (upper + lower) / 2
        chl = Math.Sqrt(m) / EllipticK(m)  ' calculate h/L with the test value of m
        If chl > h / L Then  ' compares the calculated h/L with the actual h/L then narrows the range of possible m
          upper = m
        Else
          lower = m
        End If
        n += 1
      Loop
      mult_m.Add(m)
      ' then find the second of two possible solutions for m with the following limits:
      lower = Defined.M_MAXHEIGHT  ' see constants at bottom of script
      upper = 1
      Do While (upper - lower) > Defined.MAXERR AndAlso (n) < Defined.MAXIT ' Repeat until range narrow enough or MAXIT
        m = (upper + lower) / 2
        chl = Math.Sqrt(m) / EllipticK(m)  ' calculate h/L with the test value of m
        If chl < h / L Then  ' compares the calculated h/L with the actual h/L then narrows the range of possible m
          upper = m
        Else
          lower = m
        End If
        n += 1
      Loop
      If m <= Defined.M_MAX Then  ' return this m parameter only if it falls within the maximum useful value (above which the curve breaks down)
        mult_m.Add(m)
      End If
    Else
      ' find the one possible solution for the m parameter
      upper = Defined.M_DOUBLE_W  ' limit the upper end of the search to the maximum value of m for which only one solution exists
      Do While (upper - lower) > Defined.MAXERR AndAlso (n) < Defined.MAXIT ' Repeat until range narrow enough or MAXIT
        m = (upper + lower) / 2
        chl = Math.Sqrt(m) / EllipticK(m)  ' calculate h/L with the test value of m
        If chl > h / L Then  ' compares the calculated h/L with the actual h/L then narrows the range of possible m
          upper = m
        Else
          lower = m
        End If
        n += 1
      Loop
      mult_m.Add(m)
    End If
    Return mult_m
  End Function
  ' Solve for the m parameter from width and height (derived from reference {1} equations (33) and (34) with same notes as above)
  Private Function SolveMFromWidHt(ByVal w As Double, ByVal h As Double) As Double
    Dim n As Integer = 1 ' Iteration counter (quit if >MAXIT)
    Dim lower As Double = 0 ' m must be within this range
    Dim upper As Double = 1
    Dim m As Double
    Dim cwh As Double
    Do While (upper - lower) > Defined.MAXERR AndAlso (n) < Defined.MAXIT ' Repeat until range narrow enough or MAXIT
      m = (upper + lower) / 2
      cwh = (2 * EllipticE(m) - EllipticK(m)) / Math.Sqrt(m)  ' calculate w/h with the test value of m
      If cwh < w / h Then  ' compares the calculated w/h with the actual w/h then narrows the range of possible m
        upper = m
      Else
        lower = m
      End If
      n += 1
    Loop
    Return m
  End Function
  ' Calculate length based on height and an m parameter, derived from reference {1} equation (33), except K(k) should be K(m) and k = sqrt(m)
  Private Function Cal_L(ByVal h As Double, ByVal m As Double) As Double
    Return h * EllipticK(m) / Math.Sqrt(m)
  End Function
  ' Calculate width based on length and an m parameter, derived from reference {1} equation (34), except b = width and K(k) and E(k) should be K(m) and E(m)
  Private Function Cal_W(ByVal L As Double, ByVal m As Double) As Double
    Return L * (2 * EllipticE(m) / EllipticK(m) - 1)
  End Function
  ' Calculate height based on length and an m parameter, from reference {1} equation (33), except K(k) should be K(m) and k = sqrt(m)
  Private Function Cal_H(ByVal L As Double, ByVal m As Double) As Double
    Return L * Math.Sqrt(m) / EllipticK(m)
  End Function
  ' Calculate the unique m parameter based on a start tangent angle, from reference {2}, just above equation (9a), that states k = Sin(angle / 2 + Pi / 4),
  ' but as m = k^2 and due to this script's need for an angle rotated 90° versus the one in reference {1}, the following formula is the result
  ' New note: verified by reference {4}, pg. 78 at the bottom
  Private Function Cal_M(ByVal a As Double) As Double
    Return (1 - Math.Cos(a)) / 2  ' equal to Sin^2(a/2) too
  End Function
  ' Calculate start tangent angle based on an m parameter, derived from above formula
  Private Function Cal_A(ByVal m As Double) As Double
    Return Math.Acos(1 - 2 * m)
  End Function
  ' This is the heart of this script, taking the found (or specified) length, width, and angle values along with the found m parameter to create
  ' a list of points that approximate the shape or form of the elastica. It works by finding the x and y coordinates (which are reversed versus
  ' the original equations (12a) and (12b) from reference {2} due to the 90° difference in orientation) based on the tangent angle along the curve.
  ' See reference {2} for more details on how they derived it. Note that to simplify things, the algorithm only calculates the points for half of the
  ' curve, then mirrors those points along the y-axis.
  Private Function FindBendForm(ByVal L As Double, ByVal w As Double, ByVal m As Double, ByVal ang As Double, ByVal refPln As Plane) As List(Of Point3d)
    L = L / 2  ' because the below algorithm is based on the formulas in reference {2} for only half of the curve
    w = w / 2  ' same
    If ang = 0 Then  ' if angle (and height) = 0, then simply return the start and end points of the straight line
      Dim out As New List(Of Point3d)
      out.Add(refPln.PointAt(w, 0, 0))
      out.Add(refPln.PointAt(-w, 0, 0))
      Return out
    End If
    Dim x As Double
    Dim y As Double
    Dim halfCurvePts As New List(Of Point3d)
    Dim fullCurvePts As New List(Of Point3d)
    Dim translatedPts As New List(Of Point3d)
    ang -= Math.PI / 2  ' a hack to allow this algorithm to work, since the original curve in paper {2} was rotated 90°
    Dim angB As Double = ang + (-Math.PI / 2 - ang) / Defined.CURVEDIVS  ' angB is the 'lowercase theta' which should be in formula {2}(12b) as the interval
    ' start [a typo...see equation(3)]. It's necessary to start angB at ang + [interval] instead of just ang due to integration failing at angB = ang
    halfCurvePts.Add(New Point3d(w, 0, 0))  ' start with this known initial point, as integration will fail when angB = ang
    ' each point {x, y} is calculated from the tangent angle, angB, that occurs at each point (which is why this iterates from ~ang to -pi/2, the known end condition)
    Do While Math.Round(angB, Defined.ROUNDTO) >= Math.Round(-Math.PI / 2, Defined.ROUNDTO)
      y = (Math.Sqrt(2) * Math.Sqrt(Math.Sin(ang) - Math.Sin(angB)) * (w + L)) / (2 * EllipticE(m))  ' note that x and y are swapped vs. (12a) and (12b)
      x = (L / (Math.Sqrt(2) * EllipticK(m))) * Simpson(angB, -Math.PI / 2, 500, ang)  ' calculate the Simpson approximation of the integral (function f below)
      ' over the interval angB ('lowercase theta') to -pi/2. side note: is 500 too few iterations for the Simson algorithm?
      If Math.Round(x, Defined.ROUNDTO) = 0 Then x = 0
      halfCurvePts.Add(New Point3d(x, y, 0))
      angB += (-Math.PI / 2 - ang) / Defined.CURVEDIVS  ' onto the next tangent angle
    Loop
    ' After finding the x and y values for half of the curve, add the {-x, y} values for the rest of the curve
    For Each point As Point3d In halfCurvePts
      If Math.Round(point.X, Defined.ROUNDTO) = 0 Then
        If Math.Round(point.Y, Defined.ROUNDTO) = 0 Then
          fullCurvePts.Add(New Point3d(0, 0, 0))  ' special case when width = 0: when x = 0, only duplicate the point when y = 0 too
        End If
      Else
        fullCurvePts.Add(New Point3d(-point.X, point.Y, 0))
      End If
    Next
    halfCurvePts.Reverse
    fullCurvePts.AddRange(halfCurvePts)
    For Each p As Point3d In fullCurvePts
      translatedPts.Add(refPln.PointAt(p.X, p.Y, p.Z))  ' translate the points from the reference plane to the world plane
    Next
    Return translatedPts
  End Function
  ' Interpolates the points from FindBendForm to create the Elastica curve. Uses start & end tangents for greater accuracy.
  Private Function MakeCurve(ByVal pts As List(Of Point3d), ByVal ang As Double, ByVal refPln As Plane) As Curve
    If ang <> 0 Then
      Dim ts, te As New Vector3d(refPln.XAxis)
      ts.Rotate(ang, refPln.ZAxis)
      te.Rotate(-ang, refPln.ZAxis)
      Return Curve.CreateInterpolatedCurve(pts, 3, CurveKnotStyle.Chord, ts, te)  ' 3rd degree curve with 'Chord' Knot Style
    Else
      Return Curve.CreateInterpolatedCurve(pts, 3)  ' if angle (and height) = 0, then simply interpolate the straight line (no start/end tangents)
    End If
  End Function
  ' Implements the Simpson approximation for an integral of function f below
  Public Function Simpson(a As Double, b As Double, n As Integer, theta As Double) As Double 'n should be an even number
    Dim j As Integer, s1 As Double, s2 As Double, h As Double
    h = (b - a) / n
    s1 = 0
    s2 = 0
    For j = 1 To n - 1 Step 2
      s1 = s1 + fn(a + j * h, theta)
    Next j
    For j = 2 To n - 2 Step 2
      s2 = s2 + fn(a + j * h, theta)
    Next j
    Simpson = h / 3 * (fn(a, theta) + 4 * s1 + 2 * s2 + fn(b, theta))
  End Function
  ' Specific calculation for the above integration
  Public Function fn(x As Double, theta As Double) As Double
    fn = Math.Sin(x) / (Math.Sqrt(Math.Sin(theta) - Math.Sin(x)))  ' from reference {2} formula (12b)
  End Function
  ' Return the Complete Elliptic integral of the 1st kind
  ' Abramowitz and Stegun p.591, formula 17.3.11
  ' Code from http://www.codeproject.com/Articles/566614/Elliptic-integrals
  Public Function EllipticK(ByVal m As Double) As Double
    Dim sum, term, above, below As Double
    sum = 1
    term = 1
    above = 1
    below = 2
    For i As Integer = 1 To 100
      term *= above / below
      sum += Math.Pow(m, i) * Math.Pow(term, 2)
      above += 2
      below += 2
    Next
    sum *= 0.5 * Math.PI
    Return sum
  End Function
  ' Return the Complete Elliptic integral of the 2nd kind
  ' Abramowitz and Stegun p.591, formula 17.3.12
  ' Code from http://www.codeproject.com/Articles/566614/Elliptic-integrals
  Public Function EllipticE(ByVal m As Double) As Double
    Dim sum, term, above, below As Double
    sum = 1
    term = 1
    above = 1
    below = 2
    For i As Integer = 1 To 100
      term *= above / below
      sum -= Math.Pow(m, i) * Math.Pow(term, 2) / above
      above += 2
      below += 2
    Next
    sum *= 0.5 * Math.PI
    Return sum
  End Function
  Friend Partial NotInheritable Class Defined
    Private Sub New()
    End Sub
    ' Note: most of these values for m and h/L ratio were found with Wolfram Alpha and either specific intercepts (x=0) or local minima/maxima. They should be constant.
    Public Const M_SKETCHY As Double = 0.95  ' value of the m parameter where the curvature near the ends of the curve gets wonky
    Public Const M_MAX As Double = 0.993  ' maximum useful value of the m parameter, above which this algorithm for the form of the curve breaks down
    Public Const M_ZERO_W As Double = 0.826114765984970336  ' value of the m parameter when width = 0
    Public Const M_MAXHEIGHT As Double = 0.701327460663101223  ' value of the m parameter at maximum possible height of the bent rod/wire
    Public Const M_DOUBLE_W As Double = 0.180254422335013983  ' minimum value of the m parameter when two width values are possible for a given height and length
    Public Const DOUBLE_W_HL_RATIO As Double = 0.257342117984635757  ' value of the height/length ratio above which there are two possible width values
    Public Const MAX_HL_RATIO As Double = 0.403140189705650243  ' maximum possible value of the height/length ratio
    Public Const MAXERR As Double = 0.0000000001  ' error tolerance
    Public Const MAXIT As Integer = 100  ' maximum number of iterations
    Public Const ROUNDTO As Integer = 10  ' number of decimal places to round off to
    Public Const CURVEDIVS As Integer = 50  ' number of sample points for building the curve (or half-curve as it were)
  End Class
- A VB.NET scriptable component
- 
                      98
                      86
                    
- true
- bf1f4616-5fd9-426e-9474-52a076d17bf4
- VB Script
- VB
- true
- 0
-     ' -----------------------------------------------------------------
    ' Elastic Bending Script by Will McElwain
    ' Created February 2014
    '
    ' DESCRIPTION:
    ' This beast creates the so-called 'elastica curve', the shape a long, thin rod or wire makes when it is bent elastically (i.e. not permanently). In this case, force
    ' is assumed to only be applied horizontally (which would be in line with the rod at rest) and both ends are assumed to be pinned or hinged meaning they are free
    ' to rotate (as opposed to clamped, when the end tangent angle is fixed, usually horizontally). An interesting finding is that it doesn't matter what the material or
    ' cross-sectional area is, as long as they're uniform along the entire length. Everything makes the same shape when bent as long as it doesn't cross the threshold
    ' from elastic to plastic (permanent) deformation (I don't bother to find that limit here, but can be found if the yield stress for a material is known).
    '
    ' Key to the formulas used in this script are elliptic integrals, specifically K(m), the complete elliptic integral of the first kind, and E(m), the complete elliptic
    ' integral of the second kind. There was a lot of confusion over the 'm' and 'k' parameters for these functions, as some people use them interchangeably, but they are
    ' not the same. m = k^2 (thus k = Sqrt(m)). I try to use the 'm' parameter exclusively to avoid this confusion. Note that there is a unique 'm' parameter for every
    ' configuration/shape of the elastica curve.
    '
    ' This script tries to find that unique 'm' parameter based on the inputs. The algorithm starts with a test version of m, evaluates an expression, say 2*E(m)/K(m)-1,
    ' then compares the result to what it should be (in this case, a known width/length ratio). Iterate until the correct m is found. Once we have m, we can then calculate
    ' all of the other unknowns, then find points that lie on that curve, then interpolate those points for the actual curve. You can also use Wolfram|Alpha as I did to
    ' find the m parameter based on the equations in this script (example here: http://tiny.cc/t4tpbx for when say width=45.2 and length=67.1).
    '
    ' Other notes:
    ' * This script works with negative values for width, which will creat a self-intersecting curve (as it should). The curvature of the elastica starts to break down around
    ' m=0.95 (~154°), but this script will continue to work until M_MAX, m=0.993 (~169°). If you wish to ignore self-intersecting curves, set ignoreSelfIntersecting to True
    ' * When the only known values are length and height, it is actually possible for certain ratios of height to length to have two valid m values (thus 2 possible widths
    ' and angles). This script will return them both.
    ' * Only the first two valid parameters (of the required ones) will be used, meaning if all four are connected (length, width or a PtB, height, and angle), this script will
    ' only use length and width (or a PtB).
    ' * Depending on the magnitude of your inputs (say if they're really small, like if length < 10), you might have to increase the constant ROUNDTO at the bottom
    '
    ' REFERENCES:
    ' {1} "The elastic rod" by M.E. Pacheco Q. & E. Pina, http://www.scielo.org.mx/pdf/rmfe/v53n2/v53n2a8.pdf
    ' {2} "An experiment in nonlinear beam theory" by A. Valiente, http://www.deepdyve.com/lp/doc/I3lwnxdfGz , also here: http://tiny.cc/Valiente_AEiNBT
    ' {3} "Snap buckling, writhing and Loop formation In twisted rods" by V.G.A. GOSS, http://myweb.lsbu.ac.uk/~gossga/thesisFinal.pdf
    ' {4} "Theory of Elastic Stability" by Stephen Timoshenko, http://www.scribd.com/doc/50402462/Timoshenko-Theory-of-Elastic-Stability  (start on p. 76)
    '
    ' INPUT:
    ' PtA - First anchor point (required)
    ' PtB - Second anchor point (optional, though 2 out of the 4--length, width, height, angle--need to be specified)
    '       [note that PtB can be the same as PtA (meaning width would be zero)]
    '       [also note that if a different width is additionally specified that's not equal to the distance between PtA and PtB, then the end point will not equal PtB anymore]
    ' Pln - Plane of the bent rod/wire, which bends up in the +y direction. The line between PtA and PtB (if specified) must be parallel to the x-axis of this plane
    '
    ' ** 2 of the following 4 need to be specified **
    ' Len - Length of the rod/wire, which needs to be > 0
    ' Wid - Width between the endpoints of the curve [note: if PtB is specified in addition, and distance between PtA and PtB <> width, the end point will be relocated
    ' Ht - Height of the bent rod/wire (when negative, curve will bend downward, relative to the input plane, instead)
    ' Ang - Inner departure angle or tangent angle (in radians) at the ends of the bent rod/wire. Set up so as width approaches length (thus height approaches zero), angle approaches zero
    '
    ' * Following variables only needed for optional calculating of bending force, not for shape of curve.
    ' E - Young's modulus (modulus of elasticity) in GPa (=N/m^2) (material-specific. for example, 7075 aluminum is roughly 71.7 GPa)
    ' I - Second moment of area (or area moment of inertia) in m^4 (cross-section-specific. for example, a hollow rod
    '     would have I = pi * (outer_diameter^4 - inner_diameter^4) / 32
    ' Note: E*I is also known as flexural rigidity or bending stiffness
    '
    ' OUTPUT:
    ' out - only for debugging messages
    ' Pts - the list of points that approximate the shape of the elastica
    ' Crv - the 3rd-degree curve interpolated from those points (with accurate start & end tangents)
    ' L - the length of the rod/wire
    ' W - the distance (width) between the endpoints of the rod/wire
    ' H - the height of the bent rod/wire
    ' A - the tangent angle at the (start) end of the rod/wire
    ' F - the force needed to hold the rod/wire in a specific shape (based on the material properties & cross-section) **be sure your units for 'I' match your units for the
    ' rest of your inputs (length, width, etc.). Also note that the critical buckling load (force) that makes the rod/wire start to bend can be found at height=0
    '
    ' THANKS TO:
    ' Mårten Nettelbladt (thegeometryofbending.blogspot.com)
    ' Daniel Piker (Kangaroo plugin)
    ' David Rutten (Grasshopper guru)
    ' Euler & Bernoulli (the O.G.'s)
    '
    ' -----------------------------------------------------------------
    Dim ignoreSelfIntersecting As Boolean = False  ' set to True if you don't want to output curves where width < 0, which creates a self-intersecting curve
    Dim inCt As Integer = 0  ' count the number of required parameters that are receiving data
    Dim length As Double
    Dim width As System.Object = Nothing  ' need to set as Nothing so we can check if it has been assigned a value later
    Dim height As Double
    Dim angle As Double
    Dim m As Double
    Dim multiple_m As New List(Of Double)
    Dim AtoB As Line
    Dim flip_H As Boolean = False  ' if height is negative, this flag will be set
    Dim flip_A As Boolean = False  ' if angle is negative, this flag will be set
    If Not IsSet("Pln") Then
      Msg("error", "Base plane is not set")
      Return
    End If
    If Not IsSet("PtA") Then
      Msg("error", "Point A is not set")
      Return
    End If
    If Math.Round(Pln.DistanceTo(PtA), Defined.ROUNDTO) <> 0 Then
      Msg("error", "Point A is not on the base plane")
      Return
    End If
    Dim refPlane As Plane = Pln  ' create a reference plane = input plane and set the origin of it to PtA in case PtA isn't the origin already
    refPlane.Origin = PtA
    If IsSet("PtB") Then
      If Math.Round(Pln.DistanceTo(PtB), Defined.ROUNDTO) <> 0 Then
        Msg("error", "Point B is not on the base plane")
        Return
      End If
      AtoB = New Line(PtA, PtB)
      If AtoB.Length <> 0 And Not AtoB.Direction.IsPerpendicularTo(Pln.YAxis) Then
        Msg("error", "The line between PtA and PtB is not perpendicular to the Y-axis of the specified plane")
        Return
      End If
      inCt += 1
      If IsSet("Wid") Then Msg("info", "Wid will override the distance between PtA and PtB. If you do not want this to happen, disconnect PtB or Wid.")
      width = PtA.DistanceTo(PtB)  ' get the width (distance) between PtA and PtB
      
      Dim refPtB As Point3d
      refPlane.RemapToPlaneSpace(PtB, refPtB)
      If refPtB.X < 0 Then width = -width  ' check if PtB is to the left of PtA...if so, width is negative
    End If
    If IsSet("Len") Then inCt += 1
    If IsSet("Wid") Then inCt += 1
    If IsSet("Ht") Then inCt += 1
    If IsSet("Ang") Then inCt += 1
    If inCt > 2 Then Msg("info", "More parameters set than are required (out of length, width, height, angle). Only using the first two valid ones.")
    ' check for connected/specified inputs. note: only the first two that it comes across will be used
    If IsSet("Len") Then  ' if length is specified then...
      If Len <= 0 Then
        Msg("error", "Length cannot be negative or zero")
        Return
      End If
      If IsSet("Wid") Then  ' find height & angle based on length and specified width
        If Wid > Len Then
          Msg("error", "Width is greater than length")
          Return
        End If
        If Wid = Len Then  ' skip the solver and set the known values
          height = 0
          m = 0
          angle = 0
          width = Wid
        Else
          m = SolveMFromLenWid(Len, Wid)
          height = Cal_H(Len, m)  ' L * Sqrt(m) / K(m)
          angle = Cal_A(m)  ' Acos(1 - 2 * m)
          width = Wid
        End If
      Else If width IsNot Nothing Then  ' find height & angle based on length and calculated width (distance between PtA and PtB)
        If width > Len Then
          Msg("error", "Width is greater than length")
          Return
        End If
        If width = Len Then  ' skip the solver and set the known values
          height = 0
          m = 0
          angle = 0
        Else
          m = SolveMFromLenWid(Len, width)
          height = Cal_H(Len, m)  ' L * Sqrt(m) / K(m)
          angle = Cal_A(m)  ' Acos(1 - 2 * m)
        End If
      Else If IsSet("Ht") Then  ' find width & angle based on length and height  ** possible to return 2 results **
        If Math.Abs(Ht / Len) > Defined.MAX_HL_RATIO Then
          Msg("error", "Height not possible with given length")
          Return
        End If
        If Ht < 0 Then
          Ht = -Ht  ' if height is negative, set it to positive (for the calculations) but flip the reference plane about its x-axis
          refPlane.Transform(Transform.Mirror(New Plane(refPlane.Origin, refPlane.XAxis, refPlane.ZAxis)))
          flip_A = True
          flip_H = True
        End If
        If Ht = 0 Then  ' skip the solver and set the known values
          width = Len
          angle = 0
        Else
          multiple_m = SolveMFromLenHt(Len, Ht)  ' note that it's possible for two values of m to be found if height is close to max height
          If multiple_m.Count = 1 Then  ' if there's only one m value returned, calculate the width & angle here. we'll deal with multiple m values later
            m = multiple_m.Item(0)
            width = Cal_W(Len, m)  ' L * (2 * E(m) / K(m) - 1)
            angle = Cal_A(m)  ' Acos(1 - 2 * m)
          End If
        End If
        height = Ht
      Else If IsSet("Ang") Then  ' find width & height based on length and angle
        If Ang < 0 Then
          Ang = -Ang  ' if angle is negative, set it to positive (for the calculations) but flip the reference plane about its x-axis
          refPlane.Transform(Transform.Mirror(New Plane(refPlane.Origin, refPlane.XAxis, refPlane.ZAxis)))
          flip_A = True
          flip_H = True
        End If
        m = Cal_M(Ang)  ' (1 - Cos(a)) / 2
        If Ang = 0 Then  ' skip the solver and set the known values
          width = Len
          height = 0
        Else
          width = Cal_W(Len, m)  ' L * (2 * E(m) / K(m) - 1)
          height = Cal_H(Len, m)  ' L * Sqrt(m) / K(m)
        End If
        angle = Ang
      Else
        Msg("error", "Need to specify one more parameter in addition to length")
        Return
      End If
      length = Len
    Else If IsSet("Wid") Then  ' if width is specified then...
      If IsSet("Ht") Then  ' find length & angle based on specified width and height
        If Ht < 0 Then
          Ht = -Ht  ' if height is negative, set it to positive (for the calculations) but flip the reference plane about its x-axis
          refPlane.Transform(Transform.Mirror(New Plane(refPlane.Origin, refPlane.XAxis, refPlane.ZAxis)))
          flip_A = True
          flip_H = True
        End If
        If Ht = 0 Then  ' skip the solver and set the known values
          length = Wid
          angle = 0
        Else
          m = SolveMFromWidHt(Wid, Ht)
          length = Cal_L(Ht, m)  ' h * K(m) / Sqrt(m)
          angle = Cal_A(m)  ' Acos(1 - 2 * m)
        End If
        height = Ht
      Else If IsSet("Ang") Then  ' find length & height based on specified width and angle
        If Wid = 0 Then
          Msg("error", "Curve not possible with width = 0 and an angle as inputs")
          Return
        End If
        If Ang < 0 Then
          Ang = -Ang  ' if angle is negative, set it to positive (for the calculations) but flip the reference plane about its x-axis
          refPlane.Transform(Transform.Mirror(New Plane(refPlane.Origin, refPlane.XAxis, refPlane.ZAxis)))
          flip_A = True
          flip_H = True
        End If
        m = Cal_M(Ang)  ' (1 - Cos(a)) / 2
        If Ang = 0 Then  ' skip the solver and set the known values
          length = Wid
          height = 0
        Else
          length = Wid / (2 * EllipticE(m) / EllipticK(m) - 1)
          If length < 0 Then
            Msg("error", "Curve not possible at specified width and angle (calculated length is negative)")
            Return
          End If
          height = Cal_H(length, m)  ' L * Sqrt(m) / K(m)
        End If
        angle = Ang
      Else
        Msg("error", "Need to specify one more parameter in addition to width (Wid)")
        Return
      End If
      width = Wid
    Else If width IsNot Nothing Then  ' if width is determined by PtA and PtB then...
      If IsSet("Ht") Then  ' find length & angle based on calculated width and height
        If Ht < 0 Then
          Ht = -Ht  ' if height is negative, set it to positive (for the calculations) but flip the reference plane about its x-axis
          refPlane.Transform(Transform.Mirror(New Plane(refPlane.Origin, refPlane.XAxis, refPlane.ZAxis)))
          flip_A = True
          flip_H = True
        End If
        If Ht = 0 Then  ' skip the solver and set the known values
          length = width
          angle = 0
        Else
          m = SolveMFromWidHt(width, Ht)
          length = Cal_L(Ht, m)  ' h * K(m) / Sqrt(m)
          angle = Cal_A(m)  ' Acos(1 - 2 * m)
        End If
        height = Ht
      Else If IsSet("Ang") Then  ' find length & height based on calculated width and angle
        If width = 0 Then
          Msg("error", "Curve not possible with width = 0 and an angle as inputs")
          Return
        End If
        If Ang < 0 Then
          Ang = -Ang  ' if angle is negative, set it to positive (for the calculations) but flip the reference plane about its x-axis
          refPlane.Transform(Transform.Mirror(New Plane(refPlane.Origin, refPlane.XAxis, refPlane.ZAxis)))
          flip_A = True
          flip_H = True
        End If
        m = Cal_M(Ang)  ' (1 - Cos(a)) / 2
        If Ang = 0 Then  ' skip the solver and set the known values
          length = width
          height = 0
        Else
          length = width / (2 * EllipticE(m) / EllipticK(m) - 1)
          If length < 0 Then
            Msg("error", "Curve not possible at specified width and angle (calculated length is negative)")
            Return
          End If
          height = Cal_H(length, m)  ' L * Sqrt(m) / K(m)
        End If
        angle = Ang
      Else
        Msg("error", "Need to specify one more parameter in addition to PtA and PtB")
        Return
      End If
    Else If IsSet("Ht") Then  ' if height is specified then...
      If IsSet("Ang") Then  ' find length & width based on height and angle
        If Ht < 0 Then
          Ht = -Ht  ' if height is negative, set it to positive (for the calculations) but flip the reference plane about its x-axis
          refPlane.Transform(Transform.Mirror(New Plane(refPlane.Origin, refPlane.XAxis, refPlane.ZAxis)))
          flip_H = True
          flip_A = True
        End If
        If Ht = 0 Then
          Msg("error", "Height can't = 0 if only height and angle are specified")
          Return
        Else
          If Ang < 0 Then
            Ang = -Ang  ' if angle is negative, set it to positive (for the calculations) but flip the reference plane about its x-axis
            refPlane.Transform(Transform.Mirror(New Plane(refPlane.Origin, refPlane.XAxis, refPlane.ZAxis)))
            flip_A = Not flip_A
            flip_H = Not flip_H
          End If
          m = Cal_M(Ang)  ' (1 - Cos(a)) / 2
          If Ang = 0 Then
            Msg("error", "Angle can't = 0 if only height and angle are specified")
            Return
          Else
            length = Cal_L(Ht, m)  ' h * K(m) / Sqrt(m)
            width = Cal_W(length, m)  ' L * (2 * E(m) / K(m) - 1)
          End If
          angle = Ang
        End If
        height = Ht
      Else
        Msg("error", "Need to specify one more parameter in addition to height")
        Return
      End If
    Else If IsSet("Ang") Then
      Msg("error", "Need to specify one more parameter in addition to angle")
      Return
    Else
      Msg("error", "Need to specify two of the four parameters: length, width (or PtB), height, and angle")
      Return
    End If
    If m > Defined.M_MAX Then
      Msg("error", "Form of curve not solvable with current algorithm and given inputs")
      Return
    End If
    refPlane.Origin = refPlane.PointAt(width / 2, 0, 0)  ' adjust the origin of the reference plane so that the curve is centered about the y-axis (start of the curve is at x = -width/2)
    If multiple_m.Count > 1 Then  ' if there is more than one m value returned, calculate the width, angle, and curve for each
      Dim multi_pts As New DataTree(Of Point3d)
      Dim multi_crv As New List(Of Curve)
      Dim tmp_pts As New List(Of Point3d)
      Dim multi_W, multi_A, multi_F As New List(Of Double)
      Dim j As Integer = 0  ' used for creating a new branch (GH_Path) for storing pts which is itself a list of points
      For Each m_val As Double In multiple_m
        width = Cal_W(length, m_val) 'length * (2 * EllipticE(m_val) / EllipticK(m_val) - 1)
        
        If width < 0 And ignoreSelfIntersecting Then
          Msg("warning", "One curve is self-intersecting. To enable these, set ignoreSelfIntersecting to False")
          Continue For
        End If
        
        If m_val >= Defined.M_SKETCHY Then Msg("info", "Accuracy of the curve whose width = " & Math.Round(width, 4) & " is not guaranteed")
        
        angle = Cal_A(m_val) 'Math.Asin(2 * m_val - 1)
        refPlane.Origin = refPlane.PointAt(width / 2, 0, 0)  ' adjust the origin of the reference plane so that the curve is centered about the y-axis (start of the curve is at x = -width/2)
        
        tmp_pts = FindBendForm(length, width, m_val, angle, refPlane)
        multi_pts.AddRange(tmp_pts, New GH_Path(j))
        multi_crv.Add(MakeCurve(tmp_pts, angle, refPlane))
        
        multi_W.Add(width)
        If flip_A Then angle = -angle
        multi_A.Add(angle)
        
        E = E * 10 ^ 9  ' Young's modulus input E is in GPa, so we convert to Pa here (= N/m^2)
        multi_F.Add(EllipticK(m_val) ^ 2 * E * I / length ^ 2)  ' from reference {4} pg. 79
        
        j += 1
        refPlane.Origin = PtA  ' reset the reference plane origin to PtA for the next m_val
        'Print("length=" & length & ", width=" & width & ", height=" & height & ", angle=" & angle & ", m=" & m_val & ", k=" & Math.Sqrt(m_val) & ", w/L=" & width / length & ", h/L=" & height / length & ", w/h=" & width / height)
      Next
      ' assign the outputs
      Pts = multi_pts
      Crv = multi_crv
      L = length
      W = multi_W
      If flip_H Then height = -height
      H = height
      A = multi_A
      F = multi_F
    Else  ' only deal with the single m value
      If m >= Defined.M_SKETCHY Then Msg("info", "Accuracy of the curve at these parameters is not guaranteed")
      
      If width < 0 And ignoreSelfIntersecting Then
        Msg("error", "Curve is self-intersecting. To enable these, set ignoreSelfIntersecting to False")
        Return
      End If
      
      Pts = FindBendForm(length, width, m, angle, refPlane)
      Crv = MakeCurve(pts, angle, refPlane)
      L = length
      W = width
      If flip_H Then height = -height
      H = height
      If flip_A Then angle = -angle
      A = angle
      E = E * 10 ^ 9  ' Young's modulus input E is in GPa, so we convert to Pa here (= N/m^2)
      F = EllipticK(m) ^ 2 * E * I / length ^ 2  ' from reference {4} pg. 79. Note: the critical buckling (that makes the rod/wire start to bend) can be found at height=0 (width=length)
      'height = Math.Sqrt(((2 * Len / 5) ^ 2 - ((Wid - Len / 5) / 2) ^ 2)  ' quick approximation discovered by Mårten of 'Geometry of Bending' fame ( http://tiny.cc/it2pbx )
      'width = (Len +/- 2 * Math.Sqrt(4 * Len ^ 2 - 25 * Ht ^ 2)) / 5  ' derived from above
      'length = (2 * Math.Sqrt(15 * Ht ^ 2 + 4 * Wid ^ 2) - Wid) / 3  ' derived from above
      'Print("length=" & length & ", width=" & width & ", height=" & height & ", angle=" & angle & ", m=" & m & ", k=" & Math.Sqrt(m) & ", w/L=" & width / length & ", h/L=" & height / length & ", w/h=" & width / height)
    End If
- 
                          618
                          1502
                          84
                          184
                        
- 
                          660
                          1594
                        
- 9
- 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2
- 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2
- 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2
- 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2
- 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2
- 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2
- 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2
- 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2
- 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2
- 8
- 3ede854e-c753-40eb-84cb-b48008f14fd4
- 8ec86459-bf01-4409-baee-174d0d2b13d0
- 8ec86459-bf01-4409-baee-174d0d2b13d0
- 8ec86459-bf01-4409-baee-174d0d2b13d0
- 8ec86459-bf01-4409-baee-174d0d2b13d0
- 8ec86459-bf01-4409-baee-174d0d2b13d0
- 8ec86459-bf01-4409-baee-174d0d2b13d0
- 8ec86459-bf01-4409-baee-174d0d2b13d0
- true
- Script Variable PtA
- fc00bec5-e331-4012-b0a8-a6f9d0f686f7
- PtA
- PtA
- true
- 0
- true
- 7470aaae-fe5c-4a6e-a5d7-3c8c950bb9fb
- 1
- e1937b56-b1da-4c12-8bd8-e34ee81746ef
- 
                                  620
                                  1504
                                  25
                                  20
                                
- 
                                  634
                                  1514
                                
- true
- Script Variable PtB
- c5bc96c5-9e28-4cb8-9259-356c9db2b9fb
- PtB
- PtB
- true
- 0
- true
- 0
- e1937b56-b1da-4c12-8bd8-e34ee81746ef
- 
                                  620
                                  1524
                                  25
                                  20
                                
- 
                                  634
                                  1534
                                
- true
- Script Variable Pln
- 71f32d80-b186-4e03-b761-b9bb960ea743
- Pln
- Pln
- true
- 0
- true
- c7f844d2-ba5e-476f-b4d4-193dcea7a216
- 1
- 3897522d-58e9-4d60-b38c-978ddacfedd8
- 
                                  620
                                  1544
                                  25
                                  20
                                
- 
                                  634
                                  1554
                                
- true
- Script Variable Len
- 0aa34a2c-a64a-42a7-9ee2-ff1e67f56177
- Len
- Len
- true
- 0
- true
- 7d11a12d-1f6f-4777-9bc7-965dd3035809
- 1
- 8e991e99-5fb8-41e1-928d-1bba8fb9f7d7
- 
                                  620
                                  1564
                                  25
                                  20
                                
- 
                                  634
                                  1574
                                
- true
- Script Variable Wid
- 1af65384-240e-46e3-8309-6fc1ae7504d7
- Wid
- Wid
- true
- 0
- true
- 0
- 8e991e99-5fb8-41e1-928d-1bba8fb9f7d7
- 
                                  620
                                  1584
                                  25
                                  20
                                
- 
                                  634
                                  1594
                                
- true
- Script Variable Ht
- 8d0b03a7-827e-4902-8b4f-5bb0e815b41b
- Ht
- Ht
- true
- 0
- true
- d1327bed-c875-4acd-82dd-5fed4b45b311
- 1
- 8e991e99-5fb8-41e1-928d-1bba8fb9f7d7
- 
                                  620
                                  1604
                                  25
                                  20
                                
- 
                                  634
                                  1614
                                
- true
- Script Variable Ang
- 2deaf321-2e08-44e8-a80f-9628891997a5
- Ang
- Ang
- true
- 0
- true
- 0
- 8e991e99-5fb8-41e1-928d-1bba8fb9f7d7
- 
                                  620
                                  1624
                                  25
                                  20
                                
- 
                                  634
                                  1634
                                
- true
- Script Variable E
- 8dff382d-9d65-40bc-ac45-64afb28a006d
- E
- E
- true
- 0
- true
- 0
- 8e991e99-5fb8-41e1-928d-1bba8fb9f7d7
- 
                                  620
                                  1644
                                  25
                                  20
                                
- 
                                  634
                                  1654
                                
- true
- Script Variable I
- 33d1c654-7377-4887-9445-52cefe06021d
- I
- I
- true
- 0
- true
- 0
- 8e991e99-5fb8-41e1-928d-1bba8fb9f7d7
- 
                                  620
                                  1664
                                  25
                                  20
                                
- 
                                  634
                                  1674
                                
- 1
- Print, Reflect and Error streams
- 964ae01d-510e-42cb-b06f-38805376764d
- out
- out
- false
- 0
- 
                                  675
                                  1504
                                  25
                                  22
                                
- 
                                  687.5
                                  1515.25
                                
- Output parameter Pts
- 17f99969-6a6b-431e-8210-f6e15df9a9af
- Pts
- Pts
- false
- 0
- 
                                  675
                                  1526
                                  25
                                  23
                                
- 
                                  687.5
                                  1537.75
                                
- Output parameter Crv
- 6548d62a-dfa5-4478-9f16-8d4fb96732c9
- Crv
- Crv
- false
- 0
- 
                                  675
                                  1549
                                  25
                                  22
                                
- 
                                  687.5
                                  1560.25
                                
- Output parameter L
- a2a9f9ae-744d-4886-a3ee-4c33b8365028
- L
- L
- false
- 0
- 
                                  675
                                  1571
                                  25
                                  23
                                
- 
                                  687.5
                                  1582.75
                                
- Output parameter W
- 0c900729-ed6e-40e8-809f-e2432521ac54
- W
- W
- false
- 0
- 
                                  675
                                  1594
                                  25
                                  22
                                
- 
                                  687.5
                                  1605.25
                                
- Output parameter H
- 7772d1f7-9786-4d55-8690-af9d6877a777
- H
- H
- false
- 0
- 
                                  675
                                  1616
                                  25
                                  23
                                
- 
                                  687.5
                                  1627.75
                                
- Output parameter A
- bc883717-6d8a-41a6-bb0b-3d7c5d7a61ea
- A
- A
- false
- 0
- 
                                  675
                                  1639
                                  25
                                  22
                                
- 
                                  687.5
                                  1650.25
                                
- Output parameter F
- fc8245e0-b2d0-471d-9254-01a0eff7a0b4
- F
- F
- false
- 0
- 
                                  675
                                  1661
                                  25
                                  23
                                
- 
                                  687.5
                                  1672.75
                                
- 57da07bd-ecab-415d-9d86-af36d7073abc
- Number Slider
- Numeric slider for single values
- 7d11a12d-1f6f-4777-9bc7-965dd3035809
- Number Slider
- length
- false
- 0
- 
                          163
                          1555
                          382
                          20
                        
- 
                          163.9633
                          1555.108
                        
- 2
- 1
- 0
- 400
- 0
- 0
- 225
- fbac3e32-f100-4292-8692-77240a42fd1a
- Point
- Contains a collection of three-dimensional points
- true
- 108e145a-a9f8-4c1a-856f-eef3be9eef4b
- Point
- Pt
- false
- 17f99969-6a6b-431e-8210-f6e15df9a9af
- 1
- 
                          788
                          1463
                          50
                          24
                        
- 
                          813.4178
                          1475.827
                        
- 59e0b89a-e487-49f8-bab8-b5bab16be14c
- Panel
- A panel for custom notes and text values
- de6e3b3a-9675-45ae-ad2f-bfc0988f9582
- Panel
- false
- 0
- a0d9174c-2b33-4845-86da-70d722e564b7
- 1
- Double click to edit panel content…
- 
                          846
                          1678
                          105
                          55
                        
- 0
- 0
- 0
- 
                          846.2736
                          1678.188
                        
- 
                          255;255;250;90
                        
- true
- true
- true
- false
- false
- true
- 0d77c51e-584f-44e8-aed2-c2ddf4803888
- Degrees
- Convert an angle specified in radians to degrees
- 9bc218b0-faa5-4566-a292-b5565b343ee8
- Degrees
- Deg
- 
                          759
                          1690
                          64
                          28
                        
- 
                          789
                          1704
                        
- Angle in radians
- 8dd5ffda-e6b3-4328-a1c1-726386b31dd7
- Radians
- R
- false
- bc883717-6d8a-41a6-bb0b-3d7c5d7a61ea
- 1
- 
                              761
                              1692
                              13
                              24
                            
- 
                              769
                              1704
                            
- Angle in degrees
- a0d9174c-2b33-4845-86da-70d722e564b7
- Degrees
- D
- false
- 0
- 
                              804
                              1692
                              17
                              24
                            
- 
                              812.5
                              1704
                            
- 3581f42a-9592-4549-bd6b-1c0fc39d067b
- Construct Point
- Construct a point from {xyz} coordinates.
- 5bb8544d-21ed-430d-b9a1-3d097d9c0f85
- Construct Point
- Pt
- 
                          474
                          1440
                          67
                          64
                        
- 
                          505
                          1472
                        
- {x} coordinate
- fd05bf19-e5b9-428a-a0b7-1183ddb4d4cb
- X coordinate
- X
- false
- 18da725f-8fce-4b5c-bfc0-b35f534747f4
- 1
- 
                              476
                              1442
                              14
                              20
                            
- 
                              484.5
                              1452
                            
- 1
- 1
- {0}
- 0
- {y} coordinate
- 5d500e04-4c0a-4e2e-90e3-a69f12e6e56b
- Y coordinate
- Y
- false
- bdda70a3-abe5-47d3-bab1-d54eaac87273
- 1
- 
                              476
                              1462
                              14
                              20
                            
- 
                              484.5
                              1472
                            
- 1
- 1
- {0}
- 0
- {z} coordinate
- b73aa23e-da5e-429b-a2ad-c29573433d8d
- Z coordinate
- Z
- false
- 0
- 
                              476
                              1482
                              14
                              20
                            
- 
                              484.5
                              1492
                            
- 1
- 1
- {0}
- 0
- Point coordinate
- 7470aaae-fe5c-4a6e-a5d7-3c8c950bb9fb
- Point
- Pt
- false
- 0
- 
                              520
                              1442
                              19
                              60
                            
- 
                              529.5
                              1472
                            
- d5967b9f-e8ee-436b-a8ad-29fdcecf32d5
- Curve
- Contains a collection of generic curves
- d707c7a6-ce24-45bb-a3b3-c616b13d07dc
- Curve
- Crv
- false
- 6548d62a-dfa5-4478-9f16-8d4fb96732c9
- 1
- 
                          788
                          1506
                          50
                          24
                        
- 
                          813.4067
                          1518.357
                        
- 17b7152b-d30d-4d50-b9ef-c9fe25576fc2
- XY Plane
- World XY plane.
- true
- 1653bea2-6780-45be-ad4a-2c29f59e4c19
- XY Plane
- XY
- 
                          479
                          1515
                          64
                          28
                        
- 
                          510
                          1529
                        
- Origin of plane
- 6ccdcfe2-c623-42d1-8da5-1e99c86f6f52
- Origin
- O
- false
- 0
- 
                              481
                              1517
                              14
                              24
                            
- 
                              489.5
                              1529
                            
- 1
- 1
- {0}
- 
                                      0
                                      0
                                      0
                                    
- World XY plane
- c7f844d2-ba5e-476f-b4d4-193dcea7a216
- Plane
- P
- false
- 0
- 
                              525
                              1517
                              16
                              24
                            
- 
                              533
                              1529
                            
- 57da07bd-ecab-415d-9d86-af36d7073abc
- Number Slider
- Numeric slider for single values
- d1327bed-c875-4acd-82dd-5fed4b45b311
- Number Slider
- height
- false
- 0
- 
                          168
                          1608
                          381
                          20
                        
- 
                          168.731
                          1608.997
                        
- 2
- 1
- 0
- 200
- 0
- 0
- 89
- 59e0b89a-e487-49f8-bab8-b5bab16be14c
- Panel
- A panel for custom notes and text values
- e3db26aa-60fb-43b8-8092-d7ecfc283153
- Panel
- false
- 0
- a2a9f9ae-744d-4886-a3ee-4c33b8365028
- 1
- Double click to edit panel content…
- 
                          743
                          1557
                          97
                          38
                        
- 0
- 0
- 0
- 
                          743.3972
                          1557.754
                        
- 
                          255;255;250;90
                        
- true
- true
- true
- false
- false
- true
- 59e0b89a-e487-49f8-bab8-b5bab16be14c
- Panel
- A panel for custom notes and text values
- dfa914e0-e01f-4bbe-b66d-a9d4a08bb5c7
- Panel
- false
- 0
- 0c900729-ed6e-40e8-809f-e2432521ac54
- 1
- Double click to edit panel content…
- 
                          854
                          1582
                          105
                          55
                        
- 0
- 0
- 0
- 
                          854.3154
                          1582.622
                        
- 
                          255;255;250;90
                        
- true
- true
- true
- false
- false
- true
- 59e0b89a-e487-49f8-bab8-b5bab16be14c
- Panel
- A panel for custom notes and text values
- b487f9ab-5cec-404a-9235-d2a5f0e79007
- Panel
- false
- 0
- 7772d1f7-9786-4d55-8690-af9d6877a777
- 1
- Double click to edit panel content…
- 
                          742
                          1618
                          97
                          38
                        
- 0
- 0
- 0
- 
                          742.3411
                          1618.138
                        
- 
                          255;255;250;90
                        
- true
- true
- true
- false
- false
- true
- 59e0b89a-e487-49f8-bab8-b5bab16be14c
- Panel
- A panel for custom notes and text values
- bdda70a3-abe5-47d3-bab1-d54eaac87273
- Panel
- false
- 0
- 0
- -150
- 
                          378
                          1465
                          50
                          20
                        
- 0
- 0
- 0
- 
                          378.501
                          1465.184
                        
- 
                          255;255;250;90
                        
- true
- true
- true
- false
- false
- true
- 59e0b89a-e487-49f8-bab8-b5bab16be14c
- Panel
- A panel for custom notes and text values
- 18da725f-8fce-4b5c-bfc0-b35f534747f4
- Panel
- false
- 0
- 0
- -150
- 
                          377
                          1434
                          50
                          20
                        
- 0
- 0
- 0
- 
                          377.701
                          1434.784
                        
- 
                          255;255;250;90
                        
- true
- true
- true
- false
- false
- true
- 7f5c6c55-f846-4a08-9c9a-cfdc285cc6fe
- Scribble
- true
- 
                      1685.887
                      79.1758
                    
- 
                      1984.071
                      81.3421
                    
- 
                      1983.831
                      114.478
                    
- 
                      1685.647
                      112.3117
                    
- A quick note
- Microsoft Sans Serif
- 18f8db3f-bb9b-4a79-9d98-1a46a8a0c59b
- false
- Scribble
- Scribble
- 16
- Negative width = self-intersecting result
   Negative height and angle work too
- 
                          1680.647
                          74.1758
                          308.4244
                          45.30215
                        
- 
                          1685.887
                          79.1758
                        
- 079bd9bd-54a0-41d4-98af-db999015f63d
- VB Script
-   Private Function IsSet(ByVal param As String) As Boolean  ' Check if an input parameter has data
    Dim i As Integer = Component.Params.IndexOfInputParam(param)
    If i > -1 Then
      Return Component.Params.Input.ElementAt(i).DataType > 1  ' input parameter DataType of 1 means it's not receiving input (internal or external)
    Else
      Msg("error", "Input parameter '" & param & "' not found")
      Return False
    End If
  End Function
  Private Sub Msg(ByVal type As String, ByVal msg As String)  ' Output an error, warning, or informational message
    Select Case type
      Case "error"
        Component.AddRuntimeMessage(GH_RuntimeMessageLevel.Error, msg)
        Print("Error: " & msg)
      Case "warning"
        Component.AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, msg)
        Print("Warning: " & msg)
      Case "info"
        Component.AddRuntimeMessage(GH_RuntimeMessageLevel.Remark, msg)
        Print(msg)
    End Select
  End Sub
  ' Solve for the m parameter from length and width (reference {1} equation (34), except b = width and K(k) and E(k) should be K(m) and E(m))
  Private Function SolveMFromLenWid(ByVal L As Double, ByVal w As Double) As Double
    If w = 0 Then
      Return Defined.M_ZERO_W  ' for the boundry condition width = 0, bypass the function and return the known m value
    End If
    Dim n As Integer = 1 ' Iteration counter (quit if >MAXIT)
    Dim lower As Double = 0 ' m must be within this range
    Dim upper As Double = 1
    Dim m As Double
    Dim cwl As Double
    Do While (upper - lower) > Defined.MAXERR AndAlso (n) < Defined.MAXIT ' Repeat until range narrow enough or MAXIT
      m = (upper + lower) / 2
      cwl = 2 * EllipticE(m) / EllipticK(m) - 1  ' calculate w/L with the test value of m
      If cwl < w / L Then  ' compares the calculated w/L with the actual w/L then narrows the range of possible m
        upper = m
      Else
        lower = m
      End If
      n += 1
    Loop
    Return m
  End Function
  ' Solve for the m parameter from length and height (reference {1} equation (33), except K(k) should be K(m) and k = sqrt(m))
  ' Note that it's actually possible to find 2 valid values for m (hence 2 width values) at certain height values
  Private Function SolveMFromLenHt(ByVal L As Double, ByVal h As Double) As List(Of Double)
    Dim n As Integer = 1 ' Iteration counter (quit if >MAXIT)
    Dim lower As Double = 0 ' m must be within this range
    Dim upper As Double = 1
    Dim twoWidths As Boolean = h / L >= Defined.DOUBLE_W_HL_RATIO And h / L < Defined.MAX_HL_RATIO  ' check to see if h/L is within the range where 2 solutions for the width are possible
    Dim m As Double
    Dim mult_m As New List(Of Double)
    Dim chl As Double
    If twoWidths Then
      ' find the first of two possible solutions for m with the following limits:
      lower = Defined.M_DOUBLE_W  ' see constants at bottom of script
      upper = Defined.M_MAXHEIGHT  ' see constants at bottom of script
      Do While (upper - lower) > Defined.MAXERR AndAlso (n) < Defined.MAXIT ' Repeat until range narrow enough or MAXIT
        m = (upper + lower) / 2
        chl = Math.Sqrt(m) / EllipticK(m)  ' calculate h/L with the test value of m
        If chl > h / L Then  ' compares the calculated h/L with the actual h/L then narrows the range of possible m
          upper = m
        Else
          lower = m
        End If
        n += 1
      Loop
      mult_m.Add(m)
      ' then find the second of two possible solutions for m with the following limits:
      lower = Defined.M_MAXHEIGHT  ' see constants at bottom of script
      upper = 1
      Do While (upper - lower) > Defined.MAXERR AndAlso (n) < Defined.MAXIT ' Repeat until range narrow enough or MAXIT
        m = (upper + lower) / 2
        chl = Math.Sqrt(m) / EllipticK(m)  ' calculate h/L with the test value of m
        If chl < h / L Then  ' compares the calculated h/L with the actual h/L then narrows the range of possible m
          upper = m
        Else
          lower = m
        End If
        n += 1
      Loop
      If m <= Defined.M_MAX Then  ' return this m parameter only if it falls within the maximum useful value (above which the curve breaks down)
        mult_m.Add(m)
      End If
    Else
      ' find the one possible solution for the m parameter
      upper = Defined.M_DOUBLE_W  ' limit the upper end of the search to the maximum value of m for which only one solution exists
      Do While (upper - lower) > Defined.MAXERR AndAlso (n) < Defined.MAXIT ' Repeat until range narrow enough or MAXIT
        m = (upper + lower) / 2
        chl = Math.Sqrt(m) / EllipticK(m)  ' calculate h/L with the test value of m
        If chl > h / L Then  ' compares the calculated h/L with the actual h/L then narrows the range of possible m
          upper = m
        Else
          lower = m
        End If
        n += 1
      Loop
      mult_m.Add(m)
    End If
    Return mult_m
  End Function
  ' Solve for the m parameter from width and height (derived from reference {1} equations (33) and (34) with same notes as above)
  Private Function SolveMFromWidHt(ByVal w As Double, ByVal h As Double) As Double
    Dim n As Integer = 1 ' Iteration counter (quit if >MAXIT)
    Dim lower As Double = 0 ' m must be within this range
    Dim upper As Double = 1
    Dim m As Double
    Dim cwh As Double
    Do While (upper - lower) > Defined.MAXERR AndAlso (n) < Defined.MAXIT ' Repeat until range narrow enough or MAXIT
      m = (upper + lower) / 2
      cwh = (2 * EllipticE(m) - EllipticK(m)) / Math.Sqrt(m)  ' calculate w/h with the test value of m
      If cwh < w / h Then  ' compares the calculated w/h with the actual w/h then narrows the range of possible m
        upper = m
      Else
        lower = m
      End If
      n += 1
    Loop
    Return m
  End Function
  ' Calculate length based on height and an m parameter, derived from reference {1} equation (33), except K(k) should be K(m) and k = sqrt(m)
  Private Function Cal_L(ByVal h As Double, ByVal m As Double) As Double
    Return h * EllipticK(m) / Math.Sqrt(m)
  End Function
  ' Calculate width based on length and an m parameter, derived from reference {1} equation (34), except b = width and K(k) and E(k) should be K(m) and E(m)
  Private Function Cal_W(ByVal L As Double, ByVal m As Double) As Double
    Return L * (2 * EllipticE(m) / EllipticK(m) - 1)
  End Function
  ' Calculate height based on length and an m parameter, from reference {1} equation (33), except K(k) should be K(m) and k = sqrt(m)
  Private Function Cal_H(ByVal L As Double, ByVal m As Double) As Double
    Return L * Math.Sqrt(m) / EllipticK(m)
  End Function
  ' Calculate the unique m parameter based on a start tangent angle, from reference {2}, just above equation (9a), that states k = Sin(angle / 2 + Pi / 4),
  ' but as m = k^2 and due to this script's need for an angle rotated 90° versus the one in reference {1}, the following formula is the result
  ' New note: verified by reference {4}, pg. 78 at the bottom
  Private Function Cal_M(ByVal a As Double) As Double
    Return (1 - Math.Cos(a)) / 2  ' equal to Sin^2(a/2) too
  End Function
  ' Calculate start tangent angle based on an m parameter, derived from above formula
  Private Function Cal_A(ByVal m As Double) As Double
    Return Math.Acos(1 - 2 * m)
  End Function
  ' This is the heart of this script, taking the found (or specified) length, width, and angle values along with the found m parameter to create
  ' a list of points that approximate the shape or form of the elastica. It works by finding the x and y coordinates (which are reversed versus
  ' the original equations (12a) and (12b) from reference {2} due to the 90° difference in orientation) based on the tangent angle along the curve.
  ' See reference {2} for more details on how they derived it. Note that to simplify things, the algorithm only calculates the points for half of the
  ' curve, then mirrors those points along the y-axis.
  Private Function FindBendForm(ByVal L As Double, ByVal w As Double, ByVal m As Double, ByVal ang As Double, ByVal refPln As Plane) As List(Of Point3d)
    L = L / 2  ' because the below algorithm is based on the formulas in reference {2} for only half of the curve
    w = w / 2  ' same
    If ang = 0 Then  ' if angle (and height) = 0, then simply return the start and end points of the straight line
      Dim out As New List(Of Point3d)
      out.Add(refPln.PointAt(w, 0, 0))
      out.Add(refPln.PointAt(-w, 0, 0))
      Return out
    End If
    Dim x As Double
    Dim y As Double
    Dim halfCurvePts As New List(Of Point3d)
    Dim fullCurvePts As New List(Of Point3d)
    Dim translatedPts As New List(Of Point3d)
    ang -= Math.PI / 2  ' a hack to allow this algorithm to work, since the original curve in paper {2} was rotated 90°
    Dim angB As Double = ang + (-Math.PI / 2 - ang) / Defined.CURVEDIVS  ' angB is the 'lowercase theta' which should be in formula {2}(12b) as the interval
    ' start [a typo...see equation(3)]. It's necessary to start angB at ang + [interval] instead of just ang due to integration failing at angB = ang
    halfCurvePts.Add(New Point3d(w, 0, 0))  ' start with this known initial point, as integration will fail when angB = ang
    ' each point {x, y} is calculated from the tangent angle, angB, that occurs at each point (which is why this iterates from ~ang to -pi/2, the known end condition)
    Do While Math.Round(angB, Defined.ROUNDTO) >= Math.Round(-Math.PI / 2, Defined.ROUNDTO)
      y = (Math.Sqrt(2) * Math.Sqrt(Math.Sin(ang) - Math.Sin(angB)) * (w + L)) / (2 * EllipticE(m))  ' note that x and y are swapped vs. (12a) and (12b)
      x = (L / (Math.Sqrt(2) * EllipticK(m))) * Simpson(angB, -Math.PI / 2, 500, ang)  ' calculate the Simpson approximation of the integral (function f below)
      ' over the interval angB ('lowercase theta') to -pi/2. side note: is 500 too few iterations for the Simson algorithm?
      If Math.Round(x, Defined.ROUNDTO) = 0 Then x = 0
      halfCurvePts.Add(New Point3d(x, y, 0))
      angB += (-Math.PI / 2 - ang) / Defined.CURVEDIVS  ' onto the next tangent angle
    Loop
    ' After finding the x and y values for half of the curve, add the {-x, y} values for the rest of the curve
    For Each point As Point3d In halfCurvePts
      If Math.Round(point.X, Defined.ROUNDTO) = 0 Then
        If Math.Round(point.Y, Defined.ROUNDTO) = 0 Then
          fullCurvePts.Add(New Point3d(0, 0, 0))  ' special case when width = 0: when x = 0, only duplicate the point when y = 0 too
        End If
      Else
        fullCurvePts.Add(New Point3d(-point.X, point.Y, 0))
      End If
    Next
    halfCurvePts.Reverse
    fullCurvePts.AddRange(halfCurvePts)
    For Each p As Point3d In fullCurvePts
      translatedPts.Add(refPln.PointAt(p.X, p.Y, p.Z))  ' translate the points from the reference plane to the world plane
    Next
    Return translatedPts
  End Function
  ' Interpolates the points from FindBendForm to create the Elastica curve. Uses start & end tangents for greater accuracy.
  Private Function MakeCurve(ByVal pts As List(Of Point3d), ByVal ang As Double, ByVal refPln As Plane) As Curve
    If ang <> 0 Then
      Dim ts, te As New Vector3d(refPln.XAxis)
      ts.Rotate(ang, refPln.ZAxis)
      te.Rotate(-ang, refPln.ZAxis)
      Return Curve.CreateInterpolatedCurve(pts, 3, CurveKnotStyle.Chord, ts, te)  ' 3rd degree curve with 'Chord' Knot Style
    Else
      Return Curve.CreateInterpolatedCurve(pts, 3)  ' if angle (and height) = 0, then simply interpolate the straight line (no start/end tangents)
    End If
  End Function
  ' Implements the Simpson approximation for an integral of function f below
  Public Function Simpson(a As Double, b As Double, n As Integer, theta As Double) As Double 'n should be an even number
    Dim j As Integer, s1 As Double, s2 As Double, h As Double
    h = (b - a) / n
    s1 = 0
    s2 = 0
    For j = 1 To n - 1 Step 2
      s1 = s1 + fn(a + j * h, theta)
    Next j
    For j = 2 To n - 2 Step 2
      s2 = s2 + fn(a + j * h, theta)
    Next j
    Simpson = h / 3 * (fn(a, theta) + 4 * s1 + 2 * s2 + fn(b, theta))
  End Function
  ' Specific calculation for the above integration
  Public Function fn(x As Double, theta As Double) As Double
    fn = Math.Sin(x) / (Math.Sqrt(Math.Sin(theta) - Math.Sin(x)))  ' from reference {2} formula (12b)
  End Function
  ' Return the Complete Elliptic integral of the 1st kind
  ' Abramowitz and Stegun p.591, formula 17.3.11
  ' Code from http://www.codeproject.com/Articles/566614/Elliptic-integrals
  Public Function EllipticK(ByVal m As Double) As Double
    Dim sum, term, above, below As Double
    sum = 1
    term = 1
    above = 1
    below = 2
    For i As Integer = 1 To 100
      term *= above / below
      sum += Math.Pow(m, i) * Math.Pow(term, 2)
      above += 2
      below += 2
    Next
    sum *= 0.5 * Math.PI
    Return sum
  End Function
  ' Return the Complete Elliptic integral of the 2nd kind
  ' Abramowitz and Stegun p.591, formula 17.3.12
  ' Code from http://www.codeproject.com/Articles/566614/Elliptic-integrals
  Public Function EllipticE(ByVal m As Double) As Double
    Dim sum, term, above, below As Double
    sum = 1
    term = 1
    above = 1
    below = 2
    For i As Integer = 1 To 100
      term *= above / below
      sum -= Math.Pow(m, i) * Math.Pow(term, 2) / above
      above += 2
      below += 2
    Next
    sum *= 0.5 * Math.PI
    Return sum
  End Function
  Friend Partial NotInheritable Class Defined
    Private Sub New()
    End Sub
    ' Note: most of these values for m and h/L ratio were found with Wolfram Alpha and either specific intercepts (x=0) or local minima/maxima. They should be constant.
    Public Const M_SKETCHY As Double = 0.95  ' value of the m parameter where the curvature near the ends of the curve gets wonky
    Public Const M_MAX As Double = 0.993  ' maximum useful value of the m parameter, above which this algorithm for the form of the curve breaks down
    Public Const M_ZERO_W As Double = 0.826114765984970336  ' value of the m parameter when width = 0
    Public Const M_MAXHEIGHT As Double = 0.701327460663101223  ' value of the m parameter at maximum possible height of the bent rod/wire
    Public Const M_DOUBLE_W As Double = 0.180254422335013983  ' minimum value of the m parameter when two width values are possible for a given height and length
    Public Const DOUBLE_W_HL_RATIO As Double = 0.257342117984635757  ' value of the height/length ratio above which there are two possible width values
    Public Const MAX_HL_RATIO As Double = 0.403140189705650243  ' maximum possible value of the height/length ratio
    Public Const MAXERR As Double = 0.0000000001  ' error tolerance
    Public Const MAXIT As Integer = 100  ' maximum number of iterations
    Public Const ROUNDTO As Integer = 10  ' number of decimal places to round off to
    Public Const CURVEDIVS As Integer = 50  ' number of sample points for building the curve (or half-curve as it were)
  End Class
- A VB.NET scriptable component
- 
                      98
                      86
                    
- true
- 15a333e8-a6e9-40f9-ae49-542ab7d2e084
- VB Script
- VB
- true
- 0
-     ' -----------------------------------------------------------------
    ' Elastic Bending Script by Will McElwain
    ' Created February 2014
    '
    ' DESCRIPTION:
    ' This beast creates the so-called 'elastica curve', the shape a long, thin rod or wire makes when it is bent elastically (i.e. not permanently). In this case, force
    ' is assumed to only be applied horizontally (which would be in line with the rod at rest) and both ends are assumed to be pinned or hinged meaning they are free
    ' to rotate (as opposed to clamped, when the end tangent angle is fixed, usually horizontally). An interesting finding is that it doesn't matter what the material or
    ' cross-sectional area is, as long as they're uniform along the entire length. Everything makes the same shape when bent as long as it doesn't cross the threshold
    ' from elastic to plastic (permanent) deformation (I don't bother to find that limit here, but can be found if the yield stress for a material is known).
    '
    ' Key to the formulas used in this script are elliptic integrals, specifically K(m), the complete elliptic integral of the first kind, and E(m), the complete elliptic
    ' integral of the second kind. There was a lot of confusion over the 'm' and 'k' parameters for these functions, as some people use them interchangeably, but they are
    ' not the same. m = k^2 (thus k = Sqrt(m)). I try to use the 'm' parameter exclusively to avoid this confusion. Note that there is a unique 'm' parameter for every
    ' configuration/shape of the elastica curve.
    '
    ' This script tries to find that unique 'm' parameter based on the inputs. The algorithm starts with a test version of m, evaluates an expression, say 2*E(m)/K(m)-1,
    ' then compares the result to what it should be (in this case, a known width/length ratio). Iterate until the correct m is found. Once we have m, we can then calculate
    ' all of the other unknowns, then find points that lie on that curve, then interpolate those points for the actual curve. You can also use Wolfram|Alpha as I did to
    ' find the m parameter based on the equations in this script (example here: http://tiny.cc/t4tpbx for when say width=45.2 and length=67.1).
    '
    ' Other notes:
    ' * This script works with negative values for width, which will creat a self-intersecting curve (as it should). The curvature of the elastica starts to break down around
    ' m=0.95 (~154°), but this script will continue to work until M_MAX, m=0.993 (~169°). If you wish to ignore self-intersecting curves, set ignoreSelfIntersecting to True
    ' * When the only known values are length and height, it is actually possible for certain ratios of height to length to have two valid m values (thus 2 possible widths
    ' and angles). This script will return them both.
    ' * Only the first two valid parameters (of the required ones) will be used, meaning if all four are connected (length, width or a PtB, height, and angle), this script will
    ' only use length and width (or a PtB).
    ' * Depending on the magnitude of your inputs (say if they're really small, like if length < 10), you might have to increase the constant ROUNDTO at the bottom
    '
    ' REFERENCES:
    ' {1} "The elastic rod" by M.E. Pacheco Q. & E. Pina, http://www.scielo.org.mx/pdf/rmfe/v53n2/v53n2a8.pdf
    ' {2} "An experiment in nonlinear beam theory" by A. Valiente, http://www.deepdyve.com/lp/doc/I3lwnxdfGz , also here: http://tiny.cc/Valiente_AEiNBT
    ' {3} "Snap buckling, writhing and Loop formation In twisted rods" by V.G.A. GOSS, http://myweb.lsbu.ac.uk/~gossga/thesisFinal.pdf
    ' {4} "Theory of Elastic Stability" by Stephen Timoshenko, http://www.scribd.com/doc/50402462/Timoshenko-Theory-of-Elastic-Stability  (start on p. 76)
    '
    ' INPUT:
    ' PtA - First anchor point (required)
    ' PtB - Second anchor point (optional, though 2 out of the 4--length, width, height, angle--need to be specified)
    '       [note that PtB can be the same as PtA (meaning width would be zero)]
    '       [also note that if a different width is additionally specified that's not equal to the distance between PtA and PtB, then the end point will not equal PtB anymore]
    ' Pln - Plane of the bent rod/wire, which bends up in the +y direction. The line between PtA and PtB (if specified) must be parallel to the x-axis of this plane
    '
    ' ** 2 of the following 4 need to be specified **
    ' Len - Length of the rod/wire, which needs to be > 0
    ' Wid - Width between the endpoints of the curve [note: if PtB is specified in addition, and distance between PtA and PtB <> width, the end point will be relocated
    ' Ht - Height of the bent rod/wire (when negative, curve will bend downward, relative to the input plane, instead)
    ' Ang - Inner departure angle or tangent angle (in radians) at the ends of the bent rod/wire. Set up so as width approaches length (thus height approaches zero), angle approaches zero
    '
    ' * Following variables only needed for optional calculating of bending force, not for shape of curve.
    ' E - Young's modulus (modulus of elasticity) in GPa (=N/m^2) (material-specific. for example, 7075 aluminum is roughly 71.7 GPa)
    ' I - Second moment of area (or area moment of inertia) in m^4 (cross-section-specific. for example, a hollow rod
    '     would have I = pi * (outer_diameter^4 - inner_diameter^4) / 32
    ' Note: E*I is also known as flexural rigidity or bending stiffness
    '
    ' OUTPUT:
    ' out - only for debugging messages
    ' Pts - the list of points that approximate the shape of the elastica
    ' Crv - the 3rd-degree curve interpolated from those points (with accurate start & end tangents)
    ' L - the length of the rod/wire
    ' W - the distance (width) between the endpoints of the rod/wire
    ' H - the height of the bent rod/wire
    ' A - the tangent angle at the (start) end of the rod/wire
    ' F - the force needed to hold the rod/wire in a specific shape (based on the material properties & cross-section) **be sure your units for 'I' match your units for the
    ' rest of your inputs (length, width, etc.). Also note that the critical buckling load (force) that makes the rod/wire start to bend can be found at height=0
    '
    ' THANKS TO:
    ' Mårten Nettelbladt (thegeometryofbending.blogspot.com)
    ' Daniel Piker (Kangaroo plugin)
    ' David Rutten (Grasshopper guru)
    ' Euler & Bernoulli (the O.G.'s)
    '
    ' -----------------------------------------------------------------
    Dim ignoreSelfIntersecting As Boolean = False  ' set to True if you don't want to output curves where width < 0, which creates a self-intersecting curve
    Dim inCt As Integer = 0  ' count the number of required parameters that are receiving data
    Dim length As Double
    Dim width As System.Object = Nothing  ' need to set as Nothing so we can check if it has been assigned a value later
    Dim height As Double
    Dim angle As Double
    Dim m As Double
    Dim multiple_m As New List(Of Double)
    Dim AtoB As Line
    Dim flip_H As Boolean = False  ' if height is negative, this flag will be set
    Dim flip_A As Boolean = False  ' if angle is negative, this flag will be set
    If Not IsSet("Pln") Then
      Msg("error", "Base plane is not set")
      Return
    End If
    If Not IsSet("PtA") Then
      Msg("error", "Point A is not set")
      Return
    End If
    If Math.Round(Pln.DistanceTo(PtA), Defined.ROUNDTO) <> 0 Then
      Msg("error", "Point A is not on the base plane")
      Return
    End If
    Dim refPlane As Plane = Pln  ' create a reference plane = input plane and set the origin of it to PtA in case PtA isn't the origin already
    refPlane.Origin = PtA
    If IsSet("PtB") Then
      If Math.Round(Pln.DistanceTo(PtB), Defined.ROUNDTO) <> 0 Then
        Msg("error", "Point B is not on the base plane")
        Return
      End If
      AtoB = New Line(PtA, PtB)
      If AtoB.Length <> 0 And Not AtoB.Direction.IsPerpendicularTo(Pln.YAxis) Then
        Msg("error", "The line between PtA and PtB is not perpendicular to the Y-axis of the specified plane")
        Return
      End If
      inCt += 1
      If IsSet("Wid") Then Msg("info", "Wid will override the distance between PtA and PtB. If you do not want this to happen, disconnect PtB or Wid.")
      width = PtA.DistanceTo(PtB)  ' get the width (distance) between PtA and PtB
      
      Dim refPtB As Point3d
      refPlane.RemapToPlaneSpace(PtB, refPtB)
      If refPtB.X < 0 Then width = -width  ' check if PtB is to the left of PtA...if so, width is negative
    End If
    If IsSet("Len") Then inCt += 1
    If IsSet("Wid") Then inCt += 1
    If IsSet("Ht") Then inCt += 1
    If IsSet("Ang") Then inCt += 1
    If inCt > 2 Then Msg("info", "More parameters set than are required (out of length, width, height, angle). Only using the first two valid ones.")
    ' check for connected/specified inputs. note: only the first two that it comes across will be used
    If IsSet("Len") Then  ' if length is specified then...
      If Len <= 0 Then
        Msg("error", "Length cannot be negative or zero")
        Return
      End If
      If IsSet("Wid") Then  ' find height & angle based on length and specified width
        If Wid > Len Then
          Msg("error", "Width is greater than length")
          Return
        End If
        If Wid = Len Then  ' skip the solver and set the known values
          height = 0
          m = 0
          angle = 0
          width = Wid
        Else
          m = SolveMFromLenWid(Len, Wid)
          height = Cal_H(Len, m)  ' L * Sqrt(m) / K(m)
          angle = Cal_A(m)  ' Acos(1 - 2 * m)
          width = Wid
        End If
      Else If width IsNot Nothing Then  ' find height & angle based on length and calculated width (distance between PtA and PtB)
        If width > Len Then
          Msg("error", "Width is greater than length")
          Return
        End If
        If width = Len Then  ' skip the solver and set the known values
          height = 0
          m = 0
          angle = 0
        Else
          m = SolveMFromLenWid(Len, width)
          height = Cal_H(Len, m)  ' L * Sqrt(m) / K(m)
          angle = Cal_A(m)  ' Acos(1 - 2 * m)
        End If
      Else If IsSet("Ht") Then  ' find width & angle based on length and height  ** possible to return 2 results **
        If Math.Abs(Ht / Len) > Defined.MAX_HL_RATIO Then
          Msg("error", "Height not possible with given length")
          Return
        End If
        If Ht < 0 Then
          Ht = -Ht  ' if height is negative, set it to positive (for the calculations) but flip the reference plane about its x-axis
          refPlane.Transform(Transform.Mirror(New Plane(refPlane.Origin, refPlane.XAxis, refPlane.ZAxis)))
          flip_A = True
          flip_H = True
        End If
        If Ht = 0 Then  ' skip the solver and set the known values
          width = Len
          angle = 0
        Else
          multiple_m = SolveMFromLenHt(Len, Ht)  ' note that it's possible for two values of m to be found if height is close to max height
          If multiple_m.Count = 1 Then  ' if there's only one m value returned, calculate the width & angle here. we'll deal with multiple m values later
            m = multiple_m.Item(0)
            width = Cal_W(Len, m)  ' L * (2 * E(m) / K(m) - 1)
            angle = Cal_A(m)  ' Acos(1 - 2 * m)
          End If
        End If
        height = Ht
      Else If IsSet("Ang") Then  ' find width & height based on length and angle
        If Ang < 0 Then
          Ang = -Ang  ' if angle is negative, set it to positive (for the calculations) but flip the reference plane about its x-axis
          refPlane.Transform(Transform.Mirror(New Plane(refPlane.Origin, refPlane.XAxis, refPlane.ZAxis)))
          flip_A = True
          flip_H = True
        End If
        m = Cal_M(Ang)  ' (1 - Cos(a)) / 2
        If Ang = 0 Then  ' skip the solver and set the known values
          width = Len
          height = 0
        Else
          width = Cal_W(Len, m)  ' L * (2 * E(m) / K(m) - 1)
          height = Cal_H(Len, m)  ' L * Sqrt(m) / K(m)
        End If
        angle = Ang
      Else
        Msg("error", "Need to specify one more parameter in addition to length")
        Return
      End If
      length = Len
    Else If IsSet("Wid") Then  ' if width is specified then...
      If IsSet("Ht") Then  ' find length & angle based on specified width and height
        If Ht < 0 Then
          Ht = -Ht  ' if height is negative, set it to positive (for the calculations) but flip the reference plane about its x-axis
          refPlane.Transform(Transform.Mirror(New Plane(refPlane.Origin, refPlane.XAxis, refPlane.ZAxis)))
          flip_A = True
          flip_H = True
        End If
        If Ht = 0 Then  ' skip the solver and set the known values
          length = Wid
          angle = 0
        Else
          m = SolveMFromWidHt(Wid, Ht)
          length = Cal_L(Ht, m)  ' h * K(m) / Sqrt(m)
          angle = Cal_A(m)  ' Acos(1 - 2 * m)
        End If
        height = Ht
      Else If IsSet("Ang") Then  ' find length & height based on specified width and angle
        If Wid = 0 Then
          Msg("error", "Curve not possible with width = 0 and an angle as inputs")
          Return
        End If
        If Ang < 0 Then
          Ang = -Ang  ' if angle is negative, set it to positive (for the calculations) but flip the reference plane about its x-axis
          refPlane.Transform(Transform.Mirror(New Plane(refPlane.Origin, refPlane.XAxis, refPlane.ZAxis)))
          flip_A = True
          flip_H = True
        End If
        m = Cal_M(Ang)  ' (1 - Cos(a)) / 2
        If Ang = 0 Then  ' skip the solver and set the known values
          length = Wid
          height = 0
        Else
          length = Wid / (2 * EllipticE(m) / EllipticK(m) - 1)
          If length < 0 Then
            Msg("error", "Curve not possible at specified width and angle (calculated length is negative)")
            Return
          End If
          height = Cal_H(length, m)  ' L * Sqrt(m) / K(m)
        End If
        angle = Ang
      Else
        Msg("error", "Need to specify one more parameter in addition to width (Wid)")
        Return
      End If
      width = Wid
    Else If width IsNot Nothing Then  ' if width is determined by PtA and PtB then...
      If IsSet("Ht") Then  ' find length & angle based on calculated width and height
        If Ht < 0 Then
          Ht = -Ht  ' if height is negative, set it to positive (for the calculations) but flip the reference plane about its x-axis
          refPlane.Transform(Transform.Mirror(New Plane(refPlane.Origin, refPlane.XAxis, refPlane.ZAxis)))
          flip_A = True
          flip_H = True
        End If
        If Ht = 0 Then  ' skip the solver and set the known values
          length = width
          angle = 0
        Else
          m = SolveMFromWidHt(width, Ht)
          length = Cal_L(Ht, m)  ' h * K(m) / Sqrt(m)
          angle = Cal_A(m)  ' Acos(1 - 2 * m)
        End If
        height = Ht
      Else If IsSet("Ang") Then  ' find length & height based on calculated width and angle
        If width = 0 Then
          Msg("error", "Curve not possible with width = 0 and an angle as inputs")
          Return
        End If
        If Ang < 0 Then
          Ang = -Ang  ' if angle is negative, set it to positive (for the calculations) but flip the reference plane about its x-axis
          refPlane.Transform(Transform.Mirror(New Plane(refPlane.Origin, refPlane.XAxis, refPlane.ZAxis)))
          flip_A = True
          flip_H = True
        End If
        m = Cal_M(Ang)  ' (1 - Cos(a)) / 2
        If Ang = 0 Then  ' skip the solver and set the known values
          length = width
          height = 0
        Else
          length = width / (2 * EllipticE(m) / EllipticK(m) - 1)
          If length < 0 Then
            Msg("error", "Curve not possible at specified width and angle (calculated length is negative)")
            Return
          End If
          height = Cal_H(length, m)  ' L * Sqrt(m) / K(m)
        End If
        angle = Ang
      Else
        Msg("error", "Need to specify one more parameter in addition to PtA and PtB")
        Return
      End If
    Else If IsSet("Ht") Then  ' if height is specified then...
      If IsSet("Ang") Then  ' find length & width based on height and angle
        If Ht < 0 Then
          Ht = -Ht  ' if height is negative, set it to positive (for the calculations) but flip the reference plane about its x-axis
          refPlane.Transform(Transform.Mirror(New Plane(refPlane.Origin, refPlane.XAxis, refPlane.ZAxis)))
          flip_H = True
          flip_A = True
        End If
        If Ht = 0 Then
          Msg("error", "Height can't = 0 if only height and angle are specified")
          Return
        Else
          If Ang < 0 Then
            Ang = -Ang  ' if angle is negative, set it to positive (for the calculations) but flip the reference plane about its x-axis
            refPlane.Transform(Transform.Mirror(New Plane(refPlane.Origin, refPlane.XAxis, refPlane.ZAxis)))
            flip_A = Not flip_A
            flip_H = Not flip_H
          End If
          m = Cal_M(Ang)  ' (1 - Cos(a)) / 2
          If Ang = 0 Then
            Msg("error", "Angle can't = 0 if only height and angle are specified")
            Return
          Else
            length = Cal_L(Ht, m)  ' h * K(m) / Sqrt(m)
            width = Cal_W(length, m)  ' L * (2 * E(m) / K(m) - 1)
          End If
          angle = Ang
        End If
        height = Ht
      Else
        Msg("error", "Need to specify one more parameter in addition to height")
        Return
      End If
    Else If IsSet("Ang") Then
      Msg("error", "Need to specify one more parameter in addition to angle")
      Return
    Else
      Msg("error", "Need to specify two of the four parameters: length, width (or PtB), height, and angle")
      Return
    End If
    If m > Defined.M_MAX Then
      Msg("error", "Form of curve not solvable with current algorithm and given inputs")
      Return
    End If
    refPlane.Origin = refPlane.PointAt(width / 2, 0, 0)  ' adjust the origin of the reference plane so that the curve is centered about the y-axis (start of the curve is at x = -width/2)
    If multiple_m.Count > 1 Then  ' if there is more than one m value returned, calculate the width, angle, and curve for each
      Dim multi_pts As New DataTree(Of Point3d)
      Dim multi_crv As New List(Of Curve)
      Dim tmp_pts As New List(Of Point3d)
      Dim multi_W, multi_A, multi_F As New List(Of Double)
      Dim j As Integer = 0  ' used for creating a new branch (GH_Path) for storing pts which is itself a list of points
      For Each m_val As Double In multiple_m
        width = Cal_W(length, m_val) 'length * (2 * EllipticE(m_val) / EllipticK(m_val) - 1)
        
        If width < 0 And ignoreSelfIntersecting Then
          Msg("warning", "One curve is self-intersecting. To enable these, set ignoreSelfIntersecting to False")
          Continue For
        End If
        
        If m_val >= Defined.M_SKETCHY Then Msg("info", "Accuracy of the curve whose width = " & Math.Round(width, 4) & " is not guaranteed")
        
        angle = Cal_A(m_val) 'Math.Asin(2 * m_val - 1)
        refPlane.Origin = refPlane.PointAt(width / 2, 0, 0)  ' adjust the origin of the reference plane so that the curve is centered about the y-axis (start of the curve is at x = -width/2)
        
        tmp_pts = FindBendForm(length, width, m_val, angle, refPlane)
        multi_pts.AddRange(tmp_pts, New GH_Path(j))
        multi_crv.Add(MakeCurve(tmp_pts, angle, refPlane))
        
        multi_W.Add(width)
        If flip_A Then angle = -angle
        multi_A.Add(angle)
        
        E = E * 10 ^ 9  ' Young's modulus input E is in GPa, so we convert to Pa here (= N/m^2)
        multi_F.Add(EllipticK(m_val) ^ 2 * E * I / length ^ 2)  ' from reference {4} pg. 79
        
        j += 1
        refPlane.Origin = PtA  ' reset the reference plane origin to PtA for the next m_val
        'Print("length=" & length & ", width=" & width & ", height=" & height & ", angle=" & angle & ", m=" & m_val & ", k=" & Math.Sqrt(m_val) & ", w/L=" & width / length & ", h/L=" & height / length & ", w/h=" & width / height)
      Next
      ' assign the outputs
      Pts = multi_pts
      Crv = multi_crv
      L = length
      W = multi_W
      If flip_H Then height = -height
      H = height
      A = multi_A
      F = multi_F
    Else  ' only deal with the single m value
      If m >= Defined.M_SKETCHY Then Msg("info", "Accuracy of the curve at these parameters is not guaranteed")
      
      If width < 0 And ignoreSelfIntersecting Then
        Msg("error", "Curve is self-intersecting. To enable these, set ignoreSelfIntersecting to False")
        Return
      End If
      
      Pts = FindBendForm(length, width, m, angle, refPlane)
      Crv = MakeCurve(pts, angle, refPlane)
      L = length
      W = width
      If flip_H Then height = -height
      H = height
      If flip_A Then angle = -angle
      A = angle
      E = E * 10 ^ 9  ' Young's modulus input E is in GPa, so we convert to Pa here (= N/m^2)
      F = EllipticK(m) ^ 2 * E * I / length ^ 2  ' from reference {4} pg. 79. Note: the critical buckling (that makes the rod/wire start to bend) can be found at height=0 (width=length)
      'height = Math.Sqrt(((2 * Len / 5) ^ 2 - ((Wid - Len / 5) / 2) ^ 2)  ' quick approximation discovered by Mårten of 'Geometry of Bending' fame ( http://tiny.cc/it2pbx )
      'width = (Len +/- 2 * Math.Sqrt(4 * Len ^ 2 - 25 * Ht ^ 2)) / 5  ' derived from above
      'length = (2 * Math.Sqrt(15 * Ht ^ 2 + 4 * Wid ^ 2) - Wid) / 3  ' derived from above
      'Print("length=" & length & ", width=" & width & ", height=" & height & ", angle=" & angle & ", m=" & m & ", k=" & Math.Sqrt(m) & ", w/L=" & width / length & ", h/L=" & height / length & ", w/h=" & width / height)
    End If
- 
                          1797
                          201
                          84
                          184
                        
- 
                          1839
                          293
                        
- 9
- 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2
- 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2
- 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2
- 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2
- 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2
- 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2
- 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2
- 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2
- 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2
- 8
- 3ede854e-c753-40eb-84cb-b48008f14fd4
- 8ec86459-bf01-4409-baee-174d0d2b13d0
- 8ec86459-bf01-4409-baee-174d0d2b13d0
- 8ec86459-bf01-4409-baee-174d0d2b13d0
- 8ec86459-bf01-4409-baee-174d0d2b13d0
- 8ec86459-bf01-4409-baee-174d0d2b13d0
- 8ec86459-bf01-4409-baee-174d0d2b13d0
- 8ec86459-bf01-4409-baee-174d0d2b13d0
- true
- Script Variable PtA
- 512bccc3-6c0e-4ef4-ba24-8685c3ee8d8c
- PtA
- PtA
- true
- 0
- true
- 1813e6b2-8594-4cdf-882c-e312c60bd7f7
- 1
- e1937b56-b1da-4c12-8bd8-e34ee81746ef
- 
                                  1799
                                  203
                                  25
                                  20
                                
- 
                                  1813
                                  213
                                
- true
- Script Variable PtB
- d879c694-aa7a-49cc-885b-4d3c9e0e85df
- PtB
- PtB
- true
- 0
- true
- 0
- e1937b56-b1da-4c12-8bd8-e34ee81746ef
- 
                                  1799
                                  223
                                  25
                                  20
                                
- 
                                  1813
                                  233
                                
- true
- Script Variable Pln
- 0b814522-7d00-47c6-9c48-1e46bee924f2
- Pln
- Pln
- true
- 0
- true
- f9c309f7-e784-42bd-ac1d-c6f978935e00
- 1
- 3897522d-58e9-4d60-b38c-978ddacfedd8
- 
                                  1799
                                  243
                                  25
                                  20
                                
- 
                                  1813
                                  253
                                
- true
- Script Variable Len
- 693f977f-077d-410b-a1cc-bc37f0473ad9
- Len
- Len
- true
- 0
- true
- ce3bf1e3-3694-43ca-b804-94bf1ac205b6
- 1
- 8e991e99-5fb8-41e1-928d-1bba8fb9f7d7
- 
                                  1799
                                  263
                                  25
                                  20
                                
- 
                                  1813
                                  273
                                
- true
- Script Variable Wid
- e718cabe-f163-44e2-bf0e-4866946c6c49
- Wid
- Wid
- true
- 0
- true
- 2dac057e-8756-4d2f-b7af-61904cb5801a
- 1
- 8e991e99-5fb8-41e1-928d-1bba8fb9f7d7
- 
                                  1799
                                  283
                                  25
                                  20
                                
- 
                                  1813
                                  293
                                
- true
- Script Variable Ht
- f8027746-ba7f-4f8e-bb9c-fa5b544e826b
- Ht
- Ht
- true
- 0
- true
- 0
- 8e991e99-5fb8-41e1-928d-1bba8fb9f7d7
- 
                                  1799
                                  303
                                  25
                                  20
                                
- 
                                  1813
                                  313
                                
- true
- Script Variable Ang
- 50106206-1bb3-43fe-bd4f-366e3b16274a
- Ang
- Ang
- true
- 0
- true
- 0
- 8e991e99-5fb8-41e1-928d-1bba8fb9f7d7
- 
                                  1799
                                  323
                                  25
                                  20
                                
- 
                                  1813
                                  333
                                
- true
- Script Variable E
- 1d6edbeb-7707-43da-8d81-c55c2a788b19
- E
- E
- true
- 0
- true
- 0
- 8e991e99-5fb8-41e1-928d-1bba8fb9f7d7
- 
                                  1799
                                  343
                                  25
                                  20
                                
- 
                                  1813
                                  353
                                
- true
- Script Variable I
- 06ae685a-2839-4dc2-a276-de0409a26bad
- I
- I
- true
- 0
- true
- 0
- 8e991e99-5fb8-41e1-928d-1bba8fb9f7d7
- 
                                  1799
                                  363
                                  25
                                  20
                                
- 
                                  1813
                                  373
                                
- 1
- Print, Reflect and Error streams
- 20755b5a-7694-4c4e-82c2-fb013dc3fe1b
- out
- out
- false
- 0
- 
                                  1854
                                  203
                                  25
                                  22
                                
- 
                                  1866.5
                                  214.25
                                
- Output parameter Pts
- b6862774-22a9-4557-8df9-4e105338905c
- Pts
- Pts
- false
- 0
- 
                                  1854
                                  225
                                  25
                                  23
                                
- 
                                  1866.5
                                  236.75
                                
- Output parameter Crv
- 8f545f02-550b-41fb-8dd0-70baaad81a72
- Crv
- Crv
- false
- 0
- 
                                  1854
                                  248
                                  25
                                  22
                                
- 
                                  1866.5
                                  259.25
                                
- Output parameter L
- d7f4a38f-b681-4226-a169-d484336986a2
- L
- L
- false
- 0
- 
                                  1854
                                  270
                                  25
                                  23
                                
- 
                                  1866.5
                                  281.75
                                
- Output parameter W
- ce2227d2-88d5-44a1-b925-e842136dca13
- W
- W
- false
- 0
- 
                                  1854
                                  293
                                  25
                                  22
                                
- 
                                  1866.5
                                  304.25
                                
- Output parameter H
- 1c6a682f-bab0-45c4-b876-7f71802d69ab
- H
- H
- false
- 0
- 
                                  1854
                                  315
                                  25
                                  23
                                
- 
                                  1866.5
                                  326.75
                                
- Output parameter A
- 24ef080a-aae1-4bd9-a2eb-97cd1569a733
- A
- A
- false
- 0
- 
                                  1854
                                  338
                                  25
                                  22
                                
- 
                                  1866.5
                                  349.25
                                
- Output parameter F
- 057d392c-b422-4b34-a8df-30546d6c59e2
- F
- F
- false
- 0
- 
                                  1854
                                  360
                                  25
                                  23
                                
- 
                                  1866.5
                                  371.75
                                
- 57da07bd-ecab-415d-9d86-af36d7073abc
- Number Slider
- Numeric slider for single values
- 2dac057e-8756-4d2f-b7af-61904cb5801a
- Number Slider
- width
- false
- 0
- 
                          1346
                          281
                          382
                          20
                        
- 
                          1346.563
                          281.9091
                        
- 2
- 1
- 0
- 400
- -130
- 0
- -43.19
- 57da07bd-ecab-415d-9d86-af36d7073abc
- Number Slider
- Numeric slider for single values
- ce3bf1e3-3694-43ca-b804-94bf1ac205b6
- Number Slider
- length
- false
- 0
- 
                          1344
                          255
                          382
                          20
                        
- 
                          1344.994
                          255.0591
                        
- 2
- 1
- 0
- 400
- 0
- 0
- 225
- fbac3e32-f100-4292-8692-77240a42fd1a
- Point
- Contains a collection of three-dimensional points
- true
- 8083dba1-6a1d-4290-9c38-1186214db9bc
- Point
- Pt
- false
- b6862774-22a9-4557-8df9-4e105338905c
- 1
- 
                          1969
                          163
                          50
                          24
                        
- 
                          1994.448
                          175.7781
                        
- 59e0b89a-e487-49f8-bab8-b5bab16be14c
- Panel
- A panel for custom notes and text values
- 3e685539-f44c-4607-be6b-cd3c05e3c5eb
- Panel
- false
- 0
- 4cd71eb6-cfaa-4a47-a72d-f24e55334beb
- 1
- Double click to edit panel content…
- 
                          2027
                          378
                          105
                          55
                        
- 0
- 0
- 0
- 
                          2027.304
                          378.139
                        
- 
                          255;255;250;90
                        
- true
- true
- true
- false
- false
- true
- 0d77c51e-584f-44e8-aed2-c2ddf4803888
- Degrees
- Convert an angle specified in radians to degrees
- 25514f49-1dae-40e1-8f32-66e3ea2dc7bd
- Degrees
- Deg
- 
                          1939
                          389
                          64
                          28
                        
- 
                          1969
                          403
                        
- Angle in radians
- 811b950c-3df2-44de-b7c6-6ffa4c6f2250
- Radians
- R
- false
- 24ef080a-aae1-4bd9-a2eb-97cd1569a733
- 1
- 
                              1941
                              391
                              13
                              24
                            
- 
                              1949
                              403
                            
- Angle in degrees
- 4cd71eb6-cfaa-4a47-a72d-f24e55334beb
- Degrees
- D
- false
- 0
- 
                              1984
                              391
                              17
                              24
                            
- 
                              1992.5
                              403
                            
- 3581f42a-9592-4549-bd6b-1c0fc39d067b
- Construct Point
- Construct a point from {xyz} coordinates.
- f3d440d6-99af-4801-8175-5110376379c5
- Construct Point
- Pt
- 
                          1654
                          139
                          67
                          64
                        
- 
                          1685
                          171
                        
- {x} coordinate
- 30c954ff-f9a8-4e9e-8c9e-f59a9c5d291c
- X coordinate
- X
- false
- 7feb34e6-c435-40ef-a40e-e2792a845fb9
- 1
- 
                              1656
                              141
                              14
                              20
                            
- 
                              1664.5
                              151
                            
- 1
- 1
- {0}
- 0
- {y} coordinate
- ae4bac11-a219-4f42-a0e6-d6bf63aeb9fa
- Y coordinate
- Y
- false
- 0
- 
                              1656
                              161
                              14
                              20
                            
- 
                              1664.5
                              171
                            
- 1
- 1
- {0}
- 0
- {z} coordinate
- 24106b26-bc67-44c4-a1e9-15b116c3613c
- Z coordinate
- Z
- false
- 0
- 
                              1656
                              181
                              14
                              20
                            
- 
                              1664.5
                              191
                            
- 1
- 1
- {0}
- 0
- Point coordinate
- 1813e6b2-8594-4cdf-882c-e312c60bd7f7
- Point
- Pt
- false
- 0
- 
                              1700
                              141
                              19
                              60
                            
- 
                              1709.5
                              171
                            
- d5967b9f-e8ee-436b-a8ad-29fdcecf32d5
- Curve
- Contains a collection of generic curves
- 3be0014f-c7bb-45c2-a96c-88d0e7dd1d16
- Curve
- Crv
- false
- 8f545f02-550b-41fb-8dd0-70baaad81a72
- 1
- 
                          1969
                          206
                          50
                          24
                        
- 
                          1994.437
                          218.3081
                        
- 17b7152b-d30d-4d50-b9ef-c9fe25576fc2
- XY Plane
- World XY plane.
- true
- d0010e01-3735-4f83-b1a6-500844575bf9
- XY Plane
- XY
- 
                          1659
                          214
                          64
                          28
                        
- 
                          1690
                          228
                        
- Origin of plane
- 2c415a43-0493-4511-bc80-751474a0da20
- Origin
- O
- false
- 0
- 
                              1661
                              216
                              14
                              24
                            
- 
                              1669.5
                              228
                            
- 1
- 1
- {0}
- 
                                      0
                                      0
                                      0
                                    
- World XY plane
- f9c309f7-e784-42bd-ac1d-c6f978935e00
- Plane
- P
- false
- 0
- 
                              1705
                              216
                              16
                              24
                            
- 
                              1713
                              228
                            
- a4cd2751-414d-42ec-8916-476ebf62d7fe
- Radians
- Convert an angle specified in degrees to radians
- 8fe257f5-d9cb-49d1-b6c9-0275b7bb1e07
- Radians
- Rad
- 
                          1664
                          333
                          64
                          28
                        
- 
                          1695
                          347
                        
- Angle in degrees
- 6b4b4cf1-fd46-40c8-9f67-929d72db351b
- Degrees
- D
- false
- 364d3276-a223-4ce8-826c-4071f2924b37
- 1
- 
                              1666
                              335
                              14
                              24
                            
- 
                              1674.5
                              347
                            
- Angle in radians
- c9958f3c-a438-4f78-a3b0-79c2730cd794
- Radians
- R
- false
- 0
- 
                              1710
                              335
                              16
                              24
                            
- 
                              1718
                              347
                            
- 57da07bd-ecab-415d-9d86-af36d7073abc
- Number Slider
- Numeric slider for single values
- 364d3276-a223-4ce8-826c-4071f2924b37
- Number Slider
- angle °
- false
- 0
- 
                          1351
                          340
                          295
                          20
                        
- 
                          1351.752
                          340.978
                        
- 2
- 1
- 0
- 170
- -170
- 0
- -42.08
- 59e0b89a-e487-49f8-bab8-b5bab16be14c
- Panel
- A panel for custom notes and text values
- 49784903-21d7-4279-9bef-a75b6aa5db52
- Panel
- false
- 0
- d7f4a38f-b681-4226-a169-d484336986a2
- 1
- Double click to edit panel content…
- 
                          1924
                          257
                          97
                          38
                        
- 0
- 0
- 0
- 
                          1924.427
                          257.7051
                        
- 
                          255;255;250;90
                        
- true
- true
- true
- false
- false
- true
- 59e0b89a-e487-49f8-bab8-b5bab16be14c
- Panel
- A panel for custom notes and text values
- 4aa4b973-077b-4bf3-b682-1bab56120052
- Panel
- false
- 0
- ce2227d2-88d5-44a1-b925-e842136dca13
- 1
- Double click to edit panel content…
- 
                          2035
                          282
                          105
                          55
                        
- 0
- 0
- 0
- 
                          2035.346
                          282.573
                        
- 
                          255;255;250;90
                        
- true
- true
- true
- false
- false
- true
- 59e0b89a-e487-49f8-bab8-b5bab16be14c
- Panel
- A panel for custom notes and text values
- 372b06f9-a8b8-4e7d-b9a0-47795f8b6db6
- Panel
- false
- 0
- 1c6a682f-bab0-45c4-b876-7f71802d69ab
- 1
- Double click to edit panel content…
- 
                          1923
                          318
                          97
                          38
                        
- 0
- 0
- 0
- 
                          1923.371
                          318.089
                        
- 
                          255;255;250;90
                        
- true
- true
- true
- false
- false
- true
- 59e0b89a-e487-49f8-bab8-b5bab16be14c
- Panel
- A panel for custom notes and text values
- 7feb34e6-c435-40ef-a40e-e2792a845fb9
- Panel
- false
- 0
- 0
- -75
- 
                          1568
                          140
                          50
                          20
                        
- 0
- 0
- 0
- 
                          1568.331
                          140.4951
                        
- 
                          255;255;250;90
                        
- true
- true
- true
- false
- false
- true
- 7f5c6c55-f846-4a08-9c9a-cfdc285cc6fe
- Scribble
- true
- 
                      2269.006
                      1162.356
                    
- 
                      2646.125
                      1163.049
                    
- 
                      2646.09
                      1181.682
                    
- 
                      2268.972
                      1180.989
                    
- A quick note
- Microsoft Sans Serif
- 61792023-c3a4-44db-a658-c546e321f080
- false
- Scribble
- Scribble
- 25
- And the real raison d'être: tents!
- 
                          2263.972
                          1157.356
                          387.1528
                          29.32556
                        
- 
                          2269.006
                          1162.356
                        
- 575660b1-8c79-4b8d-9222-7ab4a6ddb359
- Rectangle 2Pt
- Create a rectangle from a base plane and two points
- b8a48901-2a87-4e7d-870b-46ddd3c0a406
- Rectangle 2Pt
- Rec 2Pt
- 
                          2171
                          1539
                          64
                          84
                        
- 
                          2202
                          1581
                        
- Rectangle base plane
- e2d6cfd4-201c-479e-a449-d47449b5d99c
- Plane
- P
- false
- 8d8d0823-8c31-466e-89ab-c417764715c3
- 1
- 
                              2173
                              1541
                              14
                              20
                            
- 
                              2181.5
                              1551
                            
- 1
- 1
- {0}
- 
                                      0
                                      0
                                      0
                                      1
                                      0
                                      0
                                      0
                                      1
                                      0
                                    
- First corner point.
- c31a60ef-1b6b-45b3-b296-290087f567bf
- Point A
- A
- false
- 9ac73f55-39ae-429e-8dc8-8e7f958b4042
- 1
- 
                              2173
                              1561
                              14
                              20
                            
- 
                              2181.5
                              1571
                            
- 1
- 1
- {0}
- 
                                      0
                                      0
                                      0
                                    
- Second corner point.
- 84fdc143-bd3e-4515-a76c-b9793c5c039d
- Point B
- B
- false
- a8fa466b-7cde-4211-998f-da025b67f6b6
- 1
- 
                              2173
                              1581
                              14
                              20
                            
- 
                              2181.5
                              1591
                            
- 1
- 1
- {0}
- 
                                      10
                                      5
                                      0
                                    
- Rectangle corner fillet radius
- 789908b6-b304-431d-b593-c2d0b7f80aa3
- Radius
- R
- false
- 0
- 
                              2173
                              1601
                              14
                              20
                            
- 
                              2181.5
                              1611
                            
- 1
- 1
- {0}
- 0
- Rectangle defined by P, A and B
- 5cf2e6df-da94-4f18-9535-133a50f579e9
- Rectangle
- R
- false
- 0
- 
                              2217
                              1541
                              16
                              40
                            
- 
                              2225
                              1561
                            
- Length of rectangle curve
- 7e0b11dd-d81c-4da2-b222-5309b51b0636
- Length
- L
- false
- 0
- 
                              2217
                              1581
                              16
                              40
                            
- 
                              2225
                              1601
                            
- 17b7152b-d30d-4d50-b9ef-c9fe25576fc2
- XY Plane
- World XY plane.
- true
- 03446bc9-f51d-46c6-85eb-615230f3c249
- XY Plane
- XY
- 
                          2099
                          1495
                          64
                          28
                        
- 
                          2130
                          1509
                        
- Origin of plane
- 8b2fbbc3-5be3-46d2-9834-1a1a5caea969
- Origin
- O
- false
- 0
- 
                              2101
                              1497
                              14
                              24
                            
- 
                              2109.5
                              1509
                            
- 1
- 1
- {0}
- 
                                      0
                                      0
                                      0
                                    
- World XY plane
- 8d8d0823-8c31-466e-89ab-c417764715c3
- Plane
- P
- false
- 0
- 
                              2145
                              1497
                              16
                              24
                            
- 
                              2153
                              1509
                            
- 3581f42a-9592-4549-bd6b-1c0fc39d067b
- Construct Point
- Construct a point from {xyz} coordinates.
- 7d498686-2e4d-42a6-adc7-13da767447ec
- Construct Point
- Pt
- 
                          1530
                          1185
                          67
                          64
                        
- 
                          1561
                          1217
                        
- {x} coordinate
- bb3e48a5-a17f-4d87-8d40-67dd01b081eb
- X coordinate
- X
- false
- 0903a6c2-e102-41a9-8326-3f9533f91f9f
- 1
- 
                              1532
                              1187
                              14
                              20
                            
- 
                              1540.5
                              1197
                            
- 1
- 1
- {0}
- 0
- {y} coordinate
- c46a319c-3740-4362-8bff-3454b1d2a6cc
- Y coordinate
- Y
- false
- 17a61eca-a95a-4f8b-aa55-052523e686bc
- 1
- 
                              1532
                              1207
                              14
                              20
                            
- 
                              1540.5
                              1217
                            
- 1
- 1
- {0}
- 0
- {z} coordinate
- 6c63b308-c5d5-44f6-a259-04c99b457c22
- Z coordinate
- Z
- false
- 0
- 
                              1532
                              1227
                              14
                              20
                            
- 
                              1540.5
                              1237
                            
- 1
- 1
- {0}
- 0
- Point coordinate
- f70a66ec-d9db-496d-9885-4b577f135593
- Point
- Pt
- false
- 0
- 
                              1576
                              1187
                              19
                              60
                            
- 
                              1585.5
                              1217
                            
- a0d62394-a118-422d-abb3-6af115c75b25
- Addition
- Mathematical addition
- true
- f35af83d-b4d8-44ef-9f78-7dc1ed1ad4dd
- Addition
- A+B
- 
                          1688
                          1286
                          64
                          44
                        
- 
                          1719
                          1308
                        
- 2
- 8ec86459-bf01-4409-baee-174d0d2b13d0
- 8ec86459-bf01-4409-baee-174d0d2b13d0
- 1
- 8ec86459-bf01-4409-baee-174d0d2b13d0
- First item for addition
- f3b877be-ea2c-4706-b8e6-cf34d2796bca
- A
- A
- true
- f70a66ec-d9db-496d-9885-4b577f135593
- 1
- 
                                  1690
                                  1288
                                  14
                                  20
                                
- 
                                  1698.5
                                  1298
                                
- Second item for addition
- 16e574ce-9435-47c5-850d-a8fc5152e81d
- B
- B
- true
- 60a1321b-0d85-4215-ac31-f94c7015ccf2
- 1
- 
                                  1690
                                  1308
                                  14
                                  20
                                
- 
                                  1698.5
                                  1318
                                
- Result of addition
- 9ac73f55-39ae-429e-8dc8-8e7f958b4042
- Result
- R
- false
- 0
- 
                                  1734
                                  1288
                                  16
                                  40
                                
- 
                                  1742
                                  1308
                                
- 56b92eab-d121-43f7-94d3-6cd8f0ddead8
- Vector XYZ
- Create a vector from {xyz} components.
- true
- 25bf0db5-4adb-4408-bfee-7d3611f1d1b6
- Vector XYZ
- Vec
- 
                          1576
                          1323
                          64
                          64
                        
- 
                          1607
                          1355
                        
- Vector {x} component
- ec060dc1-0d2b-4706-ac14-728c097f877f
- X component
- X
- false
- 9b5d1997-6eb6-419e-84a2-da5dc70f5477
- 1
- 
                              1578
                              1325
                              14
                              20
                            
- 
                              1586.5
                              1335
                            
- 1
- 1
- {0}
- 0
- Vector {y} component
- 1554f826-50eb-4842-ad0c-e1591646e701
- Y component
- Y
- false
- b582b4c2-046d-4816-9bf2-b7e40b12e3a1
- 1
- 
                              1578
                              1345
                              14
                              20
                            
- 
                              1586.5
                              1355
                            
- 1
- 1
- {0}
- 0
- Vector {z} component
- c5b4970d-6668-445e-b8a3-7d736d0f83dc
- Z component
- Z
- false
- 0
- 
                              1578
                              1365
                              14
                              20
                            
- 
                              1586.5
                              1375
                            
- 1
- 1
- {0}
- 0
- Vector construct
- 60a1321b-0d85-4215-ac31-f94c7015ccf2
- Vector
- V
- false
- 0
- 
                              1622
                              1325
                              16
                              30
                            
- 
                              1630
                              1340
                            
- Vector length
- 614a3c6d-0b33-40ad-81d3-d0dfd2cda65f
- Length
- L
- false
- 0
- 
                              1622
                              1355
                              16
                              30
                            
- 
                              1630
                              1370
                            
- 59e0b89a-e487-49f8-bab8-b5bab16be14c
- Panel
- A panel for custom notes and text values
- 9b5d1997-6eb6-419e-84a2-da5dc70f5477
- Panel
- false
- 0
- 0
- 3
- 
                          1491
                          1321
                          50
                          20
                        
- 0
- 0
- 0
- 
                          1491.106
                          1321.658
                        
- 
                          255;255;250;90
                        
- true
- true
- true
- false
- false
- true
- 59e0b89a-e487-49f8-bab8-b5bab16be14c
- Panel
- A panel for custom notes and text values
- b582b4c2-046d-4816-9bf2-b7e40b12e3a1
- Panel
- false
- 0
- 0
- 2
- 
                          1489
                          1351
                          50
                          20
                        
- 0
- 0
- 0
- 
                          1489.186
                          1351.098
                        
- 
                          255;255;250;90
                        
- true
- true
- true
- false
- false
- true
- 9abae6b7-fa1d-448c-9209-4a8155345841
- Deconstruct
- Deconstruct a point into its component parts.
- true
- 04d13d9d-5383-4696-b406-0fc16bb9a913
- Deconstruct
- pDecon
- 
                          1704
                          1432
                          64
                          64
                        
- 
                          1734
                          1464
                        
- Input point
- ac0ad7b1-bf77-4354-ae03-3ed56f7694ac
- Point
- P
- false
- 9ac73f55-39ae-429e-8dc8-8e7f958b4042
- 1
- 
                              1706
                              1434
                              13
                              60
                            
- 
                              1714
                              1464
                            
- Point {x} component
- 986c6ad6-35ae-433f-bd24-072861a5425d
- X component
- X
- false
- 0
- 
                              1749
                              1434
                              17
                              20
                            
- 
                              1757.5
                              1444
                            
- Point {y} component
- 2c914091-22c1-40d8-abc1-4ccddd24e6ea
- Y component
- Y
- false
- 0
- 
                              1749
                              1454
                              17
                              20
                            
- 
                              1757.5
                              1464
                            
- Point {z} component
- eb73bdaa-9667-4377-9a20-f2e4e4e9cdbf
- Z component
- Z
- false
- 0
- 
                              1749
                              1474
                              17
                              20
                            
- 
                              1757.5
                              1484
                            
- 57da07bd-ecab-415d-9d86-af36d7073abc
- Number Slider
- Numeric slider for single values
- 91f17ed9-335a-446e-9d6c-b9c687cba0f0
- Number Slider
- Length
- false
- 0
- 
                          1456
                          1597
                          263
                          20
                        
- 
                          1456.337
                          1597.275
                        
- 1
- 1
- 0
- 100
- 0
- 0
- 88
- 57da07bd-ecab-415d-9d86-af36d7073abc
- Number Slider
- Numeric slider for single values
- 0fd09915-ec8a-4a40-989a-123b9e68d06c
- Number Slider
- Width
- false
- 0
- 
                          1457
                          1655
                          264
                          20
                        
- 
                          1457.087
                          1655.275
                        
- 1
- 1
- 0
- 100
- 0
- 0
- 54
- a0d62394-a118-422d-abb3-6af115c75b25
- Addition
- Mathematical addition
- true
- 425cffae-604f-493a-a5c9-d68e3739d648
- Addition
- A+B
- 
                          1786
                          1573
                          64
                          44
                        
- 
                          1817
                          1595
                        
- 2
- 8ec86459-bf01-4409-baee-174d0d2b13d0
- 8ec86459-bf01-4409-baee-174d0d2b13d0
- 1
- 8ec86459-bf01-4409-baee-174d0d2b13d0
- First item for addition
- bd91b324-b139-4235-80e4-f5e0f3620809
- A
- A
- true
- 986c6ad6-35ae-433f-bd24-072861a5425d
- 1
- 
                                  1788
                                  1575
                                  14
                                  20
                                
- 
                                  1796.5
                                  1585
                                
- Second item for addition
- a87172e3-431e-4ddf-a937-60b5bc804451
- B
- B
- true
- 91f17ed9-335a-446e-9d6c-b9c687cba0f0
- 1
- 
                                  1788
                                  1595
                                  14
                                  20
                                
- 
                                  1796.5
                                  1605
                                
- Result of addition
- ef5b5c46-d28c-4d3d-8719-82ebb12862d2
- Result
- R
- false
- 0
- 
                                  1832
                                  1575
                                  16
                                  40
                                
- 
                                  1840
                                  1595
                                
- a0d62394-a118-422d-abb3-6af115c75b25
- Addition
- Mathematical addition
- true
- c608fbec-5b75-4c4d-b4d8-48a376f3cd5c
- Addition
- A+B
- 
                          1790
                          1635
                          64
                          44
                        
- 
                          1821
                          1657
                        
- 2
- 8ec86459-bf01-4409-baee-174d0d2b13d0
- 8ec86459-bf01-4409-baee-174d0d2b13d0
- 1
- 8ec86459-bf01-4409-baee-174d0d2b13d0
- First item for addition
- bd152880-8e47-4e39-af2c-724b79caa7ea
- A
- A
- true
- 2c914091-22c1-40d8-abc1-4ccddd24e6ea
- 1
- 
                                  1792
                                  1637
                                  14
                                  20
                                
- 
                                  1800.5
                                  1647
                                
- Second item for addition
- 2ff8f792-cc71-4183-9cdf-57524cacfb82
- B
- B
- true
- 0fd09915-ec8a-4a40-989a-123b9e68d06c
- 1
- 
                                  1792
                                  1657
                                  14
                                  20
                                
- 
                                  1800.5
                                  1667
                                
- Result of addition
- 49b19326-ddaa-450c-a91b-d85295831ca1
- Result
- R
- false
- 0
- 
                                  1836
                                  1637
                                  16
                                  40
                                
- 
                                  1844
                                  1657
                                
- 3581f42a-9592-4549-bd6b-1c0fc39d067b
- Construct Point
- Construct a point from {xyz} coordinates.
- true
- 0025b0b3-cd63-4b6e-a883-c991f59c2549
- Construct Point
- Pt
- 
                          1994
                          1573
                          67
                          64
                        
- 
                          2025
                          1605
                        
- {x} coordinate
- e0588cd2-61aa-4863-98e0-1e9a7f21a1be
- X coordinate
- X
- false
- ef5b5c46-d28c-4d3d-8719-82ebb12862d2
- 1
- 
                              1996
                              1575
                              14
                              20
                            
- 
                              2004.5
                              1585
                            
- 1
- 1
- {0}
- 0
- {y} coordinate
- 037a8251-883a-40af-a11c-21b9ae0ecb92
- Y coordinate
- Y
- false
- 49b19326-ddaa-450c-a91b-d85295831ca1
- 1
- 
                              1996
                              1595
                              14
                              20
                            
- 
                              2004.5
                              1605
                            
- 1
- 1
- {0}
- 0
- {z} coordinate
- 54de041d-38b7-41dc-8680-c6bfa86d9ba3
- Z coordinate
- Z
- false
- 0
- 
                              1996
                              1615
                              14
                              20
                            
- 
                              2004.5
                              1625
                            
- 1
- 1
- {0}
- 0
- Point coordinate
- a8fa466b-7cde-4211-998f-da025b67f6b6
- Point
- Pt
- false
- 0
- 
                              2040
                              1575
                              19
                              60
                            
- 
                              2049.5
                              1605
                            
- a0d62394-a118-422d-abb3-6af115c75b25
- Addition
- Mathematical addition
- true
- 66ed28c2-e779-444a-9c0b-9bd8f26ea017
- Addition
- A+B
- 
                          2124
                          1296
                          64
                          44
                        
- 
                          2155
                          1318
                        
- 2
- 8ec86459-bf01-4409-baee-174d0d2b13d0
- 8ec86459-bf01-4409-baee-174d0d2b13d0
- 1
- 8ec86459-bf01-4409-baee-174d0d2b13d0
- First item for addition
- e86f9ce0-a5ad-4770-854f-f91bc82511aa
- A
- A
- true
- a8fa466b-7cde-4211-998f-da025b67f6b6
- 1
- 
                                  2126
                                  1298
                                  14
                                  20
                                
- 
                                  2134.5
                                  1308
                                
- Second item for addition
- 372d26ca-bd41-418e-9a3f-36c4cb124978
- B
- B
- true
- 60a1321b-0d85-4215-ac31-f94c7015ccf2
- 1
- 
                                  2126
                                  1318
                                  14
                                  20
                                
- 
                                  2134.5
                                  1328
                                
- Result of addition
- 79d26b1a-d554-4adf-802a-54c1a82df2de
- Result
- R
- false
- 0
- 
                                  2170
                                  1298
                                  16
                                  40
                                
- 
                                  2178
                                  1318
                                
- f12daa2f-4fd5-48c1-8ac3-5dea476912ca
- Mirror
- Mirror an object.
- true
- 5caa758f-68a9-4e10-8541-d9dcff111255
- Mirror
- Mirror
- 
                          2176
                          1350
                          65
                          44
                        
- 
                          2207
                          1372
                        
- Base geometry
- c1d5c25c-8138-49ab-bd00-a02680a1f99d
- Geometry
- G
- true
- 60a1321b-0d85-4215-ac31-f94c7015ccf2
- 1
- 
                              2178
                              1352
                              14
                              20
                            
- 
                              2186.5
                              1362
                            
- Mirror plane
- e3d075b2-072b-47d9-9463-c3aa654ad224
- Plane
- P
- false
- 48d4eb53-6ad2-481f-8610-55d9944a22c3
- 1
- 
                              2178
                              1372
                              14
                              20
                            
- 
                              2186.5
                              1382
                            
- 1
- 1
- {0}
- 
                                      0
                                      0
                                      0
                                      0
                                      1
                                      0
                                      0
                                      0
                                      1
                                    
- Mirrored geometry
- bf8b3e5d-d755-43fb-8734-c94ed4d00bba
- Geometry
- G
- false
- 0
- 
                              2222
                              1352
                              17
                              20
                            
- 
                              2230.5
                              1362
                            
- Transformation data
- 4ee0f674-5c0f-410f-b9f6-08a3604b4334
- Transform
- X
- false
- 0
- 
                              2222
                              1372
                              17
                              20
                            
- 
                              2230.5
                              1382
                            
- fad344bc-09b1-4855-a2e6-437ef5715fe3
- YZ Plane
- World YZ plane.
- true
- 272c02f3-8054-4da2-b750-4109a8b8c37e
- YZ Plane
- YZ
- 
                          2091
                          1367
                          64
                          28
                        
- 
                          2122
                          1381
                        
- Origin of plane
- 37e34f49-3112-4952-89a1-4b43e1db22f2
- Origin
- O
- false
- 0
- 
                              2093
                              1369
                              14
                              24
                            
- 
                              2101.5
                              1381
                            
- 1
- 1
- {0}
- 
                                      0
                                      0
                                      0
                                    
- World YZ plane
- 48d4eb53-6ad2-481f-8610-55d9944a22c3
- Plane
- P
- false
- 0
- 
                              2137
                              1369
                              16
                              24
                            
- 
                              2145
                              1381
                            
- 3581f42a-9592-4549-bd6b-1c0fc39d067b
- Construct Point
- Construct a point from {xyz} coordinates.
- true
- 158a8811-4a85-4636-9d80-bb6a389c6dc5
- Construct Point
- Pt
- 
                          1987
                          1388
                          67
                          64
                        
- 
                          2018
                          1420
                        
- {x} coordinate
- 9c32aac2-60cd-43ce-8916-e951db46c16d
- X coordinate
- X
- false
- 986c6ad6-35ae-433f-bd24-072861a5425d
- 1
- 
                              1989
                              1390
                              14
                              20
                            
- 
                              1997.5
                              1400
                            
- 1
- 1
- {0}
- 0
- {y} coordinate
- a95132f4-4546-4352-9af9-19e27eedb3c9
- Y coordinate
- Y
- false
- 49b19326-ddaa-450c-a91b-d85295831ca1
- 1
- 
                              1989
                              1410
                              14
                              20
                            
- 
                              1997.5
                              1420
                            
- 1
- 1
- {0}
- 0
- {z} coordinate
- 8802bfb6-39ba-40ec-84a0-199a2ccc0b6a
- Z coordinate
- Z
- false
- 0
- 
                              1989
                              1430
                              14
                              20
                            
- 
                              1997.5
                              1440
                            
- 1
- 1
- {0}
- 0
- Point coordinate
- 21b1fb4d-d8f9-4dca-a50f-bda44d8d40b3
- Point
- Pt
- false
- 0
- 
                              2033
                              1390
                              19
                              60
                            
- 
                              2042.5
                              1420
                            
- a0d62394-a118-422d-abb3-6af115c75b25
- Addition
- Mathematical addition
- true
- e0d2b78b-5b2e-48e8-af51-67f77e6fe2e3
- Addition
- A+B
- 
                          2364
                          1520
                          64
                          44
                        
- 
                          2395
                          1542
                        
- 2
- 8ec86459-bf01-4409-baee-174d0d2b13d0
- 8ec86459-bf01-4409-baee-174d0d2b13d0
- 1
- 8ec86459-bf01-4409-baee-174d0d2b13d0
- First item for addition
- 06d9a75f-442d-48a1-ace0-8e88067ed67f
- A
- A
- true
- 21b1fb4d-d8f9-4dca-a50f-bda44d8d40b3
- 1
- 
                                  2366
                                  1522
                                  14
                                  20
                                
- 
                                  2374.5
                                  1532
                                
- Second item for addition
- 6e986d97-59c1-46d7-8208-3fa2d487fe5c
- B
- B
- true
- bf8b3e5d-d755-43fb-8734-c94ed4d00bba
- 1
- 
                                  2366
                                  1542
                                  14
                                  20
                                
- 
                                  2374.5
                                  1552
                                
- Result of addition
- 5b37f206-7db4-44b0-ba0f-6175cec13953
- Result
- R
- false
- 0
- 
                                  2410
                                  1522
                                  16
                                  40
                                
- 
                                  2418
                                  1542
                                
- 3581f42a-9592-4549-bd6b-1c0fc39d067b
- Construct Point
- Construct a point from {xyz} coordinates.
- true
- 8ecbb3d6-8916-43ff-9ea1-e19a4fb39844
- Construct Point
- Pt
- 
                          1996
                          1662
                          67
                          64
                        
- 
                          2027
                          1694
                        
- {x} coordinate
- 8e8e1801-b640-4212-9871-fb70a85ac93c
- X coordinate
- X
- false
- ef5b5c46-d28c-4d3d-8719-82ebb12862d2
- 1
- 
                              1998
                              1664
                              14
                              20
                            
- 
                              2006.5
                              1674
                            
- 1
- 1
- {0}
- 0
- {y} coordinate
- 26f967a7-45e3-4567-8d5b-e583254c129a
- Y coordinate
- Y
- false
- 2c914091-22c1-40d8-abc1-4ccddd24e6ea
- 1
- 
                              1998
                              1684
                              14
                              20
                            
- 
                              2006.5
                              1694
                            
- 1
- 1
- {0}
- 0
- {z} coordinate
- dfcf11d4-ae95-4bcd-afb7-606d1755dc76
- Z coordinate
- Z
- false
- 0
- 
                              1998
                              1704
                              14
                              20
                            
- 
                              2006.5
                              1714
                            
- 1
- 1
- {0}
- 0
- Point coordinate
- e825beda-2c01-4b73-b180-297fcfe8bbc3
- Point
- Pt
- false
- 0
- 
                              2042
                              1664
                              19
                              60
                            
- 
                              2051.5
                              1694
                            
- 2c56ab33-c7cc-4129-886c-d5856b714010
- Subtraction
- Mathematical subtraction
- true
- 716d8d38-b0b8-409b-9809-4626eaa49feb
- Subtraction
- A-B
- 
                          2368
                          1584
                          64
                          44
                        
- 
                          2399
                          1606
                        
- Item to subtract from (minuend)
- 1104ec21-7fa5-4dae-af48-1016aa881210
- A
- A
- false
- e825beda-2c01-4b73-b180-297fcfe8bbc3
- 1
- 
                              2370
                              1586
                              14
                              20
                            
- 
                              2378.5
                              1596
                            
- Item to subtract (subtrahend)
- a3acb875-c63e-4a60-8e24-40c0d03aba55
- B
- B
- false
- bf8b3e5d-d755-43fb-8734-c94ed4d00bba
- 1
- 
                              2370
                              1606
                              14
                              20
                            
- 
                              2378.5
                              1616
                            
- The result of the Subtraction
- 40a43f7c-5b18-42a9-934b-a3fca8b86584
- Result
- R
- false
- 0
- 
                              2414
                              1586
                              16
                              40
                            
- 
                              2422
                              1606
                            
- fbac3e32-f100-4292-8692-77240a42fd1a
- Point
- Contains a collection of three-dimensional points
- true
- 5c0c8191-e5d5-44d8-9b74-ad7b50095c12
- Point
- Pt
- false
- 40a43f7c-5b18-42a9-934b-a3fca8b86584
- 1
- 
                          2466
                          1587
                          50
                          24
                        
- 
                          2491.524
                          1599.556
                        
- fbac3e32-f100-4292-8692-77240a42fd1a
- Point
- Contains a collection of three-dimensional points
- true
- 83dc0e24-1c12-445e-8647-dffc452baa6a
- Point
- Pt
- false
- 5b37f206-7db4-44b0-ba0f-6175cec13953
- 1
- 
                          2464
                          1538
                          50
                          24
                        
- 
                          2489.024
                          1550.806
                        
- fbac3e32-f100-4292-8692-77240a42fd1a
- Point
- Contains a collection of three-dimensional points
- true
- c54e879a-bb6c-47c6-b366-aaa5a16a426a
- Point
- Pt
- false
- f70a66ec-d9db-496d-9885-4b577f135593
- 1
- 
                          2387
                          1270
                          50
                          24
                        
- 
                          2412.399
                          1282.068
                        
- fbac3e32-f100-4292-8692-77240a42fd1a
- Point
- Contains a collection of three-dimensional points
- true
- 72b7092f-b51c-4a8b-b457-5cc6f58de91d
- Point
- Pt
- false
- 79d26b1a-d554-4adf-802a-54c1a82df2de
- 1
- 
                          2387
                          1315
                          50
                          24
                        
- 
                          2412.599
                          1327.418
                        
- 59e0b89a-e487-49f8-bab8-b5bab16be14c
- Panel
- A panel for custom notes and text values
- 8526fdb2-be35-4339-84b0-0de9c353ed2c
- Panel
- false
- 0
- 0
- 3
- 
                          2586
                          1726
                          50
                          20
                        
- 0
- 0
- 0
- 
                          2586.39
                          1726.995
                        
- 
                          255;255;250;90
                        
- true
- true
- true
- false
- false
- true
- a0d62394-a118-422d-abb3-6af115c75b25
- Addition
- Mathematical addition
- e9472173-0e76-45e7-b4b3-2d927d4baecc
- Addition
- A+B
- 
                          2663
                          1691
                          64
                          44
                        
- 
                          2694
                          1713
                        
- 2
- 8ec86459-bf01-4409-baee-174d0d2b13d0
- 8ec86459-bf01-4409-baee-174d0d2b13d0
- 1
- 8ec86459-bf01-4409-baee-174d0d2b13d0
- First item for addition
- da0b56ad-280a-4f2a-8298-030632f1527e
- A
- A
- true
- 14cc88f5-707d-4e86-a518-ccdcce6ded66
- 1
- 
                                  2665
                                  1693
                                  14
                                  20
                                
- 
                                  2673.5
                                  1703
                                
- Second item for addition
- 7467100d-05d3-4ae7-a577-8da37d4b9e55
- B
- B
- true
- 8526fdb2-be35-4339-84b0-0de9c353ed2c
- 1
- 
                                  2665
                                  1713
                                  14
                                  20
                                
- 
                                  2673.5
                                  1723
                                
- Result of addition
- cd2f5af0-b741-48d5-8bbd-e9695d5278d8
- Result
- R
- false
- 0
- 
                                  2709
                                  1693
                                  16
                                  40
                                
- 
                                  2717
                                  1713
                                
- 57da07bd-ecab-415d-9d86-af36d7073abc
- Number Slider
- Numeric slider for single values
- 14cc88f5-707d-4e86-a518-ccdcce6ded66
- Number Slider
- Peak Height
- false
- 0
- 
                          2372
                          1693
                          263
                          20
                        
- 
                          2372.275
                          1693.369
                        
- 1
- 1
- 0
- 72
- 0
- 0
- 44
- 9103c240-a6a9-4223-9b42-dbd19bf38e2b
- Unit Z
- Unit vector parallel to the world {z} axis.
- c51aaec6-9bc7-40d7-ab2d-705fd2e20e1e
- Unit Z
- Z
- 
                          2553
                          1260
                          62
                          28
                        
- 
                          2582
                          1274
                        
- Unit multiplication
- 2414a112-d958-411b-b27f-8cdf9d0d2480
- Factor
- F
- false
- 0
- 
                              2555
                              1262
                              12
                              24
                            
- 
                              2562.5
                              1274
                            
- 1
- 1
- {0}
- 1
- World {z} vector
- fdc6f14b-d2af-4143-9fa5-98d72e1496f4
- Unit vector
- V
- false
- 0
- 
                              2597
                              1262
                              16
                              24
                            
- 
                              2605
                              1274
                            
- 934ede4a-924a-4973-bb05-0dc4b36fae75
- Vector 2Pt
- Create a vector between two points.
- 361f13b0-f722-496a-b487-cfffdce2f9cb
- Vector 2Pt
- Vec2Pt
- 
                          2548
                          1387
                          64
                          64
                        
- 
                          2579
                          1419
                        
- Base point
- 5e0ee3e7-7ca6-486b-a276-9290daec2c1d
- Point A
- A
- false
- c54e879a-bb6c-47c6-b366-aaa5a16a426a
- 83dc0e24-1c12-445e-8647-dffc452baa6a
- 2
- 
                              2550
                              1389
                              14
                              20
                            
- 
                              2558.5
                              1399
                            
- Tip point
- 69e066b8-5497-4517-9782-d03091f32b49
- Point B
- B
- false
- 72b7092f-b51c-4a8b-b457-5cc6f58de91d
- 5c0c8191-e5d5-44d8-9b74-ad7b50095c12
- 2
- 
                              2550
                              1409
                              14
                              20
                            
- 
                              2558.5
                              1419
                            
- Unitize output
- e01e96a4-176c-42b4-baed-01d2da98668f
- Unitize
- U
- false
- 0
- 
                              2550
                              1429
                              14
                              20
                            
- 
                              2558.5
                              1439
                            
- 1
- 1
- {0}
- false
- Vector
- a09f5810-c5e6-41cf-a732-76ade1d918e1
- Vector
- V
- false
- 0
- 
                              2594
                              1389
                              16
                              30
                            
- 
                              2602
                              1404
                            
- Vector length
- 15154730-ac41-4df7-abd3-5125f66ed008
- Length
- L
- false
- 0
- 
                              2594
                              1419
                              16
                              30
                            
- 
                              2602
                              1434
                            
- bc3e379e-7206-4e7b-b63a-ff61f4b38a3e
- Construct Plane
- Construct a plane from an origin point and {x}, {y} axes.
- true
- 1b6a1009-88b9-418a-8918-f95aabbb1c52
- Construct Plane
- Pl
- 
                          2674
                          1295
                          66
                          64
                        
- 
                          2705
                          1327
                        
- Origin of plane
- 7a695424-f044-41a8-9bf1-a2cbf28cc226
- Origin
- O
- false
- c54e879a-bb6c-47c6-b366-aaa5a16a426a
- 83dc0e24-1c12-445e-8647-dffc452baa6a
- 2
- 
                              2676
                              1297
                              14
                              20
                            
- 
                              2684.5
                              1307
                            
- 1
- 1
- {0}
- 
                                      0
                                      0
                                      0
                                    
- X-Axis direction of plane
- c61582e5-1354-459b-babb-382f6952792a
- X-Axis
- X
- false
- a09f5810-c5e6-41cf-a732-76ade1d918e1
- 1
- 
                              2676
                              1317
                              14
                              20
                            
- 
                              2684.5
                              1327
                            
- 1
- 1
- {0}
- 
                                      1
                                      0
                                      0
                                    
- Y-Axis direction of plane
- ec988c3e-fd2b-4d2b-aa6a-5e3a9c15a503
- Y-Axis
- Y
- false
- fdc6f14b-d2af-4143-9fa5-98d72e1496f4
- 1
- 
                              2676
                              1337
                              14
                              20
                            
- 
                              2684.5
                              1347
                            
- 1
- 1
- {0}
- 
                                      0
                                      1
                                      0
                                    
- Constructed plane
- f5ef3118-8c76-4765-bdd9-16087c3ebb2d
- Plane
- Pl
- false
- 0
- 
                              2720
                              1297
                              18
                              60
                            
- 
                              2729
                              1327
                            
- 079bd9bd-54a0-41d4-98af-db999015f63d
- VB Script
-   Private Function IsSet(ByVal param As String) As Boolean  ' Check if an input parameter has data
    Dim i As Integer = Component.Params.IndexOfInputParam(param)
    If i > -1 Then
      Return Component.Params.Input.ElementAt(i).DataType > 1  ' input parameter DataType of 1 means it's not receiving input (internal or external)
    Else
      Msg("error", "Input parameter '" & param & "' not found")
      Return False
    End If
  End Function
  Private Sub Msg(ByVal type As String, ByVal msg As String)  ' Output an error, warning, or informational message
    Select Case type
      Case "error"
        Component.AddRuntimeMessage(GH_RuntimeMessageLevel.Error, msg)
        Print("Error: " & msg)
      Case "warning"
        Component.AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, msg)
        Print("Warning: " & msg)
      Case "info"
        Component.AddRuntimeMessage(GH_RuntimeMessageLevel.Remark, msg)
        Print(msg)
    End Select
  End Sub
  ' Solve for the m parameter from length and width (reference {1} equation (34), except b = width and K(k) and E(k) should be K(m) and E(m))
  Private Function SolveMFromLenWid(ByVal L As Double, ByVal w As Double) As Double
    If w = 0 Then
      Return Defined.M_ZERO_W  ' for the boundry condition width = 0, bypass the function and return the known m value
    End If
    Dim n As Integer = 1 ' Iteration counter (quit if >MAXIT)
    Dim lower As Double = 0 ' m must be within this range
    Dim upper As Double = 1
    Dim m As Double
    Dim cwl As Double
    Do While (upper - lower) > Defined.MAXERR AndAlso (n) < Defined.MAXIT ' Repeat until range narrow enough or MAXIT
      m = (upper + lower) / 2
      cwl = 2 * EllipticE(m) / EllipticK(m) - 1  ' calculate w/L with the test value of m
      If cwl < w / L Then  ' compares the calculated w/L with the actual w/L then narrows the range of possible m
        upper = m
      Else
        lower = m
      End If
      n += 1
    Loop
    Return m
  End Function
  ' Solve for the m parameter from length and height (reference {1} equation (33), except K(k) should be K(m) and k = sqrt(m))
  ' Note that it's actually possible to find 2 valid values for m (hence 2 width values) at certain height values
  Private Function SolveMFromLenHt(ByVal L As Double, ByVal h As Double) As List(Of Double)
    Dim n As Integer = 1 ' Iteration counter (quit if >MAXIT)
    Dim lower As Double = 0 ' m must be within this range
    Dim upper As Double = 1
    Dim twoWidths As Boolean = h / L >= Defined.DOUBLE_W_HL_RATIO And h / L < Defined.MAX_HL_RATIO  ' check to see if h/L is within the range where 2 solutions for the width are possible
    Dim m As Double
    Dim mult_m As New List(Of Double)
    Dim chl As Double
    If twoWidths Then
      ' find the first of two possible solutions for m with the following limits:
      lower = Defined.M_DOUBLE_W  ' see constants at bottom of script
      upper = Defined.M_MAXHEIGHT  ' see constants at bottom of script
      Do While (upper - lower) > Defined.MAXERR AndAlso (n) < Defined.MAXIT ' Repeat until range narrow enough or MAXIT
        m = (upper + lower) / 2
        chl = Math.Sqrt(m) / EllipticK(m)  ' calculate h/L with the test value of m
        If chl > h / L Then  ' compares the calculated h/L with the actual h/L then narrows the range of possible m
          upper = m
        Else
          lower = m
        End If
        n += 1
      Loop
      mult_m.Add(m)
      ' then find the second of two possible solutions for m with the following limits:
      lower = Defined.M_MAXHEIGHT  ' see constants at bottom of script
      upper = 1
      Do While (upper - lower) > Defined.MAXERR AndAlso (n) < Defined.MAXIT ' Repeat until range narrow enough or MAXIT
        m = (upper + lower) / 2
        chl = Math.Sqrt(m) / EllipticK(m)  ' calculate h/L with the test value of m
        If chl < h / L Then  ' compares the calculated h/L with the actual h/L then narrows the range of possible m
          upper = m
        Else
          lower = m
        End If
        n += 1
      Loop
      If m <= Defined.M_MAX Then  ' return this m parameter only if it falls within the maximum useful value (above which the curve breaks down)
        mult_m.Add(m)
      End If
    Else
      ' find the one possible solution for the m parameter
      upper = Defined.M_DOUBLE_W  ' limit the upper end of the search to the maximum value of m for which only one solution exists
      Do While (upper - lower) > Defined.MAXERR AndAlso (n) < Defined.MAXIT ' Repeat until range narrow enough or MAXIT
        m = (upper + lower) / 2
        chl = Math.Sqrt(m) / EllipticK(m)  ' calculate h/L with the test value of m
        If chl > h / L Then  ' compares the calculated h/L with the actual h/L then narrows the range of possible m
          upper = m
        Else
          lower = m
        End If
        n += 1
      Loop
      mult_m.Add(m)
    End If
    Return mult_m
  End Function
  ' Solve for the m parameter from width and height (derived from reference {1} equations (33) and (34) with same notes as above)
  Private Function SolveMFromWidHt(ByVal w As Double, ByVal h As Double) As Double
    Dim n As Integer = 1 ' Iteration counter (quit if >MAXIT)
    Dim lower As Double = 0 ' m must be within this range
    Dim upper As Double = 1
    Dim m As Double
    Dim cwh As Double
    Do While (upper - lower) > Defined.MAXERR AndAlso (n) < Defined.MAXIT ' Repeat until range narrow enough or MAXIT
      m = (upper + lower) / 2
      cwh = (2 * EllipticE(m) - EllipticK(m)) / Math.Sqrt(m)  ' calculate w/h with the test value of m
      If cwh < w / h Then  ' compares the calculated w/h with the actual w/h then narrows the range of possible m
        upper = m
      Else
        lower = m
      End If
      n += 1
    Loop
    Return m
  End Function
  ' Calculate length based on height and an m parameter, derived from reference {1} equation (33), except K(k) should be K(m) and k = sqrt(m)
  Private Function Cal_L(ByVal h As Double, ByVal m As Double) As Double
    Return h * EllipticK(m) / Math.Sqrt(m)
  End Function
  ' Calculate width based on length and an m parameter, derived from reference {1} equation (34), except b = width and K(k) and E(k) should be K(m) and E(m)
  Private Function Cal_W(ByVal L As Double, ByVal m As Double) As Double
    Return L * (2 * EllipticE(m) / EllipticK(m) - 1)
  End Function
  ' Calculate height based on length and an m parameter, from reference {1} equation (33), except K(k) should be K(m) and k = sqrt(m)
  Private Function Cal_H(ByVal L As Double, ByVal m As Double) As Double
    Return L * Math.Sqrt(m) / EllipticK(m)
  End Function
  ' Calculate the unique m parameter based on a start tangent angle, from reference {2}, just above equation (9a), that states k = Sin(angle / 2 + Pi / 4),
  ' but as m = k^2 and due to this script's need for an angle rotated 90° versus the one in reference {1}, the following formula is the result
  ' New note: verified by reference {4}, pg. 78 at the bottom
  Private Function Cal_M(ByVal a As Double) As Double
    Return (1 - Math.Cos(a)) / 2  ' equal to Sin^2(a/2) too
  End Function
  ' Calculate start tangent angle based on an m parameter, derived from above formula
  Private Function Cal_A(ByVal m As Double) As Double
    Return Math.Acos(1 - 2 * m)
  End Function
  ' This is the heart of this script, taking the found (or specified) length, width, and angle values along with the found m parameter to create
  ' a list of points that approximate the shape or form of the elastica. It works by finding the x and y coordinates (which are reversed versus
  ' the original equations (12a) and (12b) from reference {2} due to the 90° difference in orientation) based on the tangent angle along the curve.
  ' See reference {2} for more details on how they derived it. Note that to simplify things, the algorithm only calculates the points for half of the
  ' curve, then mirrors those points along the y-axis.
  Private Function FindBendForm(ByVal L As Double, ByVal w As Double, ByVal m As Double, ByVal ang As Double, ByVal refPln As Plane) As List(Of Point3d)
    L = L / 2  ' because the below algorithm is based on the formulas in reference {2} for only half of the curve
    w = w / 2  ' same
    If ang = 0 Then  ' if angle (and height) = 0, then simply return the start and end points of the straight line
      Dim out As New List(Of Point3d)
      out.Add(refPln.PointAt(w, 0, 0))
      out.Add(refPln.PointAt(-w, 0, 0))
      Return out
    End If
    Dim x As Double
    Dim y As Double
    Dim halfCurvePts As New List(Of Point3d)
    Dim fullCurvePts As New List(Of Point3d)
    Dim translatedPts As New List(Of Point3d)
    ang -= Math.PI / 2  ' a hack to allow this algorithm to work, since the original curve in paper {2} was rotated 90°
    Dim angB As Double = ang + (-Math.PI / 2 - ang) / Defined.CURVEDIVS  ' angB is the 'lowercase theta' which should be in formula {2}(12b) as the interval
    ' start [a typo...see equation(3)]. It's necessary to start angB at ang + [interval] instead of just ang due to integration failing at angB = ang
    halfCurvePts.Add(New Point3d(w, 0, 0))  ' start with this known initial point, as integration will fail when angB = ang
    ' each point {x, y} is calculated from the tangent angle, angB, that occurs at each point (which is why this iterates from ~ang to -pi/2, the known end condition)
    Do While Math.Round(angB, Defined.ROUNDTO) >= Math.Round(-Math.PI / 2, Defined.ROUNDTO)
      y = (Math.Sqrt(2) * Math.Sqrt(Math.Sin(ang) - Math.Sin(angB)) * (w + L)) / (2 * EllipticE(m))  ' note that x and y are swapped vs. (12a) and (12b)
      x = (L / (Math.Sqrt(2) * EllipticK(m))) * Simpson(angB, -Math.PI / 2, 500, ang)  ' calculate the Simpson approximation of the integral (function f below)
      ' over the interval angB ('lowercase theta') to -pi/2. side note: is 500 too few iterations for the Simson algorithm?
      If Math.Round(x, Defined.ROUNDTO) = 0 Then x = 0
      halfCurvePts.Add(New Point3d(x, y, 0))
      angB += (-Math.PI / 2 - ang) / Defined.CURVEDIVS  ' onto the next tangent angle
    Loop
    ' After finding the x and y values for half of the curve, add the {-x, y} values for the rest of the curve
    For Each point As Point3d In halfCurvePts
      If Math.Round(point.X, Defined.ROUNDTO) = 0 Then
        If Math.Round(point.Y, Defined.ROUNDTO) = 0 Then
          fullCurvePts.Add(New Point3d(0, 0, 0))  ' special case when width = 0: when x = 0, only duplicate the point when y = 0 too
        End If
      Else
        fullCurvePts.Add(New Point3d(-point.X, point.Y, 0))
      End If
    Next
    halfCurvePts.Reverse
    fullCurvePts.AddRange(halfCurvePts)
    For Each p As Point3d In fullCurvePts
      translatedPts.Add(refPln.PointAt(p.X, p.Y, p.Z))  ' translate the points from the reference plane to the world plane
    Next
    Return translatedPts
  End Function
  ' Interpolates the points from FindBendForm to create the Elastica curve. Uses start & end tangents for greater accuracy.
  Private Function MakeCurve(ByVal pts As List(Of Point3d), ByVal ang As Double, ByVal refPln As Plane) As Curve
    If ang <> 0 Then
      Dim ts, te As New Vector3d(refPln.XAxis)
      ts.Rotate(ang, refPln.ZAxis)
      te.Rotate(-ang, refPln.ZAxis)
      Return Curve.CreateInterpolatedCurve(pts, 3, CurveKnotStyle.Chord, ts, te)  ' 3rd degree curve with 'Chord' Knot Style
    Else
      Return Curve.CreateInterpolatedCurve(pts, 3)  ' if angle (and height) = 0, then simply interpolate the straight line (no start/end tangents)
    End If
  End Function
  ' Implements the Simpson approximation for an integral of function f below
  Public Function Simpson(a As Double, b As Double, n As Integer, theta As Double) As Double 'n should be an even number
    Dim j As Integer, s1 As Double, s2 As Double, h As Double
    h = (b - a) / n
    s1 = 0
    s2 = 0
    For j = 1 To n - 1 Step 2
      s1 = s1 + fn(a + j * h, theta)
    Next j
    For j = 2 To n - 2 Step 2
      s2 = s2 + fn(a + j * h, theta)
    Next j
    Simpson = h / 3 * (fn(a, theta) + 4 * s1 + 2 * s2 + fn(b, theta))
  End Function
  ' Specific calculation for the above integration
  Public Function fn(x As Double, theta As Double) As Double
    fn = Math.Sin(x) / (Math.Sqrt(Math.Sin(theta) - Math.Sin(x)))  ' from reference {2} formula (12b)
  End Function
  ' Return the Complete Elliptic integral of the 1st kind
  ' Abramowitz and Stegun p.591, formula 17.3.11
  ' Code from http://www.codeproject.com/Articles/566614/Elliptic-integrals
  Public Function EllipticK(ByVal m As Double) As Double
    Dim sum, term, above, below As Double
    sum = 1
    term = 1
    above = 1
    below = 2
    For i As Integer = 1 To 100
      term *= above / below
      sum += Math.Pow(m, i) * Math.Pow(term, 2)
      above += 2
      below += 2
    Next
    sum *= 0.5 * Math.PI
    Return sum
  End Function
  ' Return the Complete Elliptic integral of the 2nd kind
  ' Abramowitz and Stegun p.591, formula 17.3.12
  ' Code from http://www.codeproject.com/Articles/566614/Elliptic-integrals
  Public Function EllipticE(ByVal m As Double) As Double
    Dim sum, term, above, below As Double
    sum = 1
    term = 1
    above = 1
    below = 2
    For i As Integer = 1 To 100
      term *= above / below
      sum -= Math.Pow(m, i) * Math.Pow(term, 2) / above
      above += 2
      below += 2
    Next
    sum *= 0.5 * Math.PI
    Return sum
  End Function
  Friend Partial NotInheritable Class Defined
    Private Sub New()
    End Sub
    ' Note: most of these values for m and h/L ratio were found with Wolfram Alpha and either specific intercepts (x=0) or local minima/maxima. They should be constant.
    Public Const M_SKETCHY As Double = 0.95  ' value of the m parameter where the curvature near the ends of the curve gets wonky
    Public Const M_MAX As Double = 0.993  ' maximum useful value of the m parameter, above which this algorithm for the form of the curve breaks down
    Public Const M_ZERO_W As Double = 0.826114765984970336  ' value of the m parameter when width = 0
    Public Const M_MAXHEIGHT As Double = 0.701327460663101223  ' value of the m parameter at maximum possible height of the bent rod/wire
    Public Const M_DOUBLE_W As Double = 0.180254422335013983  ' minimum value of the m parameter when two width values are possible for a given height and length
    Public Const DOUBLE_W_HL_RATIO As Double = 0.257342117984635757  ' value of the height/length ratio above which there are two possible width values
    Public Const MAX_HL_RATIO As Double = 0.403140189705650243  ' maximum possible value of the height/length ratio
    Public Const MAXERR As Double = 0.0000000001  ' error tolerance
    Public Const MAXIT As Integer = 100  ' maximum number of iterations
    Public Const ROUNDTO As Integer = 10  ' number of decimal places to round off to
    Public Const CURVEDIVS As Integer = 50  ' number of sample points for building the curve (or half-curve as it were)
  End Class
- A VB.NET scriptable component
- 
                      98
                      86
                    
- true
- efeac80e-aaa9-43ef-acff-f0dc08a37ca1
- VB Script
- VB
- true
- 0
-     ' -----------------------------------------------------------------
    ' Elastic Bending Script by Will McElwain
    ' Created February 2014
    '
    ' DESCRIPTION:
    ' This beast creates the so-called 'elastica curve', the shape a long, thin rod or wire makes when it is bent elastically (i.e. not permanently). In this case, force
    ' is assumed to only be applied horizontally (which would be in line with the rod at rest) and both ends are assumed to be pinned or hinged meaning they are free
    ' to rotate (as opposed to clamped, when the end tangent angle is fixed, usually horizontally). An interesting finding is that it doesn't matter what the material or
    ' cross-sectional area is, as long as they're uniform along the entire length. Everything makes the same shape when bent as long as it doesn't cross the threshold
    ' from elastic to plastic (permanent) deformation (I don't bother to find that limit here, but can be found if the yield stress for a material is known).
    '
    ' Key to the formulas used in this script are elliptic integrals, specifically K(m), the complete elliptic integral of the first kind, and E(m), the complete elliptic
    ' integral of the second kind. There was a lot of confusion over the 'm' and 'k' parameters for these functions, as some people use them interchangeably, but they are
    ' not the same. m = k^2 (thus k = Sqrt(m)). I try to use the 'm' parameter exclusively to avoid this confusion. Note that there is a unique 'm' parameter for every
    ' configuration/shape of the elastica curve.
    '
    ' This script tries to find that unique 'm' parameter based on the inputs. The algorithm starts with a test version of m, evaluates an expression, say 2*E(m)/K(m)-1,
    ' then compares the result to what it should be (in this case, a known width/length ratio). Iterate until the correct m is found. Once we have m, we can then calculate
    ' all of the other unknowns, then find points that lie on that curve, then interpolate those points for the actual curve. You can also use Wolfram|Alpha as I did to
    ' find the m parameter based on the equations in this script (example here: http://tiny.cc/t4tpbx for when say width=45.2 and length=67.1).
    '
    ' Other notes:
    ' * This script works with negative values for width, which will creat a self-intersecting curve (as it should). The curvature of the elastica starts to break down around
    ' m=0.95 (~154°), but this script will continue to work until M_MAX, m=0.993 (~169°). If you wish to ignore self-intersecting curves, set ignoreSelfIntersecting to True
    ' * When the only known values are length and height, it is actually possible for certain ratios of height to length to have two valid m values (thus 2 possible widths
    ' and angles). This script will return them both.
    ' * Only the first two valid parameters (of the required ones) will be used, meaning if all four are connected (length, width or a PtB, height, and angle), this script will
    ' only use length and width (or a PtB).
    ' * Depending on the magnitude of your inputs (say if they're really small, like if length < 10), you might have to increase the constant ROUNDTO at the bottom
    '
    ' REFERENCES:
    ' {1} "The elastic rod" by M.E. Pacheco Q. & E. Pina, http://www.scielo.org.mx/pdf/rmfe/v53n2/v53n2a8.pdf
    ' {2} "An experiment in nonlinear beam theory" by A. Valiente, http://www.deepdyve.com/lp/doc/I3lwnxdfGz , also here: http://tiny.cc/Valiente_AEiNBT
    ' {3} "Snap buckling, writhing and Loop formation In twisted rods" by V.G.A. GOSS, http://myweb.lsbu.ac.uk/~gossga/thesisFinal.pdf
    ' {4} "Theory of Elastic Stability" by Stephen Timoshenko, http://www.scribd.com/doc/50402462/Timoshenko-Theory-of-Elastic-Stability  (start on p. 76)
    '
    ' INPUT:
    ' PtA - First anchor point (required)
    ' PtB - Second anchor point (optional, though 2 out of the 4--length, width, height, angle--need to be specified)
    '       [note that PtB can be the same as PtA (meaning width would be zero)]
    '       [also note that if a different width is additionally specified that's not equal to the distance between PtA and PtB, then the end point will not equal PtB anymore]
    ' Pln - Plane of the bent rod/wire, which bends up in the +y direction. The line between PtA and PtB (if specified) must be parallel to the x-axis of this plane
    '
    ' ** 2 of the following 4 need to be specified **
    ' Len - Length of the rod/wire, which needs to be > 0
    ' Wid - Width between the endpoints of the curve [note: if PtB is specified in addition, and distance between PtA and PtB <> width, the end point will be relocated
    ' Ht - Height of the bent rod/wire (when negative, curve will bend downward, relative to the input plane, instead)
    ' Ang - Inner departure angle or tangent angle (in radians) at the ends of the bent rod/wire. Set up so as width approaches length (thus height approaches zero), angle approaches zero
    '
    ' * Following variables only needed for optional calculating of bending force, not for shape of curve.
    ' E - Young's modulus (modulus of elasticity) in GPa (=N/m^2) (material-specific. for example, 7075 aluminum is roughly 71.7 GPa)
    ' I - Second moment of area (or area moment of inertia) in m^4 (cross-section-specific. for example, a hollow rod
    '     would have I = pi * (outer_diameter^4 - inner_diameter^4) / 32
    ' Note: E*I is also known as flexural rigidity or bending stiffness
    '
    ' OUTPUT:
    ' out - only for debugging messages
    ' Pts - the list of points that approximate the shape of the elastica
    ' Crv - the 3rd-degree curve interpolated from those points (with accurate start & end tangents)
    ' L - the length of the rod/wire
    ' W - the distance (width) between the endpoints of the rod/wire
    ' H - the height of the bent rod/wire
    ' A - the tangent angle at the (start) end of the rod/wire
    ' F - the force needed to hold the rod/wire in a specific shape (based on the material properties & cross-section) **be sure your units for 'I' match your units for the
    ' rest of your inputs (length, width, etc.). Also note that the critical buckling load (force) that makes the rod/wire start to bend can be found at height=0
    '
    ' THANKS TO:
    ' Mårten Nettelbladt (thegeometryofbending.blogspot.com)
    ' Daniel Piker (Kangaroo plugin)
    ' David Rutten (Grasshopper guru)
    ' Euler & Bernoulli (the O.G.'s)
    '
    ' -----------------------------------------------------------------
    Dim ignoreSelfIntersecting As Boolean = False  ' set to True if you don't want to output curves where width < 0, which creates a self-intersecting curve
    Dim inCt As Integer = 0  ' count the number of required parameters that are receiving data
    Dim length As Double
    Dim width As System.Object = Nothing  ' need to set as Nothing so we can check if it has been assigned a value later
    Dim height As Double
    Dim angle As Double
    Dim m As Double
    Dim multiple_m As New List(Of Double)
    Dim AtoB As Line
    Dim flip_H As Boolean = False  ' if height is negative, this flag will be set
    Dim flip_A As Boolean = False  ' if angle is negative, this flag will be set
    If Not IsSet("Pln") Then
      Msg("error", "Base plane is not set")
      Return
    End If
    If Not IsSet("PtA") Then
      Msg("error", "Point A is not set")
      Return
    End If
    If Math.Round(Pln.DistanceTo(PtA), Defined.ROUNDTO) <> 0 Then
      Msg("error", "Point A is not on the base plane")
      Return
    End If
    Dim refPlane As Plane = Pln  ' create a reference plane = input plane and set the origin of it to PtA in case PtA isn't the origin already
    refPlane.Origin = PtA
    If IsSet("PtB") Then
      If Math.Round(Pln.DistanceTo(PtB), Defined.ROUNDTO) <> 0 Then
        Msg("error", "Point B is not on the base plane")
        Return
      End If
      AtoB = New Line(PtA, PtB)
      If AtoB.Length <> 0 And Not AtoB.Direction.IsPerpendicularTo(Pln.YAxis) Then
        Msg("error", "The line between PtA and PtB is not perpendicular to the Y-axis of the specified plane")
        Return
      End If
      inCt += 1
      If IsSet("Wid") Then Msg("info", "Wid will override the distance between PtA and PtB. If you do not want this to happen, disconnect PtB or Wid.")
      width = PtA.DistanceTo(PtB)  ' get the width (distance) between PtA and PtB
      
      Dim refPtB As Point3d
      refPlane.RemapToPlaneSpace(PtB, refPtB)
      If refPtB.X < 0 Then width = -width  ' check if PtB is to the left of PtA...if so, width is negative
    End If
    If IsSet("Len") Then inCt += 1
    If IsSet("Wid") Then inCt += 1
    If IsSet("Ht") Then inCt += 1
    If IsSet("Ang") Then inCt += 1
    If inCt > 2 Then Msg("info", "More parameters set than are required (out of length, width, height, angle). Only using the first two valid ones.")
    ' check for connected/specified inputs. note: only the first two that it comes across will be used
    If IsSet("Len") Then  ' if length is specified then...
      If Len <= 0 Then
        Msg("error", "Length cannot be negative or zero")
        Return
      End If
      If IsSet("Wid") Then  ' find height & angle based on length and specified width
        If Wid > Len Then
          Msg("error", "Width is greater than length")
          Return
        End If
        If Wid = Len Then  ' skip the solver and set the known values
          height = 0
          m = 0
          angle = 0
          width = Wid
        Else
          m = SolveMFromLenWid(Len, Wid)
          height = Cal_H(Len, m)  ' L * Sqrt(m) / K(m)
          angle = Cal_A(m)  ' Acos(1 - 2 * m)
          width = Wid
        End If
      Else If width IsNot Nothing Then  ' find height & angle based on length and calculated width (distance between PtA and PtB)
        If width > Len Then
          Msg("error", "Width is greater than length")
          Return
        End If
        If width = Len Then  ' skip the solver and set the known values
          height = 0
          m = 0
          angle = 0
        Else
          m = SolveMFromLenWid(Len, width)
          height = Cal_H(Len, m)  ' L * Sqrt(m) / K(m)
          angle = Cal_A(m)  ' Acos(1 - 2 * m)
        End If
      Else If IsSet("Ht") Then  ' find width & angle based on length and height  ** possible to return 2 results **
        If Math.Abs(Ht / Len) > Defined.MAX_HL_RATIO Then
          Msg("error", "Height not possible with given length")
          Return
        End If
        If Ht < 0 Then
          Ht = -Ht  ' if height is negative, set it to positive (for the calculations) but flip the reference plane about its x-axis
          refPlane.Transform(Transform.Mirror(New Plane(refPlane.Origin, refPlane.XAxis, refPlane.ZAxis)))
          flip_A = True
          flip_H = True
        End If
        If Ht = 0 Then  ' skip the solver and set the known values
          width = Len
          angle = 0
        Else
          multiple_m = SolveMFromLenHt(Len, Ht)  ' note that it's possible for two values of m to be found if height is close to max height
          If multiple_m.Count = 1 Then  ' if there's only one m value returned, calculate the width & angle here. we'll deal with multiple m values later
            m = multiple_m.Item(0)
            width = Cal_W(Len, m)  ' L * (2 * E(m) / K(m) - 1)
            angle = Cal_A(m)  ' Acos(1 - 2 * m)
          End If
        End If
        height = Ht
      Else If IsSet("Ang") Then  ' find width & height based on length and angle
        If Ang < 0 Then
          Ang = -Ang  ' if angle is negative, set it to positive (for the calculations) but flip the reference plane about its x-axis
          refPlane.Transform(Transform.Mirror(New Plane(refPlane.Origin, refPlane.XAxis, refPlane.ZAxis)))
          flip_A = True
          flip_H = True
        End If
        m = Cal_M(Ang)  ' (1 - Cos(a)) / 2
        If Ang = 0 Then  ' skip the solver and set the known values
          width = Len
          height = 0
        Else
          width = Cal_W(Len, m)  ' L * (2 * E(m) / K(m) - 1)
          height = Cal_H(Len, m)  ' L * Sqrt(m) / K(m)
        End If
        angle = Ang
      Else
        Msg("error", "Need to specify one more parameter in addition to length")
        Return
      End If
      length = Len
    Else If IsSet("Wid") Then  ' if width is specified then...
      If IsSet("Ht") Then  ' find length & angle based on specified width and height
        If Ht < 0 Then
          Ht = -Ht  ' if height is negative, set it to positive (for the calculations) but flip the reference plane about its x-axis
          refPlane.Transform(Transform.Mirror(New Plane(refPlane.Origin, refPlane.XAxis, refPlane.ZAxis)))
          flip_A = True
          flip_H = True
        End If
        If Ht = 0 Then  ' skip the solver and set the known values
          length = Wid
          angle = 0
        Else
          m = SolveMFromWidHt(Wid, Ht)
          length = Cal_L(Ht, m)  ' h * K(m) / Sqrt(m)
          angle = Cal_A(m)  ' Acos(1 - 2 * m)
        End If
        height = Ht
      Else If IsSet("Ang") Then  ' find length & height based on specified width and angle
        If Wid = 0 Then
          Msg("error", "Curve not possible with width = 0 and an angle as inputs")
          Return
        End If
        If Ang < 0 Then
          Ang = -Ang  ' if angle is negative, set it to positive (for the calculations) but flip the reference plane about its x-axis
          refPlane.Transform(Transform.Mirror(New Plane(refPlane.Origin, refPlane.XAxis, refPlane.ZAxis)))
          flip_A = True
          flip_H = True
        End If
        m = Cal_M(Ang)  ' (1 - Cos(a)) / 2
        If Ang = 0 Then  ' skip the solver and set the known values
          length = Wid
          height = 0
        Else
          length = Wid / (2 * EllipticE(m) / EllipticK(m) - 1)
          If length < 0 Then
            Msg("error", "Curve not possible at specified width and angle (calculated length is negative)")
            Return
          End If
          height = Cal_H(length, m)  ' L * Sqrt(m) / K(m)
        End If
        angle = Ang
      Else
        Msg("error", "Need to specify one more parameter in addition to width (Wid)")
        Return
      End If
      width = Wid
    Else If width IsNot Nothing Then  ' if width is determined by PtA and PtB then...
      If IsSet("Ht") Then  ' find length & angle based on calculated width and height
        If Ht < 0 Then
          Ht = -Ht  ' if height is negative, set it to positive (for the calculations) but flip the reference plane about its x-axis
          refPlane.Transform(Transform.Mirror(New Plane(refPlane.Origin, refPlane.XAxis, refPlane.ZAxis)))
          flip_A = True
          flip_H = True
        End If
        If Ht = 0 Then  ' skip the solver and set the known values
          length = width
          angle = 0
        Else
          m = SolveMFromWidHt(width, Ht)
          length = Cal_L(Ht, m)  ' h * K(m) / Sqrt(m)
          angle = Cal_A(m)  ' Acos(1 - 2 * m)
        End If
        height = Ht
      Else If IsSet("Ang") Then  ' find length & height based on calculated width and angle
        If width = 0 Then
          Msg("error", "Curve not possible with width = 0 and an angle as inputs")
          Return
        End If
        If Ang < 0 Then
          Ang = -Ang  ' if angle is negative, set it to positive (for the calculations) but flip the reference plane about its x-axis
          refPlane.Transform(Transform.Mirror(New Plane(refPlane.Origin, refPlane.XAxis, refPlane.ZAxis)))
          flip_A = True
          flip_H = True
        End If
        m = Cal_M(Ang)  ' (1 - Cos(a)) / 2
        If Ang = 0 Then  ' skip the solver and set the known values
          length = width
          height = 0
        Else
          length = width / (2 * EllipticE(m) / EllipticK(m) - 1)
          If length < 0 Then
            Msg("error", "Curve not possible at specified width and angle (calculated length is negative)")
            Return
          End If
          height = Cal_H(length, m)  ' L * Sqrt(m) / K(m)
        End If
        angle = Ang
      Else
        Msg("error", "Need to specify one more parameter in addition to PtA and PtB")
        Return
      End If
    Else If IsSet("Ht") Then  ' if height is specified then...
      If IsSet("Ang") Then  ' find length & width based on height and angle
        If Ht < 0 Then
          Ht = -Ht  ' if height is negative, set it to positive (for the calculations) but flip the reference plane about its x-axis
          refPlane.Transform(Transform.Mirror(New Plane(refPlane.Origin, refPlane.XAxis, refPlane.ZAxis)))
          flip_H = True
          flip_A = True
        End If
        If Ht = 0 Then
          Msg("error", "Height can't = 0 if only height and angle are specified")
          Return
        Else
          If Ang < 0 Then
            Ang = -Ang  ' if angle is negative, set it to positive (for the calculations) but flip the reference plane about its x-axis
            refPlane.Transform(Transform.Mirror(New Plane(refPlane.Origin, refPlane.XAxis, refPlane.ZAxis)))
            flip_A = Not flip_A
            flip_H = Not flip_H
          End If
          m = Cal_M(Ang)  ' (1 - Cos(a)) / 2
          If Ang = 0 Then
            Msg("error", "Angle can't = 0 if only height and angle are specified")
            Return
          Else
            length = Cal_L(Ht, m)  ' h * K(m) / Sqrt(m)
            width = Cal_W(length, m)  ' L * (2 * E(m) / K(m) - 1)
          End If
          angle = Ang
        End If
        height = Ht
      Else
        Msg("error", "Need to specify one more parameter in addition to height")
        Return
      End If
    Else If IsSet("Ang") Then
      Msg("error", "Need to specify one more parameter in addition to angle")
      Return
    Else
      Msg("error", "Need to specify two of the four parameters: length, width (or PtB), height, and angle")
      Return
    End If
    If m > Defined.M_MAX Then
      Msg("error", "Form of curve not solvable with current algorithm and given inputs")
      Return
    End If
    refPlane.Origin = refPlane.PointAt(width / 2, 0, 0)  ' adjust the origin of the reference plane so that the curve is centered about the y-axis (start of the curve is at x = -width/2)
    If multiple_m.Count > 1 Then  ' if there is more than one m value returned, calculate the width, angle, and curve for each
      Dim multi_pts As New DataTree(Of Point3d)
      Dim multi_crv As New List(Of Curve)
      Dim tmp_pts As New List(Of Point3d)
      Dim multi_W, multi_A, multi_F As New List(Of Double)
      Dim j As Integer = 0  ' used for creating a new branch (GH_Path) for storing pts which is itself a list of points
      For Each m_val As Double In multiple_m
        width = Cal_W(length, m_val) 'length * (2 * EllipticE(m_val) / EllipticK(m_val) - 1)
        
        If width < 0 And ignoreSelfIntersecting Then
          Msg("warning", "One curve is self-intersecting. To enable these, set ignoreSelfIntersecting to False")
          Continue For
        End If
        
        If m_val >= Defined.M_SKETCHY Then Msg("info", "Accuracy of the curve whose width = " & Math.Round(width, 4) & " is not guaranteed")
        
        angle = Cal_A(m_val) 'Math.Asin(2 * m_val - 1)
        refPlane.Origin = refPlane.PointAt(width / 2, 0, 0)  ' adjust the origin of the reference plane so that the curve is centered about the y-axis (start of the curve is at x = -width/2)
        
        tmp_pts = FindBendForm(length, width, m_val, angle, refPlane)
        multi_pts.AddRange(tmp_pts, New GH_Path(j))
        multi_crv.Add(MakeCurve(tmp_pts, angle, refPlane))
        
        multi_W.Add(width)
        If flip_A Then angle = -angle
        multi_A.Add(angle)
        
        E = E * 10 ^ 9  ' Young's modulus input E is in GPa, so we convert to Pa here (= N/m^2)
        multi_F.Add(EllipticK(m_val) ^ 2 * E * I / length ^ 2)  ' from reference {4} pg. 79
        
        j += 1
        refPlane.Origin = PtA  ' reset the reference plane origin to PtA for the next m_val
        'Print("length=" & length & ", width=" & width & ", height=" & height & ", angle=" & angle & ", m=" & m_val & ", k=" & Math.Sqrt(m_val) & ", w/L=" & width / length & ", h/L=" & height / length & ", w/h=" & width / height)
      Next
      ' assign the outputs
      Pts = multi_pts
      Crv = multi_crv
      L = length
      W = multi_W
      If flip_H Then height = -height
      H = height
      A = multi_A
      F = multi_F
    Else  ' only deal with the single m value
      If m >= Defined.M_SKETCHY Then Msg("info", "Accuracy of the curve at these parameters is not guaranteed")
      
      If width < 0 And ignoreSelfIntersecting Then
        Msg("error", "Curve is self-intersecting. To enable these, set ignoreSelfIntersecting to False")
        Return
      End If
      
      Pts = FindBendForm(length, width, m, angle, refPlane)
      Crv = MakeCurve(pts, angle, refPlane)
      L = length
      W = width
      If flip_H Then height = -height
      H = height
      If flip_A Then angle = -angle
      A = angle
      E = E * 10 ^ 9  ' Young's modulus input E is in GPa, so we convert to Pa here (= N/m^2)
      F = EllipticK(m) ^ 2 * E * I / length ^ 2  ' from reference {4} pg. 79. Note: the critical buckling (that makes the rod/wire start to bend) can be found at height=0 (width=length)
      'height = Math.Sqrt(((2 * Len / 5) ^ 2 - ((Wid - Len / 5) / 2) ^ 2)  ' quick approximation discovered by Mårten of 'Geometry of Bending' fame ( http://tiny.cc/it2pbx )
      'width = (Len +/- 2 * Math.Sqrt(4 * Len ^ 2 - 25 * Ht ^ 2)) / 5  ' derived from above
      'length = (2 * Math.Sqrt(15 * Ht ^ 2 + 4 * Wid ^ 2) - Wid) / 3  ' derived from above
      'Print("length=" & length & ", width=" & width & ", height=" & height & ", angle=" & angle & ", m=" & m & ", k=" & Math.Sqrt(m) & ", w/L=" & width / length & ", h/L=" & height / length & ", w/h=" & width / height)
    End If
- 
                          2806
                          1380
                          84
                          184
                        
- 
                          2848
                          1472
                        
- 9
- 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2
- 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2
- 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2
- 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2
- 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2
- 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2
- 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2
- 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2
- 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2
- 8
- 3ede854e-c753-40eb-84cb-b48008f14fd4
- 8ec86459-bf01-4409-baee-174d0d2b13d0
- 8ec86459-bf01-4409-baee-174d0d2b13d0
- 8ec86459-bf01-4409-baee-174d0d2b13d0
- 8ec86459-bf01-4409-baee-174d0d2b13d0
- 8ec86459-bf01-4409-baee-174d0d2b13d0
- 8ec86459-bf01-4409-baee-174d0d2b13d0
- 8ec86459-bf01-4409-baee-174d0d2b13d0
- true
- Script Variable PtA
- 89fe7d9c-b998-43b5-8788-30064fd07e47
- PtA
- PtA
- true
- 0
- true
- c54e879a-bb6c-47c6-b366-aaa5a16a426a
- 83dc0e24-1c12-445e-8647-dffc452baa6a
- 2
- e1937b56-b1da-4c12-8bd8-e34ee81746ef
- 
                                  2808
                                  1382
                                  25
                                  20
                                
- 
                                  2822
                                  1392
                                
- true
- Script Variable PtB
- d6635d82-91c7-476c-acf5-3f2feae5d91b
- PtB
- PtB
- true
- 0
- true
- 72b7092f-b51c-4a8b-b457-5cc6f58de91d
- 5c0c8191-e5d5-44d8-9b74-ad7b50095c12
- 2
- e1937b56-b1da-4c12-8bd8-e34ee81746ef
- 
                                  2808
                                  1402
                                  25
                                  20
                                
- 
                                  2822
                                  1412
                                
- true
- Script Variable Pln
- 8a5ea10d-8baa-47cd-8970-989b44d90853
- Pln
- Pln
- true
- 0
- true
- f5ef3118-8c76-4765-bdd9-16087c3ebb2d
- 1
- 3897522d-58e9-4d60-b38c-978ddacfedd8
- 
                                  2808
                                  1422
                                  25
                                  20
                                
- 
                                  2822
                                  1432
                                
- true
- Script Variable Len
- 4adfaa55-4523-43d7-9887-fcfc9daa5d32
- Len
- Len
- true
- 0
- true
- 0
- 8e991e99-5fb8-41e1-928d-1bba8fb9f7d7
- 
                                  2808
                                  1442
                                  25
                                  20
                                
- 
                                  2822
                                  1452
                                
- true
- Script Variable Wid
- 8d352101-30bc-4590-8ef7-3bebef383668
- Wid
- Wid
- true
- 0
- true
- 0
- 8e991e99-5fb8-41e1-928d-1bba8fb9f7d7
- 
                                  2808
                                  1462
                                  25
                                  20
                                
- 
                                  2822
                                  1472
                                
- true
- Script Variable Ht
- ed97f943-b85a-4bc0-84db-64b077475aca
- Ht
- Ht
- true
- 0
- true
- cd2f5af0-b741-48d5-8bbd-e9695d5278d8
- 1
- 8e991e99-5fb8-41e1-928d-1bba8fb9f7d7
- 
                                  2808
                                  1482
                                  25
                                  20
                                
- 
                                  2822
                                  1492
                                
- true
- Script Variable Ang
- c30d75f7-bb99-4be5-88aa-f992b8386696
- Ang
- Ang
- true
- 0
- true
- 0
- 8e991e99-5fb8-41e1-928d-1bba8fb9f7d7
- 
                                  2808
                                  1502
                                  25
                                  20
                                
- 
                                  2822
                                  1512
                                
- true
- Script Variable E
- 33bfc033-c0d3-4ebb-a5b0-659df3a0b51e
- E
- E
- true
- 0
- true
- 0
- 8e991e99-5fb8-41e1-928d-1bba8fb9f7d7
- 
                                  2808
                                  1522
                                  25
                                  20
                                
- 
                                  2822
                                  1532
                                
- true
- Script Variable I
- 66f1e54b-d2c1-43dd-8716-e6fa7a1ddeca
- I
- I
- true
- 0
- true
- 0
- 8e991e99-5fb8-41e1-928d-1bba8fb9f7d7
- 
                                  2808
                                  1542
                                  25
                                  20
                                
- 
                                  2822
                                  1552
                                
- 1
- Print, Reflect and Error streams
- be85f9e8-bde2-44f9-9bb8-80b1010c9d68
- out
- out
- false
- 0
- 
                                  2863
                                  1382
                                  25
                                  22
                                
- 
                                  2875.5
                                  1393.25
                                
- Output parameter Pts
- bacf233a-c717-41ce-b241-8552418f09f9
- Pts
- Pts
- false
- 0
- 
                                  2863
                                  1404
                                  25
                                  23
                                
- 
                                  2875.5
                                  1415.75
                                
- Output parameter Crv
- 4fa97325-f527-43c0-a006-78cf944c5e40
- Crv
- Crv
- false
- 0
- 
                                  2863
                                  1427
                                  25
                                  22
                                
- 
                                  2875.5
                                  1438.25
                                
- Output parameter L
- b9ed95d2-8f4a-49e9-a734-c73e21c200b4
- L
- L
- false
- 0
- 
                                  2863
                                  1449
                                  25
                                  23
                                
- 
                                  2875.5
                                  1460.75
                                
- Output parameter W
- 264cbae0-f043-490d-9121-0e45630a0b2f
- W
- W
- false
- 0
- 
                                  2863
                                  1472
                                  25
                                  22
                                
- 
                                  2875.5
                                  1483.25
                                
- Output parameter H
- 1578bf3a-8211-4a77-85d0-3cd951789283
- H
- H
- false
- 0
- 
                                  2863
                                  1494
                                  25
                                  23
                                
- 
                                  2875.5
                                  1505.75
                                
- Output parameter A
- 97c17859-cbbf-4962-a448-d8665c3e706a
- A
- A
- false
- 0
- 
                                  2863
                                  1517
                                  25
                                  22
                                
- 
                                  2875.5
                                  1528.25
                                
- Output parameter F
- 8f3ba33f-2383-4ae9-b911-b9b6e4553a35
- F
- F
- false
- 0
- 
                                  2863
                                  1539
                                  25
                                  23
                                
- 
                                  2875.5
                                  1550.75
                                
- c277f778-6fdf-4890-8f78-347efb23c406
- Pipe
- Create a pipe surface around a rail curve.
- a18b4542-f317-4532-9634-9ef245df4e2c
- Pipe
- Pipe
- 
                          3076
                          1319
                          64
                          64
                        
- 
                          3107
                          1351
                        
- Base curve
- 9be76020-39f2-465f-b508-f09d3f48a425
- Curve
- C
- false
- 4fa97325-f527-43c0-a006-78cf944c5e40
- 1
- 
                              3078
                              1321
                              14
                              20
                            
- 
                              3086.5
                              1331
                            
- Pipe radius
- 0f317bff-3048-480b-865a-13a2e1cb5106
- Radius
- R
- false
- f2abb0db-802c-4f59-83cb-393711b4a3d9
- 1
- 
                              3078
                              1341
                              14
                              20
                            
- 
                              3086.5
                              1351
                            
- 1
- 1
- {0}
- 1
- Specifies the type of caps (0=None, 1=Flat, 2=Round)
- 38981e04-97f9-4736-a46b-c55825f5b8fe
- Caps
- E
- false
- 0
- 
                              3078
                              1361
                              14
                              20
                            
- 
                              3086.5
                              1371
                            
- 1
- 1
- {0}
- 0
- 1
- Resulting Pipe
- d118f269-0338-4d1d-b06d-018819a25f1a
- Pipe
- P
- false
- 0
- 
                              3122
                              1321
                              16
                              60
                            
- 
                              3130
                              1351
                            
- 59e0b89a-e487-49f8-bab8-b5bab16be14c
- Panel
- A panel for custom notes and text values
- f2abb0db-802c-4f59-83cb-393711b4a3d9
- Panel
- false
- 0
- 0
- .25
- 
                          2955
                          1314
                          50
                          20
                        
- 0
- 0
- 0
- 
                          2955.289
                          1314.952
                        
- 
                          255;255;250;90
                        
- true
- true
- true
- false
- false
- true
- 59e0b89a-e487-49f8-bab8-b5bab16be14c
- Panel
- A panel for custom notes and text values
- 26ed0e55-cf0a-436e-9447-805704984e62
- Panel
- false
- 0
- 087cd096-ba72-4a81-a462-a9ce3ce43ec4
- 1
- Double click to edit panel content…
- 
                          3045
                          1553
                          105
                          55
                        
- 0
- 0
- 0
- 
                          3045.485
                          1553.607
                        
- 
                          255;255;250;90
                        
- true
- true
- true
- false
- false
- true
- 0d77c51e-584f-44e8-aed2-c2ddf4803888
- Degrees
- Convert an angle specified in radians to degrees
- bb620c76-8624-412c-8f17-4aa82e09f1b9
- Degrees
- Deg
- 
                          2955
                          1562
                          64
                          28
                        
- 
                          2985
                          1576
                        
- Angle in radians
- e10ae9f2-834e-4fd3-afbb-6416a8f9ca28
- Radians
- R
- false
- 97c17859-cbbf-4962-a448-d8665c3e706a
- 1
- 
                              2957
                              1564
                              13
                              24
                            
- 
                              2965
                              1576
                            
- Angle in degrees
- 087cd096-ba72-4a81-a462-a9ce3ce43ec4
- Degrees
- D
- false
- 0
- 
                              3000
                              1564
                              17
                              24
                            
- 
                              3008.5
                              1576
                            
- 59e0b89a-e487-49f8-bab8-b5bab16be14c
- Panel
- A panel for custom notes and text values
- 4ddb17a4-9e5f-4fb4-9f06-84399d240517
- Panel
- false
- 0
- b9ed95d2-8f4a-49e9-a734-c73e21c200b4
- 1
- Double click to edit panel content…
- 
                          2941
                          1424
                          97
                          54
                        
- 0
- 0
- 0
- 
                          2941.968
                          1424.592
                        
- 
                          255;255;250;90
                        
- true
- true
- true
- false
- false
- true
- 59e0b89a-e487-49f8-bab8-b5bab16be14c
- Panel
- A panel for custom notes and text values
- 97a1d833-23ef-4dd7-a8f6-0467955bf4f5
- Panel
- false
- 0
- 264cbae0-f043-490d-9121-0e45630a0b2f
- 1
- Double click to edit panel content…
- 
                          3053
                          1458
                          105
                          55
                        
- 0
- 0
- 0
- 
                          3053.527
                          1458.041
                        
- 
                          255;255;250;90
                        
- true
- true
- true
- false
- false
- true
- 59e0b89a-e487-49f8-bab8-b5bab16be14c
- Panel
- A panel for custom notes and text values
- 8e36a5c6-61f4-4366-8856-2c787fd9a806
- Panel
- false
- 0
- 1578bf3a-8211-4a77-85d0-3cd951789283
- 1
- Double click to edit panel content…
- 
                          2941
                          1493
                          97
                          55
                        
- 0
- 0
- 0
- 
                          2941.552
                          1493.67
                        
- 
                          255;255;250;90
                        
- true
- true
- true
- false
- false
- true
- 59e0b89a-e487-49f8-bab8-b5bab16be14c
- Panel
- A panel for custom notes and text values
- 0903a6c2-e102-41a9-8326-3f9533f91f9f
- Panel
- false
- 0
- 0
- -150
- 
                          1440
                          1185
                          50
                          20
                        
- 0
- 0
- 0
- 
                          1440.106
                          1185.658
                        
- 
                          255;255;250;90
                        
- true
- true
- true
- false
- false
- true
- 59e0b89a-e487-49f8-bab8-b5bab16be14c
- Panel
- A panel for custom notes and text values
- 17a61eca-a95a-4f8b-aa55-052523e686bc
- Panel
- false
- 0
- 0
- 150
- 
                          1441
                          1215
                          50
                          20
                        
- 0
- 0
- 0
- 
                          1441.106
                          1215.658
                        
- 
                          255;255;250;90
                        
- true
- true
- true
- false
- false
- true
- d1a28e95-cf96-4936-bf34-8bf142d731bf
- Construct Domain
- Create a numeric domain from two numeric extremes.
- 14534673-98f6-45e8-b11f-39da628bc4ca
- Construct Domain
- Dom
- 
                          2193
                          764
                          61
                          44
                        
- 
                          2224
                          786
                        
- Start value of numeric domain
- c60598bb-4ac8-4310-9f9f-0d75cea21cfe
- Domain start
- A
- false
- 64b83d9b-5ae1-4022-b79e-c9135d3cdfc6
- 1
- 
                              2195
                              766
                              14
                              20
                            
- 
                              2203.5
                              776
                            
- 1
- 1
- {0}
- 0
- End value of numeric domain
- c4f2cdcf-3ac3-420a-925f-c2653c042270
- Domain end
- B
- false
- 2398bd00-b514-4723-b31f-c436e1ae908b
- 1
- 
                              2195
                              786
                              14
                              20
                            
- 
                              2203.5
                              796
                            
- 1
- 1
- {0}
- 1
- Numeric domain between {A} and {B}
- 035d494c-d9fa-434d-874c-206716be82af
- Domain
- I
- false
- 0
- 
                              2239
                              766
                              13
                              40
                            
- 
                              2245.5
                              786
                            
- 9445ca40-cc73-4861-a455-146308676855
- Range
- Create a range of numbers.
- fbb4ab09-bb2a-42d6-a9a9-345b5f2473bc
- Range
- Range
- 
                          2295
                          775
                          64
                          44
                        
- 
                          2326
                          797
                        
- Domain of numeric range
- 0dd6e136-7641-43ed-94ff-d87c8b3a4a7f
- Domain
- D
- false
- 035d494c-d9fa-434d-874c-206716be82af
- 1
- 
                              2297
                              777
                              14
                              20
                            
- 
                              2305.5
                              787
                            
- 1
- 1
- {0}
- 
                                      0
                                      1
                                    
- Number of steps
- b991e2eb-aa24-4a37-b83b-4de89b217793
- Steps
- N
- false
- cc8db470-d2c6-4bbc-92b0-9305165143f7
- 1
- 
                              2297
                              797
                              14
                              20
                            
- 
                              2305.5
                              807
                            
- 1
- 1
- {0}
- 10
- 1
- Range of numbers
- 9b2fc3d6-5abb-46f8-a49e-0ae9e8dc1647
- Range
- R
- false
- 0
- 
                              2341
                              777
                              16
                              40
                            
- 
                              2349
                              797
                            
- 57da07bd-ecab-415d-9d86-af36d7073abc
- Number Slider
- Numeric slider for single values
- cc8db470-d2c6-4bbc-92b0-9305165143f7
- Number Slider
- num curves
- false
- 0
- 
                          1969
                          831
                          284
                          20
                        
- 
                          1969.186
                          831.0843
                        
- 0
- 1
- 0
- 400
- 1
- 0
- 200
- 079bd9bd-54a0-41d4-98af-db999015f63d
- VB Script
-   Private Function IsSet(ByVal param As String) As Boolean  ' Check if an input parameter has data
    Dim i As Integer = Component.Params.IndexOfInputParam(param)
    If i > -1 Then
      Return Component.Params.Input.ElementAt(i).DataType > 1  ' input parameter DataType of 1 means it's not receiving input (internal or external)
    Else
      Msg("error", "Input parameter '" & param & "' not found")
      Return False
    End If
  End Function
  Private Sub Msg(ByVal type As String, ByVal msg As String)  ' Output an error, warning, or informational message
    Select Case type
      Case "error"
        Component.AddRuntimeMessage(GH_RuntimeMessageLevel.Error, msg)
        Print("Error: " & msg)
      Case "warning"
        Component.AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, msg)
        Print("Warning: " & msg)
      Case "info"
        Component.AddRuntimeMessage(GH_RuntimeMessageLevel.Remark, msg)
        Print(msg)
    End Select
  End Sub
  ' Solve for the m parameter from length and width (reference {1} equation (34), except b = width and K(k) and E(k) should be K(m) and E(m))
  Private Function SolveMFromLenWid(ByVal L As Double, ByVal w As Double) As Double
    If w = 0 Then
      Return Defined.M_ZERO_W  ' for the boundry condition width = 0, bypass the function and return the known m value
    End If
    Dim n As Integer = 1 ' Iteration counter (quit if >MAXIT)
    Dim lower As Double = 0 ' m must be within this range
    Dim upper As Double = 1
    Dim m As Double
    Dim cwl As Double
    Do While (upper - lower) > Defined.MAXERR AndAlso (n) < Defined.MAXIT ' Repeat until range narrow enough or MAXIT
      m = (upper + lower) / 2
      cwl = 2 * EllipticE(m) / EllipticK(m) - 1  ' calculate w/L with the test value of m
      If cwl < w / L Then  ' compares the calculated w/L with the actual w/L then narrows the range of possible m
        upper = m
      Else
        lower = m
      End If
      n += 1
    Loop
    Return m
  End Function
  ' Solve for the m parameter from length and height (reference {1} equation (33), except K(k) should be K(m) and k = sqrt(m))
  ' Note that it's actually possible to find 2 valid values for m (hence 2 width values) at certain height values
  Private Function SolveMFromLenHt(ByVal L As Double, ByVal h As Double) As List(Of Double)
    Dim n As Integer = 1 ' Iteration counter (quit if >MAXIT)
    Dim lower As Double = 0 ' m must be within this range
    Dim upper As Double = 1
    Dim twoWidths As Boolean = h / L >= Defined.DOUBLE_W_HL_RATIO And h / L < Defined.MAX_HL_RATIO  ' check to see if h/L is within the range where 2 solutions for the width are possible
    Dim m As Double
    Dim mult_m As New List(Of Double)
    Dim chl As Double
    If twoWidths Then
      ' find the first of two possible solutions for m with the following limits:
      lower = Defined.M_DOUBLE_W  ' see constants at bottom of script
      upper = Defined.M_MAXHEIGHT  ' see constants at bottom of script
      Do While (upper - lower) > Defined.MAXERR AndAlso (n) < Defined.MAXIT ' Repeat until range narrow enough or MAXIT
        m = (upper + lower) / 2
        chl = Math.Sqrt(m) / EllipticK(m)  ' calculate h/L with the test value of m
        If chl > h / L Then  ' compares the calculated h/L with the actual h/L then narrows the range of possible m
          upper = m
        Else
          lower = m
        End If
        n += 1
      Loop
      mult_m.Add(m)
      ' then find the second of two possible solutions for m with the following limits:
      lower = Defined.M_MAXHEIGHT  ' see constants at bottom of script
      upper = 1
      Do While (upper - lower) > Defined.MAXERR AndAlso (n) < Defined.MAXIT ' Repeat until range narrow enough or MAXIT
        m = (upper + lower) / 2
        chl = Math.Sqrt(m) / EllipticK(m)  ' calculate h/L with the test value of m
        If chl < h / L Then  ' compares the calculated h/L with the actual h/L then narrows the range of possible m
          upper = m
        Else
          lower = m
        End If
        n += 1
      Loop
      If m <= Defined.M_MAX Then  ' return this m parameter only if it falls within the maximum useful value (above which the curve breaks down)
        mult_m.Add(m)
      End If
    Else
      ' find the one possible solution for the m parameter
      upper = Defined.M_DOUBLE_W  ' limit the upper end of the search to the maximum value of m for which only one solution exists
      Do While (upper - lower) > Defined.MAXERR AndAlso (n) < Defined.MAXIT ' Repeat until range narrow enough or MAXIT
        m = (upper + lower) / 2
        chl = Math.Sqrt(m) / EllipticK(m)  ' calculate h/L with the test value of m
        If chl > h / L Then  ' compares the calculated h/L with the actual h/L then narrows the range of possible m
          upper = m
        Else
          lower = m
        End If
        n += 1
      Loop
      mult_m.Add(m)
    End If
    Return mult_m
  End Function
  ' Solve for the m parameter from width and height (derived from reference {1} equations (33) and (34) with same notes as above)
  Private Function SolveMFromWidHt(ByVal w As Double, ByVal h As Double) As Double
    Dim n As Integer = 1 ' Iteration counter (quit if >MAXIT)
    Dim lower As Double = 0 ' m must be within this range
    Dim upper As Double = 1
    Dim m As Double
    Dim cwh As Double
    Do While (upper - lower) > Defined.MAXERR AndAlso (n) < Defined.MAXIT ' Repeat until range narrow enough or MAXIT
      m = (upper + lower) / 2
      cwh = (2 * EllipticE(m) - EllipticK(m)) / Math.Sqrt(m)  ' calculate w/h with the test value of m
      If cwh < w / h Then  ' compares the calculated w/h with the actual w/h then narrows the range of possible m
        upper = m
      Else
        lower = m
      End If
      n += 1
    Loop
    Return m
  End Function
  ' Calculate length based on height and an m parameter, derived from reference {1} equation (33), except K(k) should be K(m) and k = sqrt(m)
  Private Function Cal_L(ByVal h As Double, ByVal m As Double) As Double
    Return h * EllipticK(m) / Math.Sqrt(m)
  End Function
  ' Calculate width based on length and an m parameter, derived from reference {1} equation (34), except b = width and K(k) and E(k) should be K(m) and E(m)
  Private Function Cal_W(ByVal L As Double, ByVal m As Double) As Double
    Return L * (2 * EllipticE(m) / EllipticK(m) - 1)
  End Function
  ' Calculate height based on length and an m parameter, from reference {1} equation (33), except K(k) should be K(m) and k = sqrt(m)
  Private Function Cal_H(ByVal L As Double, ByVal m As Double) As Double
    Return L * Math.Sqrt(m) / EllipticK(m)
  End Function
  ' Calculate the unique m parameter based on a start tangent angle, from reference {2}, just above equation (9a), that states k = Sin(angle / 2 + Pi / 4),
  ' but as m = k^2 and due to this script's need for an angle rotated 90° versus the one in reference {1}, the following formula is the result
  ' New note: verified by reference {4}, pg. 78 at the bottom
  Private Function Cal_M(ByVal a As Double) As Double
    Return (1 - Math.Cos(a)) / 2  ' equal to Sin^2(a/2) too
  End Function
  ' Calculate start tangent angle based on an m parameter, derived from above formula
  Private Function Cal_A(ByVal m As Double) As Double
    Return Math.Acos(1 - 2 * m)
  End Function
  ' This is the heart of this script, taking the found (or specified) length, width, and angle values along with the found m parameter to create
  ' a list of points that approximate the shape or form of the elastica. It works by finding the x and y coordinates (which are reversed versus
  ' the original equations (12a) and (12b) from reference {2} due to the 90° difference in orientation) based on the tangent angle along the curve.
  ' See reference {2} for more details on how they derived it. Note that to simplify things, the algorithm only calculates the points for half of the
  ' curve, then mirrors those points along the y-axis.
  Private Function FindBendForm(ByVal L As Double, ByVal w As Double, ByVal m As Double, ByVal ang As Double, ByVal refPln As Plane) As List(Of Point3d)
    L = L / 2  ' because the below algorithm is based on the formulas in reference {2} for only half of the curve
    w = w / 2  ' same
    If ang = 0 Then  ' if angle (and height) = 0, then simply return the start and end points of the straight line
      Dim out As New List(Of Point3d)
      out.Add(refPln.PointAt(w, 0, 0))
      out.Add(refPln.PointAt(-w, 0, 0))
      Return out
    End If
    Dim x As Double
    Dim y As Double
    Dim halfCurvePts As New List(Of Point3d)
    Dim fullCurvePts As New List(Of Point3d)
    Dim translatedPts As New List(Of Point3d)
    ang -= Math.PI / 2  ' a hack to allow this algorithm to work, since the original curve in paper {2} was rotated 90°
    Dim angB As Double = ang + (-Math.PI / 2 - ang) / Defined.CURVEDIVS  ' angB is the 'lowercase theta' which should be in formula {2}(12b) as the interval
    ' start [a typo...see equation(3)]. It's necessary to start angB at ang + [interval] instead of just ang due to integration failing at angB = ang
    halfCurvePts.Add(New Point3d(w, 0, 0))  ' start with this known initial point, as integration will fail when angB = ang
    ' each point {x, y} is calculated from the tangent angle, angB, that occurs at each point (which is why this iterates from ~ang to -pi/2, the known end condition)
    Do While Math.Round(angB, Defined.ROUNDTO) >= Math.Round(-Math.PI / 2, Defined.ROUNDTO)
      y = (Math.Sqrt(2) * Math.Sqrt(Math.Sin(ang) - Math.Sin(angB)) * (w + L)) / (2 * EllipticE(m))  ' note that x and y are swapped vs. (12a) and (12b)
      x = (L / (Math.Sqrt(2) * EllipticK(m))) * Simpson(angB, -Math.PI / 2, 500, ang)  ' calculate the Simpson approximation of the integral (function f below)
      ' over the interval angB ('lowercase theta') to -pi/2. side note: is 500 too few iterations for the Simson algorithm?
      If Math.Round(x, Defined.ROUNDTO) = 0 Then x = 0
      halfCurvePts.Add(New Point3d(x, y, 0))
      angB += (-Math.PI / 2 - ang) / Defined.CURVEDIVS  ' onto the next tangent angle
    Loop
    ' After finding the x and y values for half of the curve, add the {-x, y} values for the rest of the curve
    For Each point As Point3d In halfCurvePts
      If Math.Round(point.X, Defined.ROUNDTO) = 0 Then
        If Math.Round(point.Y, Defined.ROUNDTO) = 0 Then
          fullCurvePts.Add(New Point3d(0, 0, 0))  ' special case when width = 0: when x = 0, only duplicate the point when y = 0 too
        End If
      Else
        fullCurvePts.Add(New Point3d(-point.X, point.Y, 0))
      End If
    Next
    halfCurvePts.Reverse
    fullCurvePts.AddRange(halfCurvePts)
    For Each p As Point3d In fullCurvePts
      translatedPts.Add(refPln.PointAt(p.X, p.Y, p.Z))  ' translate the points from the reference plane to the world plane
    Next
    Return translatedPts
  End Function
  ' Interpolates the points from FindBendForm to create the Elastica curve. Uses start & end tangents for greater accuracy.
  Private Function MakeCurve(ByVal pts As List(Of Point3d), ByVal ang As Double, ByVal refPln As Plane) As Curve
    If ang <> 0 Then
      Dim ts, te As New Vector3d(refPln.XAxis)
      ts.Rotate(ang, refPln.ZAxis)
      te.Rotate(-ang, refPln.ZAxis)
      Return Curve.CreateInterpolatedCurve(pts, 3, CurveKnotStyle.Chord, ts, te)  ' 3rd degree curve with 'Chord' Knot Style
    Else
      Return Curve.CreateInterpolatedCurve(pts, 3)  ' if angle (and height) = 0, then simply interpolate the straight line (no start/end tangents)
    End If
  End Function
  ' Implements the Simpson approximation for an integral of function f below
  Public Function Simpson(a As Double, b As Double, n As Integer, theta As Double) As Double 'n should be an even number
    Dim j As Integer, s1 As Double, s2 As Double, h As Double
    h = (b - a) / n
    s1 = 0
    s2 = 0
    For j = 1 To n - 1 Step 2
      s1 = s1 + fn(a + j * h, theta)
    Next j
    For j = 2 To n - 2 Step 2
      s2 = s2 + fn(a + j * h, theta)
    Next j
    Simpson = h / 3 * (fn(a, theta) + 4 * s1 + 2 * s2 + fn(b, theta))
  End Function
  ' Specific calculation for the above integration
  Public Function fn(x As Double, theta As Double) As Double
    fn = Math.Sin(x) / (Math.Sqrt(Math.Sin(theta) - Math.Sin(x)))  ' from reference {2} formula (12b)
  End Function
  ' Return the Complete Elliptic integral of the 1st kind
  ' Abramowitz and Stegun p.591, formula 17.3.11
  ' Code from http://www.codeproject.com/Articles/566614/Elliptic-integrals
  Public Function EllipticK(ByVal m As Double) As Double
    Dim sum, term, above, below As Double
    sum = 1
    term = 1
    above = 1
    below = 2
    For i As Integer = 1 To 100
      term *= above / below
      sum += Math.Pow(m, i) * Math.Pow(term, 2)
      above += 2
      below += 2
    Next
    sum *= 0.5 * Math.PI
    Return sum
  End Function
  ' Return the Complete Elliptic integral of the 2nd kind
  ' Abramowitz and Stegun p.591, formula 17.3.12
  ' Code from http://www.codeproject.com/Articles/566614/Elliptic-integrals
  Public Function EllipticE(ByVal m As Double) As Double
    Dim sum, term, above, below As Double
    sum = 1
    term = 1
    above = 1
    below = 2
    For i As Integer = 1 To 100
      term *= above / below
      sum -= Math.Pow(m, i) * Math.Pow(term, 2) / above
      above += 2
      below += 2
    Next
    sum *= 0.5 * Math.PI
    Return sum
  End Function
  Friend Partial NotInheritable Class Defined
    Private Sub New()
    End Sub
    ' Note: most of these values for m and h/L ratio were found with Wolfram Alpha and either specific intercepts (x=0) or local minima/maxima. They should be constant.
    Public Const M_SKETCHY As Double = 0.95  ' value of the m parameter where the curvature near the ends of the curve gets wonky
    Public Const M_MAX As Double = 0.993  ' maximum useful value of the m parameter, above which this algorithm for the form of the curve breaks down
    Public Const M_ZERO_W As Double = 0.826114765984970336  ' value of the m parameter when width = 0
    Public Const M_MAXHEIGHT As Double = 0.701327460663101223  ' value of the m parameter at maximum possible height of the bent rod/wire
    Public Const M_DOUBLE_W As Double = 0.180254422335013983  ' minimum value of the m parameter when two width values are possible for a given height and length
    Public Const DOUBLE_W_HL_RATIO As Double = 0.257342117984635757  ' value of the height/length ratio above which there are two possible width values
    Public Const MAX_HL_RATIO As Double = 0.403140189705650243  ' maximum possible value of the height/length ratio
    Public Const MAXERR As Double = 0.0000000001  ' error tolerance
    Public Const MAXIT As Integer = 100  ' maximum number of iterations
    Public Const ROUNDTO As Integer = 10  ' number of decimal places to round off to
    Public Const CURVEDIVS As Integer = 50  ' number of sample points for building the curve (or half-curve as it were)
  End Class
- A VB.NET scriptable component
- 
                      98
                      86
                    
- true
- 63218c71-7758-4168-b163-745e456fb525
- VB Script
- VB
- true
- 0
-     ' -----------------------------------------------------------------
    ' Elastic Bending Script by Will McElwain
    ' Created February 2014
    '
    ' DESCRIPTION:
    ' This beast creates the so-called 'elastica curve', the shape a long, thin rod or wire makes when it is bent elastically (i.e. not permanently). In this case, force
    ' is assumed to only be applied horizontally (which would be in line with the rod at rest) and both ends are assumed to be pinned or hinged meaning they are free
    ' to rotate (as opposed to clamped, when the end tangent angle is fixed, usually horizontally). An interesting finding is that it doesn't matter what the material or
    ' cross-sectional area is, as long as they're uniform along the entire length. Everything makes the same shape when bent as long as it doesn't cross the threshold
    ' from elastic to plastic (permanent) deformation (I don't bother to find that limit here, but can be found if the yield stress for a material is known).
    '
    ' Key to the formulas used in this script are elliptic integrals, specifically K(m), the complete elliptic integral of the first kind, and E(m), the complete elliptic
    ' integral of the second kind. There was a lot of confusion over the 'm' and 'k' parameters for these functions, as some people use them interchangeably, but they are
    ' not the same. m = k^2 (thus k = Sqrt(m)). I try to use the 'm' parameter exclusively to avoid this confusion. Note that there is a unique 'm' parameter for every
    ' configuration/shape of the elastica curve.
    '
    ' This script tries to find that unique 'm' parameter based on the inputs. The algorithm starts with a test version of m, evaluates an expression, say 2*E(m)/K(m)-1,
    ' then compares the result to what it should be (in this case, a known width/length ratio). Iterate until the correct m is found. Once we have m, we can then calculate
    ' all of the other unknowns, then find points that lie on that curve, then interpolate those points for the actual curve. You can also use Wolfram|Alpha as I did to
    ' find the m parameter based on the equations in this script (example here: http://tiny.cc/t4tpbx for when say width=45.2 and length=67.1).
    '
    ' Other notes:
    ' * This script works with negative values for width, which will creat a self-intersecting curve (as it should). The curvature of the elastica starts to break down around
    ' m=0.95 (~154°), but this script will continue to work until M_MAX, m=0.993 (~169°). If you wish to ignore self-intersecting curves, set ignoreSelfIntersecting to True
    ' * When the only known values are length and height, it is actually possible for certain ratios of height to length to have two valid m values (thus 2 possible widths
    ' and angles). This script will return them both.
    ' * Only the first two valid parameters (of the required ones) will be used, meaning if all four are connected (length, width or a PtB, height, and angle), this script will
    ' only use length and width (or a PtB).
    ' * Depending on the magnitude of your inputs (say if they're really small, like if length < 10), you might have to increase the constant ROUNDTO at the bottom
    '
    ' REFERENCES:
    ' {1} "The elastic rod" by M.E. Pacheco Q. & E. Pina, http://www.scielo.org.mx/pdf/rmfe/v53n2/v53n2a8.pdf
    ' {2} "An experiment in nonlinear beam theory" by A. Valiente, http://www.deepdyve.com/lp/doc/I3lwnxdfGz , also here: http://tiny.cc/Valiente_AEiNBT
    ' {3} "Snap buckling, writhing and Loop formation In twisted rods" by V.G.A. GOSS, http://myweb.lsbu.ac.uk/~gossga/thesisFinal.pdf
    ' {4} "Theory of Elastic Stability" by Stephen Timoshenko, http://www.scribd.com/doc/50402462/Timoshenko-Theory-of-Elastic-Stability  (start on p. 76)
    '
    ' INPUT:
    ' PtA - First anchor point (required)
    ' PtB - Second anchor point (optional, though 2 out of the 4--length, width, height, angle--need to be specified)
    '       [note that PtB can be the same as PtA (meaning width would be zero)]
    '       [also note that if a different width is additionally specified that's not equal to the distance between PtA and PtB, then the end point will not equal PtB anymore]
    ' Pln - Plane of the bent rod/wire, which bends up in the +y direction. The line between PtA and PtB (if specified) must be parallel to the x-axis of this plane
    '
    ' ** 2 of the following 4 need to be specified **
    ' Len - Length of the rod/wire, which needs to be > 0
    ' Wid - Width between the endpoints of the curve [note: if PtB is specified in addition, and distance between PtA and PtB <> width, the end point will be relocated
    ' Ht - Height of the bent rod/wire (when negative, curve will bend downward, relative to the input plane, instead)
    ' Ang - Inner departure angle or tangent angle (in radians) at the ends of the bent rod/wire. Set up so as width approaches length (thus height approaches zero), angle approaches zero
    '
    ' * Following variables only needed for optional calculating of bending force, not for shape of curve.
    ' E - Young's modulus (modulus of elasticity) in GPa (=N/m^2) (material-specific. for example, 7075 aluminum is roughly 71.7 GPa)
    ' I - Second moment of area (or area moment of inertia) in m^4 (cross-section-specific. for example, a hollow rod
    '     would have I = pi * (outer_diameter^4 - inner_diameter^4) / 32
    ' Note: E*I is also known as flexural rigidity or bending stiffness
    '
    ' OUTPUT:
    ' out - only for debugging messages
    ' Pts - the list of points that approximate the shape of the elastica
    ' Crv - the 3rd-degree curve interpolated from those points (with accurate start & end tangents)
    ' L - the length of the rod/wire
    ' W - the distance (width) between the endpoints of the rod/wire
    ' H - the height of the bent rod/wire
    ' A - the tangent angle at the (start) end of the rod/wire
    ' F - the force needed to hold the rod/wire in a specific shape (based on the material properties & cross-section) **be sure your units for 'I' match your units for the
    ' rest of your inputs (length, width, etc.). Also note that the critical buckling load (force) that makes the rod/wire start to bend can be found at height=0
    '
    ' THANKS TO:
    ' Mårten Nettelbladt (thegeometryofbending.blogspot.com)
    ' Daniel Piker (Kangaroo plugin)
    ' David Rutten (Grasshopper guru)
    ' Euler & Bernoulli (the O.G.'s)
    '
    ' -----------------------------------------------------------------
    Dim ignoreSelfIntersecting As Boolean = False  ' set to True if you don't want to output curves where width < 0, which creates a self-intersecting curve
    Dim inCt As Integer = 0  ' count the number of required parameters that are receiving data
    Dim length As Double
    Dim width As System.Object = Nothing  ' need to set as Nothing so we can check if it has been assigned a value later
    Dim height As Double
    Dim angle As Double
    Dim m As Double
    Dim multiple_m As New List(Of Double)
    Dim AtoB As Line
    Dim flip_H As Boolean = False  ' if height is negative, this flag will be set
    Dim flip_A As Boolean = False  ' if angle is negative, this flag will be set
    If Not IsSet("Pln") Then
      Msg("error", "Base plane is not set")
      Return
    End If
    If Not IsSet("PtA") Then
      Msg("error", "Point A is not set")
      Return
    End If
    If Math.Round(Pln.DistanceTo(PtA), Defined.ROUNDTO) <> 0 Then
      Msg("error", "Point A is not on the base plane")
      Return
    End If
    Dim refPlane As Plane = Pln  ' create a reference plane = input plane and set the origin of it to PtA in case PtA isn't the origin already
    refPlane.Origin = PtA
    If IsSet("PtB") Then
      If Math.Round(Pln.DistanceTo(PtB), Defined.ROUNDTO) <> 0 Then
        Msg("error", "Point B is not on the base plane")
        Return
      End If
      AtoB = New Line(PtA, PtB)
      If AtoB.Length <> 0 And Not AtoB.Direction.IsPerpendicularTo(Pln.YAxis) Then
        Msg("error", "The line between PtA and PtB is not perpendicular to the Y-axis of the specified plane")
        Return
      End If
      inCt += 1
      If IsSet("Wid") Then Msg("info", "Wid will override the distance between PtA and PtB. If you do not want this to happen, disconnect PtB or Wid.")
      width = PtA.DistanceTo(PtB)  ' get the width (distance) between PtA and PtB
      
      Dim refPtB As Point3d
      refPlane.RemapToPlaneSpace(PtB, refPtB)
      If refPtB.X < 0 Then width = -width  ' check if PtB is to the left of PtA...if so, width is negative
    End If
    If IsSet("Len") Then inCt += 1
    If IsSet("Wid") Then inCt += 1
    If IsSet("Ht") Then inCt += 1
    If IsSet("Ang") Then inCt += 1
    If inCt > 2 Then Msg("info", "More parameters set than are required (out of length, width, height, angle). Only using the first two valid ones.")
    ' check for connected/specified inputs. note: only the first two that it comes across will be used
    If IsSet("Len") Then  ' if length is specified then...
      If Len <= 0 Then
        Msg("error", "Length cannot be negative or zero")
        Return
      End If
      If IsSet("Wid") Then  ' find height & angle based on length and specified width
        If Wid > Len Then
          Msg("error", "Width is greater than length")
          Return
        End If
        If Wid = Len Then  ' skip the solver and set the known values
          height = 0
          m = 0
          angle = 0
          width = Wid
        Else
          m = SolveMFromLenWid(Len, Wid)
          height = Cal_H(Len, m)  ' L * Sqrt(m) / K(m)
          angle = Cal_A(m)  ' Acos(1 - 2 * m)
          width = Wid
        End If
      Else If width IsNot Nothing Then  ' find height & angle based on length and calculated width (distance between PtA and PtB)
        If width > Len Then
          Msg("error", "Width is greater than length")
          Return
        End If
        If width = Len Then  ' skip the solver and set the known values
          height = 0
          m = 0
          angle = 0
        Else
          m = SolveMFromLenWid(Len, width)
          height = Cal_H(Len, m)  ' L * Sqrt(m) / K(m)
          angle = Cal_A(m)  ' Acos(1 - 2 * m)
        End If
      Else If IsSet("Ht") Then  ' find width & angle based on length and height  ** possible to return 2 results **
        If Math.Abs(Ht / Len) > Defined.MAX_HL_RATIO Then
          Msg("error", "Height not possible with given length")
          Return
        End If
        If Ht < 0 Then
          Ht = -Ht  ' if height is negative, set it to positive (for the calculations) but flip the reference plane about its x-axis
          refPlane.Transform(Transform.Mirror(New Plane(refPlane.Origin, refPlane.XAxis, refPlane.ZAxis)))
          flip_A = True
          flip_H = True
        End If
        If Ht = 0 Then  ' skip the solver and set the known values
          width = Len
          angle = 0
        Else
          multiple_m = SolveMFromLenHt(Len, Ht)  ' note that it's possible for two values of m to be found if height is close to max height
          If multiple_m.Count = 1 Then  ' if there's only one m value returned, calculate the width & angle here. we'll deal with multiple m values later
            m = multiple_m.Item(0)
            width = Cal_W(Len, m)  ' L * (2 * E(m) / K(m) - 1)
            angle = Cal_A(m)  ' Acos(1 - 2 * m)
          End If
        End If
        height = Ht
      Else If IsSet("Ang") Then  ' find width & height based on length and angle
        If Ang < 0 Then
          Ang = -Ang  ' if angle is negative, set it to positive (for the calculations) but flip the reference plane about its x-axis
          refPlane.Transform(Transform.Mirror(New Plane(refPlane.Origin, refPlane.XAxis, refPlane.ZAxis)))
          flip_A = True
          flip_H = True
        End If
        m = Cal_M(Ang)  ' (1 - Cos(a)) / 2
        If Ang = 0 Then  ' skip the solver and set the known values
          width = Len
          height = 0
        Else
          width = Cal_W(Len, m)  ' L * (2 * E(m) / K(m) - 1)
          height = Cal_H(Len, m)  ' L * Sqrt(m) / K(m)
        End If
        angle = Ang
      Else
        Msg("error", "Need to specify one more parameter in addition to length")
        Return
      End If
      length = Len
    Else If IsSet("Wid") Then  ' if width is specified then...
      If IsSet("Ht") Then  ' find length & angle based on specified width and height
        If Ht < 0 Then
          Ht = -Ht  ' if height is negative, set it to positive (for the calculations) but flip the reference plane about its x-axis
          refPlane.Transform(Transform.Mirror(New Plane(refPlane.Origin, refPlane.XAxis, refPlane.ZAxis)))
          flip_A = True
          flip_H = True
        End If
        If Ht = 0 Then  ' skip the solver and set the known values
          length = Wid
          angle = 0
        Else
          m = SolveMFromWidHt(Wid, Ht)
          length = Cal_L(Ht, m)  ' h * K(m) / Sqrt(m)
          angle = Cal_A(m)  ' Acos(1 - 2 * m)
        End If
        height = Ht
      Else If IsSet("Ang") Then  ' find length & height based on specified width and angle
        If Wid = 0 Then
          Msg("error", "Curve not possible with width = 0 and an angle as inputs")
          Return
        End If
        If Ang < 0 Then
          Ang = -Ang  ' if angle is negative, set it to positive (for the calculations) but flip the reference plane about its x-axis
          refPlane.Transform(Transform.Mirror(New Plane(refPlane.Origin, refPlane.XAxis, refPlane.ZAxis)))
          flip_A = True
          flip_H = True
        End If
        m = Cal_M(Ang)  ' (1 - Cos(a)) / 2
        If Ang = 0 Then  ' skip the solver and set the known values
          length = Wid
          height = 0
        Else
          length = Wid / (2 * EllipticE(m) / EllipticK(m) - 1)
          If length < 0 Then
            Msg("error", "Curve not possible at specified width and angle (calculated length is negative)")
            Return
          End If
          height = Cal_H(length, m)  ' L * Sqrt(m) / K(m)
        End If
        angle = Ang
      Else
        Msg("error", "Need to specify one more parameter in addition to width (Wid)")
        Return
      End If
      width = Wid
    Else If width IsNot Nothing Then  ' if width is determined by PtA and PtB then...
      If IsSet("Ht") Then  ' find length & angle based on calculated width and height
        If Ht < 0 Then
          Ht = -Ht  ' if height is negative, set it to positive (for the calculations) but flip the reference plane about its x-axis
          refPlane.Transform(Transform.Mirror(New Plane(refPlane.Origin, refPlane.XAxis, refPlane.ZAxis)))
          flip_A = True
          flip_H = True
        End If
        If Ht = 0 Then  ' skip the solver and set the known values
          length = width
          angle = 0
        Else
          m = SolveMFromWidHt(width, Ht)
          length = Cal_L(Ht, m)  ' h * K(m) / Sqrt(m)
          angle = Cal_A(m)  ' Acos(1 - 2 * m)
        End If
        height = Ht
      Else If IsSet("Ang") Then  ' find length & height based on calculated width and angle
        If width = 0 Then
          Msg("error", "Curve not possible with width = 0 and an angle as inputs")
          Return
        End If
        If Ang < 0 Then
          Ang = -Ang  ' if angle is negative, set it to positive (for the calculations) but flip the reference plane about its x-axis
          refPlane.Transform(Transform.Mirror(New Plane(refPlane.Origin, refPlane.XAxis, refPlane.ZAxis)))
          flip_A = True
          flip_H = True
        End If
        m = Cal_M(Ang)  ' (1 - Cos(a)) / 2
        If Ang = 0 Then  ' skip the solver and set the known values
          length = width
          height = 0
        Else
          length = width / (2 * EllipticE(m) / EllipticK(m) - 1)
          If length < 0 Then
            Msg("error", "Curve not possible at specified width and angle (calculated length is negative)")
            Return
          End If
          height = Cal_H(length, m)  ' L * Sqrt(m) / K(m)
        End If
        angle = Ang
      Else
        Msg("error", "Need to specify one more parameter in addition to PtA and PtB")
        Return
      End If
    Else If IsSet("Ht") Then  ' if height is specified then...
      If IsSet("Ang") Then  ' find length & width based on height and angle
        If Ht < 0 Then
          Ht = -Ht  ' if height is negative, set it to positive (for the calculations) but flip the reference plane about its x-axis
          refPlane.Transform(Transform.Mirror(New Plane(refPlane.Origin, refPlane.XAxis, refPlane.ZAxis)))
          flip_H = True
          flip_A = True
        End If
        If Ht = 0 Then
          Msg("error", "Height can't = 0 if only height and angle are specified")
          Return
        Else
          If Ang < 0 Then
            Ang = -Ang  ' if angle is negative, set it to positive (for the calculations) but flip the reference plane about its x-axis
            refPlane.Transform(Transform.Mirror(New Plane(refPlane.Origin, refPlane.XAxis, refPlane.ZAxis)))
            flip_A = Not flip_A
            flip_H = Not flip_H
          End If
          m = Cal_M(Ang)  ' (1 - Cos(a)) / 2
          If Ang = 0 Then
            Msg("error", "Angle can't = 0 if only height and angle are specified")
            Return
          Else
            length = Cal_L(Ht, m)  ' h * K(m) / Sqrt(m)
            width = Cal_W(length, m)  ' L * (2 * E(m) / K(m) - 1)
          End If
          angle = Ang
        End If
        height = Ht
      Else
        Msg("error", "Need to specify one more parameter in addition to height")
        Return
      End If
    Else If IsSet("Ang") Then
      Msg("error", "Need to specify one more parameter in addition to angle")
      Return
    Else
      Msg("error", "Need to specify two of the four parameters: length, width (or PtB), height, and angle")
      Return
    End If
    If m > Defined.M_MAX Then
      Msg("error", "Form of curve not solvable with current algorithm and given inputs")
      Return
    End If
    refPlane.Origin = refPlane.PointAt(width / 2, 0, 0)  ' adjust the origin of the reference plane so that the curve is centered about the y-axis (start of the curve is at x = -width/2)
    If multiple_m.Count > 1 Then  ' if there is more than one m value returned, calculate the width, angle, and curve for each
      Dim multi_pts As New DataTree(Of Point3d)
      Dim multi_crv As New List(Of Curve)
      Dim tmp_pts As New List(Of Point3d)
      Dim multi_W, multi_A, multi_F As New List(Of Double)
      Dim j As Integer = 0  ' used for creating a new branch (GH_Path) for storing pts which is itself a list of points
      For Each m_val As Double In multiple_m
        width = Cal_W(length, m_val) 'length * (2 * EllipticE(m_val) / EllipticK(m_val) - 1)
        
        If width < 0 And ignoreSelfIntersecting Then
          Msg("warning", "One curve is self-intersecting. To enable these, set ignoreSelfIntersecting to False")
          Continue For
        End If
        
        If m_val >= Defined.M_SKETCHY Then Msg("info", "Accuracy of the curve whose width = " & Math.Round(width, 4) & " is not guaranteed")
        
        angle = Cal_A(m_val) 'Math.Asin(2 * m_val - 1)
        refPlane.Origin = refPlane.PointAt(width / 2, 0, 0)  ' adjust the origin of the reference plane so that the curve is centered about the y-axis (start of the curve is at x = -width/2)
        
        tmp_pts = FindBendForm(length, width, m_val, angle, refPlane)
        multi_pts.AddRange(tmp_pts, New GH_Path(j))
        multi_crv.Add(MakeCurve(tmp_pts, angle, refPlane))
        
        multi_W.Add(width)
        If flip_A Then angle = -angle
        multi_A.Add(angle)
        
        E = E * 10 ^ 9  ' Young's modulus input E is in GPa, so we convert to Pa here (= N/m^2)
        multi_F.Add(EllipticK(m_val) ^ 2 * E * I / length ^ 2)  ' from reference {4} pg. 79
        
        j += 1
        refPlane.Origin = PtA  ' reset the reference plane origin to PtA for the next m_val
        'Print("length=" & length & ", width=" & width & ", height=" & height & ", angle=" & angle & ", m=" & m_val & ", k=" & Math.Sqrt(m_val) & ", w/L=" & width / length & ", h/L=" & height / length & ", w/h=" & width / height)
      Next
      ' assign the outputs
      Pts = multi_pts
      Crv = multi_crv
      L = length
      W = multi_W
      If flip_H Then height = -height
      H = height
      A = multi_A
      F = multi_F
    Else  ' only deal with the single m value
      If m >= Defined.M_SKETCHY Then Msg("info", "Accuracy of the curve at these parameters is not guaranteed")
      
      If width < 0 And ignoreSelfIntersecting Then
        Msg("error", "Curve is self-intersecting. To enable these, set ignoreSelfIntersecting to False")
        Return
      End If
      
      Pts = FindBendForm(length, width, m, angle, refPlane)
      Crv = MakeCurve(pts, angle, refPlane)
      L = length
      W = width
      If flip_H Then height = -height
      H = height
      If flip_A Then angle = -angle
      A = angle
      E = E * 10 ^ 9  ' Young's modulus input E is in GPa, so we convert to Pa here (= N/m^2)
      F = EllipticK(m) ^ 2 * E * I / length ^ 2  ' from reference {4} pg. 79. Note: the critical buckling (that makes the rod/wire start to bend) can be found at height=0 (width=length)
      'height = Math.Sqrt(((2 * Len / 5) ^ 2 - ((Wid - Len / 5) / 2) ^ 2)  ' quick approximation discovered by Mårten of 'Geometry of Bending' fame ( http://tiny.cc/it2pbx )
      'width = (Len +/- 2 * Math.Sqrt(4 * Len ^ 2 - 25 * Ht ^ 2)) / 5  ' derived from above
      'length = (2 * Math.Sqrt(15 * Ht ^ 2 + 4 * Wid ^ 2) - Wid) / 3  ' derived from above
      'Print("length=" & length & ", width=" & width & ", height=" & height & ", angle=" & angle & ", m=" & m & ", k=" & Math.Sqrt(m) & ", w/L=" & width / length & ", h/L=" & height / length & ", w/h=" & width / height)
    End If
- 
                          2397
                          703
                          84
                          184
                        
- 
                          2439
                          795
                        
- 9
- 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2
- 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2
- 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2
- 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2
- 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2
- 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2
- 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2
- 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2
- 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2
- 8
- 3ede854e-c753-40eb-84cb-b48008f14fd4
- 8ec86459-bf01-4409-baee-174d0d2b13d0
- 8ec86459-bf01-4409-baee-174d0d2b13d0
- 8ec86459-bf01-4409-baee-174d0d2b13d0
- 8ec86459-bf01-4409-baee-174d0d2b13d0
- 8ec86459-bf01-4409-baee-174d0d2b13d0
- 8ec86459-bf01-4409-baee-174d0d2b13d0
- 8ec86459-bf01-4409-baee-174d0d2b13d0
- true
- Script Variable PtA
- c36c2a91-b586-4100-a3d3-5bbd29795b28
- PtA
- PtA
- true
- 0
- true
- 75154365-a588-4c21-86a3-ce81e626861d
- 1
- e1937b56-b1da-4c12-8bd8-e34ee81746ef
- 
                                  2399
                                  705
                                  25
                                  20
                                
- 
                                  2413
                                  715
                                
- true
- Script Variable PtB
- c03912a8-42cd-4a8e-b0e4-d859c1258a99
- PtB
- PtB
- true
- 0
- true
- 0
- e1937b56-b1da-4c12-8bd8-e34ee81746ef
- 
                                  2399
                                  725
                                  25
                                  20
                                
- 
                                  2413
                                  735
                                
- true
- Script Variable Pln
- f51b86ed-0366-4427-847a-63fd2fd6bf90
- Pln
- Pln
- true
- 0
- true
- f3933593-ac71-4dcf-9de1-01828b79508a
- 1
- 3897522d-58e9-4d60-b38c-978ddacfedd8
- 
                                  2399
                                  745
                                  25
                                  20
                                
- 
                                  2413
                                  755
                                
- true
- Script Variable Len
- 7ea941b6-d28a-421f-a3f1-b6ee6ba45ce3
- Len
- Len
- true
- 0
- true
- 2398bd00-b514-4723-b31f-c436e1ae908b
- 1
- 8e991e99-5fb8-41e1-928d-1bba8fb9f7d7
- 
                                  2399
                                  765
                                  25
                                  20
                                
- 
                                  2413
                                  775
                                
- true
- Script Variable Wid
- ca56b21d-1bf4-4ef7-9aba-89e8c40123e1
- Wid
- Wid
- true
- 0
- true
- 0
- 8e991e99-5fb8-41e1-928d-1bba8fb9f7d7
- 
                                  2399
                                  785
                                  25
                                  20
                                
- 
                                  2413
                                  795
                                
- true
- Script Variable Ht
- 01f793d6-6952-4cc0-9007-804b34e3573a
- Ht
- Ht
- true
- 0
- true
- 0
- 8e991e99-5fb8-41e1-928d-1bba8fb9f7d7
- 
                                  2399
                                  805
                                  25
                                  20
                                
- 
                                  2413
                                  815
                                
- true
- Script Variable Ang
- d1ecc6ce-5745-410a-98ac-8cd99da220f9
- Ang
- Ang
- true
- 0
- true
- 0
- 8e991e99-5fb8-41e1-928d-1bba8fb9f7d7
- 
                                  2399
                                  825
                                  25
                                  20
                                
- 
                                  2413
                                  835
                                
- true
- Script Variable E
- ee84edc7-8985-4013-a1da-ab406c4a251b
- E
- E
- true
- 0
- true
- 0
- 8e991e99-5fb8-41e1-928d-1bba8fb9f7d7
- 
                                  2399
                                  845
                                  25
                                  20
                                
- 
                                  2413
                                  855
                                
- true
- Script Variable I
- 06df9652-281a-4459-91a6-57c181550607
- I
- I
- true
- 0
- true
- 0
- 8e991e99-5fb8-41e1-928d-1bba8fb9f7d7
- 
                                  2399
                                  865
                                  25
                                  20
                                
- 
                                  2413
                                  875
                                
- 1
- Print, Reflect and Error streams
- c01c7c67-2ce9-42db-98c8-ac53917d2607
- out
- out
- false
- 0
- 
                                  2454
                                  705
                                  25
                                  22
                                
- 
                                  2466.5
                                  716.25
                                
- Output parameter Pts
- 03112bf2-28fb-457f-b3d5-277c7e00bc21
- Pts
- Pts
- false
- 0
- 
                                  2454
                                  727
                                  25
                                  23
                                
- 
                                  2466.5
                                  738.75
                                
- Output parameter Crv
- 49ed72a9-4d6b-4881-ac0f-b8700f17fd26
- Crv
- Crv
- false
- 0
- 
                                  2454
                                  750
                                  25
                                  22
                                
- 
                                  2466.5
                                  761.25
                                
- Output parameter L
- 88bfd5c3-b1ad-4215-961b-9ab638f2cfd6
- L
- L
- false
- 0
- 
                                  2454
                                  772
                                  25
                                  23
                                
- 
                                  2466.5
                                  783.75
                                
- Output parameter W
- 5419ee09-aef9-46c4-abed-2d8045ba1ca7
- W
- W
- false
- 0
- 
                                  2454
                                  795
                                  25
                                  22
                                
- 
                                  2466.5
                                  806.25
                                
- Output parameter H
- b01ed3c0-f6fa-4b63-bd7e-3eef2c0d55a4
- H
- H
- false
- 0
- 
                                  2454
                                  817
                                  25
                                  23
                                
- 
                                  2466.5
                                  828.75
                                
- Output parameter A
- 7adf1044-78f7-4bcc-874b-e500d7bbbd0d
- A
- A
- false
- 0
- 
                                  2454
                                  840
                                  25
                                  22
                                
- 
                                  2466.5
                                  851.25
                                
- Output parameter F
- 06232a84-6a80-4dfa-8393-98b404b97208
- F
- F
- false
- 0
- 
                                  2454
                                  862
                                  25
                                  23
                                
- 
                                  2466.5
                                  873.75
                                
- 57da07bd-ecab-415d-9d86-af36d7073abc
- Number Slider
- Numeric slider for single values
- 2398bd00-b514-4723-b31f-c436e1ae908b
- Number Slider
- length
- false
- 0
- 
                          1782
                          726
                          382
                          20
                        
- 
                          1782.348
                          726.8306
                        
- 2
- 1
- 0
- 400
- 0
- 0
- 250
- 3581f42a-9592-4549-bd6b-1c0fc39d067b
- Construct Point
- Construct a point from {xyz} coordinates.
- cf3f354f-4379-4525-be10-5b0dbf31bcff
- Construct Point
- Pt
- 
                          2254
                          641
                          67
                          64
                        
- 
                          2285
                          673
                        
- {x} coordinate
- 661f67f9-9359-4ee5-a58c-df76414fabf0
- X coordinate
- X
- false
- c2ff491e-b898-432c-8e6a-7db46434934a
- 1
- 
                              2256
                              643
                              14
                              20
                            
- 
                              2264.5
                              653
                            
- 1
- 1
- {0}
- 0
- {y} coordinate
- fe9dc686-4183-43f9-863d-c8c499a24577
- Y coordinate
- Y
- false
- 0
- 
                              2256
                              663
                              14
                              20
                            
- 
                              2264.5
                              673
                            
- 1
- 1
- {0}
- 0
- {z} coordinate
- 878e78bd-0868-4cae-b9a9-ef4a62dac81e
- Z coordinate
- Z
- false
- 0
- 
                              2256
                              683
                              14
                              20
                            
- 
                              2264.5
                              693
                            
- 1
- 1
- {0}
- 0
- Point coordinate
- 75154365-a588-4c21-86a3-ce81e626861d
- Point
- Pt
- false
- 0
- 
                              2300
                              643
                              19
                              60
                            
- 
                              2309.5
                              673
                            
- d5967b9f-e8ee-436b-a8ad-29fdcecf32d5
- Curve
- Contains a collection of generic curves
- 934a131f-f506-4502-86d5-aca65a992e3c
- Curve
- Crv
- false
- 49ed72a9-4d6b-4881-ac0f-b8700f17fd26
- 1
- 
                          2525
                          750
                          50
                          24
                        
- 
                          2550.661
                          762.5297
                        
- 17b7152b-d30d-4d50-b9ef-c9fe25576fc2
- XY Plane
- World XY plane.
- true
- b2200c91-bbca-48a4-a165-a7f1e2fe3c5f
- XY Plane
- XY
- 
                          2261
                          707
                          64
                          28
                        
- 
                          2292
                          721
                        
- Origin of plane
- 8589cc40-e2f3-4654-885c-b57ca3fd526a
- Origin
- O
- false
- 0
- 
                              2263
                              709
                              14
                              24
                            
- 
                              2271.5
                              721
                            
- 1
- 1
- {0}
- 
                                      0
                                      0
                                      0
                                    
- World XY plane
- f3933593-ac71-4dcf-9de1-01828b79508a
- Plane
- P
- false
- 0
- 
                              2307
                              709
                              16
                              24
                            
- 
                              2315
                              721
                            
- 59e0b89a-e487-49f8-bab8-b5bab16be14c
- Panel
- A panel for custom notes and text values
- c2ff491e-b898-432c-8e6a-7db46434934a
- Panel
- false
- 0
- 0
- 0
- 
                          2170
                          644
                          50
                          20
                        
- 0
- 0
- 0
- 
                          2170.805
                          644.7167
                        
- 
                          255;255;250;90
                        
- true
- true
- true
- false
- false
- true
- 7f5c6c55-f846-4a08-9c9a-cfdc285cc6fe
- Scribble
- true
- 
                      2131.598
                      592.215
                    
- 
                      2482.523
                      592.215
                    
- 
                      2482.523
                      607.2424
                    
- 
                      2131.598
                      607.2424
                    
- A quick note
- Microsoft Sans Serif
- 61857d57-1c68-49a3-ad6f-54433ce11822
- false
- Scribble
- Scribble
- 16
- Connect the Range component to Wid (ooooh)
- 
                          2126.598
                          587.215
                          360.9243
                          25.02734
                        
- 
                          2131.598
                          592.215
                        
- 7f5c6c55-f846-4a08-9c9a-cfdc285cc6fe
- Scribble
- true
- 
                      29.21105
                      1018.627
                    
- 
                      472.5363
                      1018.376
                    
- 
                      472.5443
                      1032.464
                    
- 
                      29.21903
                      1032.715
                    
- A quick note
- Microsoft Sans Serif
- a735556e-8f05-4f8e-b6ab-1cc5ff398382
- false
- Scribble
- Scribble
- 15
- For Force calc, Young's modulus (material-dependent, in GPa)
- 
                          24.21105
                          1013.376
                          453.3333
                          24.33868
                        
- 
                          29.21105
                          1018.627
                        
- 59e0b89a-e487-49f8-bab8-b5bab16be14c
- Panel
- A panel for custom notes and text values
- 64b83d9b-5ae1-4022-b79e-c9135d3cdfc6
- Panel
- false
- 0
- 0
- 0
- 
                          2102
                          767
                          50
                          20
                        
- 0
- 0
- 0
- 
                          2102.709
                          767.0847
                        
- 
                          255;255;250;90
                        
- true
- true
- true
- false
- false
- true
- 57da07bd-ecab-415d-9d86-af36d7073abc
- Number Slider
- Numeric slider for single values
- 8162af0c-aab0-4024-a905-8206506ff4fd
- Number Slider
- height
- false
- 0
- 
                          1344
                          308
                          384
                          20
                        
- 
                          1344.632
                          308.1685
                        
- 2
- 1
- 0
- 200
- -200
- 0
- -56.13
- 
          iVBORw0KGgoAAAANSUhEUgAAAJYAAABkCAIAAADrOV6nAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAACr1SURBVHhe7X1XVFxJtuX7m3lf89Wv15p5H9Pvc9brj561erpfTRtVybuqkjdlVSp5nIQ3wnuTCem992SSDpOYxHufmXjvhAeBfFX1NLNvXkQBEsghnqjmrrMuceNGxI2MHSfixDkngn/6p93rF9ACS7vXjm2B5e6H+pfuXjuwBQDcLoQ7ELdVVd6FcGfjh9rvQrgL4Y5vgR3/A3a5cBfCHd8CO/4H7HLhLoQ7vgV2/A/Y5cJdCHd8C+z4H7DLhbsQ7vgW2PE/YJcLdyEsLa2qqqqursa93H292CRlZWUVFRUr8SUlJXhEltWR63LhFa6XloaUKPCl2TcpELlQWmVlJb6O+0rJ6+pGJkPhuDb6+rqqvljCNneKd+VC/E6j0SgUCuVyuc1mKywsJH8/fgbZyjU1NUhjNptJ2PCD8ZiTkyORSJAerYkL8JOoIICMyIJyrFYrEiBMlkZ2FCQjS0B2FELmxR2FI4Cv4BX5RdxJwMgGRS6Ulpubi2TIWFBQgNKQBgF8iKwzWThipFKpQCBAYvInkKCSwJOVJCtMVslut+fl5eEtWcI244fPvROEZAf87LPPPDw84uPjw8PDU1JSLBaLTqfDz1Or1WismJiY2NhYCoWCjwHpoqKi5ubm77///vLlyxcvXsSPR/qsrCyUo1QqtVptXV0dHr/66quoqCg+nw9UEI/IzMxM9JLi4uL6+vrr16/fuHHj2rVreNRoNHiVn58vk8mQBV8EAIgPCgri8Xhk0+NqbGyMjIzcs2cPvv773/+eTqcDOYPBoNfrk5OTUQ3kQg2bmppCQ0NPnjwZGBgoFotRW5QMLPHp7OxsFIsAcuGn4bfjZ+LCdz09PfF7UU98aEdCePjwYT8/Pw6HgxbE70f77t+/H8h99NFHd+/e/fLLL7/99lu0iJeX19WrV1ksVnt7+zfffAMAjh07lp6efuTIkaNHjwYEBKArfP311yjkypUrJ06cuHPnjo+Pz+nTp7/44gtEIv3nn3+OTtDS0oJi0QOio6MzMjLwFt/C/bvvvkMWsmegTQ8cOID4hoYGNDcaGsglJCT86U9/Anh/+MMf8N1bt27t27cvLCwMnz5//jy+iAK7u7v9/f3xUeRF70FpqBI+ik+fO3cuODgYVUX47NmzSIw7EqD74rp06RL6B0rDF7cZxXflQnTGgwcPJiYmKhQKtCx+CS7E+Pr6gpPws729vRFGs6KZ0IUxALpcLjyCZdHuiATeaAggjUZBJPKCoW/evAng8RatBi45fvw4WBlFMZlMtBFaCkh8+umnp06dCgkJwUgOAFABoIhyqFQquByFs9lssCxqFRcX53Q6UT7eosOhhqgSykeYxB79A7nQdfr6+m7fvo1X6JEYzFF/dCwMLQigqyFjREQEEuCOOqMQVBUJkH7v3r3ol3i1wyBEd8PQgUZEr8edy+UyGAz8MDAlei66M7gHAbAgXqFB0QQYncAQaBSABHgwgqGJwbsikQgpMXIiAaBCCUiP4RcxAJ5Go2Fw+93vfofhDmMd8ANIaEcMceAAZAcAABIjJzoH2hS5kB3YY7bDIFxbW4sRFSWjGklJSZjnEMAnwLUoCheqjR6A/oG6IS8GEgwAaWlpeIVIdFAMIeheCKOeQBcdET/h448/xm9E9RCDV0ijUqnI6Xw7r3fiQrKi6OlkM6H2ZJMhZnXbkS2IGMQjDWYUxCCMDosesNLEpJiAlGQJZBayTGRBz0AjkuIJsiMNLmRHSjzigqwBdAE2JjmUTEooK+IMAiuFk69W6klKTKQ8gg/hjux4S36avFaqRBaCGHQ+fAuQk6WRafB25YvbhuIWQLgNdQU8gArX5iIfmg9NCcloG9qRFHq34UOvbN6dAeErf8Y/coI1EJZV2Hdpx7XAGgjN6oZd2nEtsAZCC3/yvZJVMG1kT2bS7+kZ4xsS/Z6BOYGU77Umv6TC10BoFd17f5QtmjAJRszq2gJrU4GlyWZq2Iiy9bV6Xle2eOL9VeaXVPL2QWiTzrHjS3v7Oh4/WVh4OP/0h0dPf3j4Iv3w0+P7Dyc1vBqrcOqX1NDv77dsE4S5kilFeofnzYCBgV6LQWPKLZqamhx52TU6Oto/2KPm1WbvQvh6g+I2QZgjmchk9ft7xTmcLa0tjY1NzUPDwysIArbB59fQ0FBPX6eaW5MtnH5/PfeXVPI2QYgmy5POqeiuuvq6iYmJ0dGRgYEBqDZgQIBKBWv23t4+gIcL8V3dbVpBQ45w5pfU0O/vt2wfhDYZMRdCmdXV1eFyugYHh2RSKRSbMAjAmNDX2+dobWlqaenv7+/odLKSsvPli/mKuVzpVLZ4/P39/l9AydsEITEXUts9b/i52hxFhbkKvXFocAiKTeipYeGDWW5kZEijlKWkpNXUNQ0ODYSHR3hfojJjSyRpTRbhWKHyPrD8BTT3+/gJ2wQh5kI9a8DfKwEa7/b2tvrmlq6uzt7eXljyoPVva2vDY1NzS0N9fVNTM9g0IjQx6rY6JcQS6inyv8aM9lWr6e0AMmd3pfGCjLNNEKL32WSzakYblJm9vT3dXV0w4HV1dZEOFgg4nS6Ygts7cLU3NtfJGJV25aMCxTzG0izeYEZUwZ0rtKjbCnCkTT5rFY29j+68Q8vcTgjnmLFFxcX2psa60rJyGH5bW1vBf7gQcDy/AG1DY62CVZUjWpZIscYHlrnS6dRQq9elVEWGE4+7KK50uG2CEDMZ5sJb1283NNabDGq+WA52gwvFixfgrKuvkjMrckRrJNJs0XiRahH43fo6SZRSX6C8v4siieI2QYg5zMAZ8vdMKIctr7gwv8judDg2grC2vlLGKF8Hobu6YwWKuUx2D1CUpDXu8uK2QkjOhUqaCz5jNbUVcPQqKS16KZWW220FVim9PEf80nXhWL58VsvsuvV1oo7VbZPtrh3fjQsxS+VIJl9KGymp5bQmSXqNNL12I5IQr+pM/OGNl4NjBcp5YUqd9yVKjngcsu4OFUO2qtpvP5DmiCfVtBEZZUBOHVxHiMxkjb2kcYX3MnnOTEGzXtCaKWjZkPgtJsEwJr+Nf+QY5sXkEHO4t7RQubBVbbFDy3lLCPOkGM26ywrDHC23Oxz+Hc6A7raATmeAq9kP5Gjxyc1KyeJMFSjuY6wjqUi5qKK3uVyOh4/vz9+fnp2fmnsZ3V+YuTc5qOHVvdJSgfWG/3UWJ77cPSm+RzPZB17420CIkVPHHPDzinm4+MXS0qmFyaOLk0dcDR8PDx1aWjq7tHRmaelku+uSx2UqJ66SE1+BVuYmVNAii309YvsHekqL8osr6+bn5iYnJ16kqamp0XuDGv6rLRVYZmSyez2/TcWoiyp94A39/qr3NhDmSaclKU7PW15PHny7tHSho/FQXdU+o+5PzY2Hl5YA6sWlpfO93Ve/POcT7qWM9dPE+Gni/HWB1/g3rnr39HSWFefbSytgnSD12riGh4dfsFQAwldbKqCvoYbnhXoKP7ThFLNMrng6RzydK5nOk86AEMAjSdbN5og3Hk7eBkK32eE+Mza/w/X53PyJ8dHPZqdOzk6emJk8MT9zan765Nz8Z6UFX/LiXSXax1jAkVSiecKOL6mtrRkfHx8ZHoY6Gwq2HvfV2dmJR6AIMwXu3T3tbnvhqyFETbDM8LvKYH9IwylEuUx2t4LeoKA3aditalarjuvU89uUjCYFvVHJaIGOaQtRfEsIUQOMXUpGpZxepGSWKBnF5F1BJ0hGK9SwGtH1Vo8eebI5KNhq62qHhgb7+/pgqYDvM3bAmEwm7E0BkH29vW4EB9o7HApmdYH8ARQCkIk2lWvQmaawusBwahaMfgDD6TjqbOZPmnQlbR3tXd19VmvOuXNn/+OjP4aGhvX3Dzud7fAl1rCd8GHYKtXEW0MIfh/PEc/liOdfRtBHQ5P585jgNvkO+HnGtbQ2ldjzM01WDJ9QkGLfEO7YNAS+NGiVGXRmc6urv78nIiwxKciszHABHjerzYPbNkLo+XAq+k8cTrEEypfPwSBj4A5G3pGx2WI4l+fklF68+MXly9i1cek3//ZvUqmutLQxJ9ce4pumZfZuVYd7FwjfYNQmFGxwvLjh19ICE29DUUUVeA7abfAf9iRATdPX24Ntg3nZuTW1Df19vTA23fgyMfqOKvgWP/AG566XhBph0zA6geVLl/OID7rJpUUVFqqwxthuJXiebBp9lB5d5HuVfuOLpFOffZFOw+4LU0RE6q9+9Styh80///N/vXzZUyIx8/kaL29PepR9qwTpbYLQrZ2Z4ySUQb2GGbCrsxNqbgyeMFPA3oQAHjEjAlRYKppbG5iJ1gLZIvo1umoWd0CYXJcQaAi4zgq5JeAnViM+b61eJlcyCbnU45tkKFHxdhtRJLRFmawe3yt0fD09wqZn90EODwtN4vCUfIH20OFj/+Nff/3f//XX/+cPf2AwZWyOMpXCjPQTQtjZfIJ4fQl2WyFU0hzYhOByOmAUhEUCF5TacL9AYI2loqlWxa3Nfa7mxhiFbk5afaHgBl8GXGdLKc0YNlfrgNCUigwH1KdZ3MHtUrwRli8YMq9/GRftqyIHfCx1bNJZSowuOoKRGCMIC6R8fvSrE8e/ueMVkxwnio1kR4UxtKyOdYLC6wP2YsptghDMBPcnX4/o6poqW7ZRIleRlgrSzEQGyAuP9Q3Vcmbly9TcYOUZCLei1Po732dE3VEBQqhen/McoXjjJVZ5fpti5A0B0ffNi+hSsGXe+Co+PiATn16Z29yqwQkjdxhkEdxDTYA03GjJGDN/DEuOd8FsXd5tghDzvDIDc6F/TW1VttWoN1udDidmxRcvMCX04DLGemPT6nqjRcCXScFG7+8oinTHaikGzAo1AsY0NaOjSLXw4mCVjeYTTL0+wRfypfpe4IT+hHk61EOIoXtdGrzdSHu85Y4H2wQhAMh3uz9l55qcbc1NLXUNTTUvpcbm2oqaIgm9dANLxbIMhTYCQjJqC3guPSIPKK40DdgUHjeIp4TnQguBwW2lfdH94Seu4pVrhdVaYZVG8EqqVPEqs/j9L6KIYqnhuTe/TjQLRtb59SCxkTuqyugGZTKJvOhwJv5yjJbRD47ceVyIGuOX4NdKmAVynk3G3Zh4Ngk7V8fpIEcbsBEybkDjbqFuHLJomKcIELp9MgizItgCzv8RPjLfKzRaVIGBO4DRDAxqkyxI2YU9/V0dXViz9fcNDPT09nX19HavIjz2DQz29Q9A14AELc5mJaveJp23rBJ0wX9KWtuVC1Gi1AaoatfjIZi06hrqa1qb6jqKbFUhATHXLvtwmbLWxu6aytaSwjqjsC9HvGXeXNvHhW4UxzEuvXJLCkY5YrgTjbm784g6o0tD63kpqWndWkYvykwLy/b+Lg0yDlgTWKK5IeUDMxW9Heo9iD8hHoKkYBM8qRLi07DLODYqITIqNSoiUSQ15+TgTJWSFbJaSiRirVxhEfDUGq0tJ7ckLCBFkd62wmroWxgkfS5T4wP1qxcGkIrxWKJ5xIqpysstWFr66ae//ZCekbb/wCeffnbU0+vm9Mzkjz89m5weSY3UWgSvUFm8PptuK4SvXy13ynHgp5eVldjrigvr7Pm1Rfk15cVNFSXNpUUNCNsLaosL6kqKao2ashw4OWY4IePE+KmhpgF45NCHdkcYAXl6Kzehyuf7tNi4BIOhkMVWpVO4ERHJTJZao7EplTkrpNHkRkUkBATFBQcncfl6o7EoINCfGm4j0UIvxECNbgEI0VfcBrUxfAVvVbS2tLvZkd6qsye+y7VZ4PGMJRMOSMEefDjKfvLJJzivYXJysqu7MyDQLyOiaOetC98Qv3uQgIi5RJvb1tFd3+Boae1odXSK5Roqk2ey2OD/1tTc1tDobGvvybYWyiiOMt1TDKQpoRY0LhylsEwkRk7ZrHsQJvReGPFskvuM5CxtZrZOVwAyGOw6nU2lylGrc1eTRpOHR/KuVBlTIjTkBg9ghkmXcjfnyoVoDbOLXLrgK9A5gMth+QKji1IaInykarUWqvumpsYrV74PDg764ouLv/nN/4Tr18BAf0trQ5h/mobRA6590zZ5afoPlwuh0Q/0pGTQOKlJDE+fuxyeTizL8bnmefPchZhIqlJtS4xNu+kZLJVZ2RyJ17VwVkw5HDKKNQ/BGRjisNaOuqPkJlRiIiSWIoSKbr5Q9oBLyVZrLQq5RaHMViqtCoUVEK4msCMBsDYf+CFerjDoeK2FigduDd9EYlDW1QvREJfcCgQCv4zIfIhO7LgyfIXoNJiPBVNKsdVeUoDTE3DOzl/+8pff/va3ON4De/Ph9Gy2mDQsBybXrVrzfMAQiqZ9byakUujUNG5IWBKTn8WLTemK+ZeJ+P+S5/tnOiOTQhWmUnDOSSaDKbx+2TfMQ+pe9bPAiATPyWdZsSWQaMiJEHCmhmX7X2fGRCeazCXx0SneXkFXvveKTuJn6vKVBJzLhDOrKGkcGgOKPysiFcqs+FCZmt4F7R1cPTDjYsAEQ4OzARiMaH7XGBbh6OpREXyvY3fL0hvlGbBUuDK57QZBF+54BCloH4ql4g0UpG83XMAEocrojIpI5wk0HK6ayVYxkzPY0eGsuEhmdDgtXcjmqKCvAsXGpotTmkq1TyC7gxGxXsRYiuHOrl4s1T5GZ0ej85OqWXHld65QY6Lj9foCokCGNCggmkKTa9S54MXnlK1WWoODo297Btz0DJEr8/T6fP9A31OHb6ErQH/m1hTOkK6tkbflcDZHX8GYv+43EvZCCWEsdBOMhYS9cIW20NKE7364XEisyoXjCZHiqIiMmEhGTCQ9JpodHcsnKSbKHUPE02LCOVDHkOtCyIqYrjARwvUbDuDi1EZ42RCzoGwG93zpAuZChcqEERJTnU6Xr8ZQiUH1ZwitxKMyRyYxMMGIimylyhTqR5FSHOgf7iU8Ma1itMSKPvK2AkBu+VL9TXv8GgixWPmgCJ3XIhjHZgwDe3AjwlszH7LPGvswJi2sLrDG8LvGxJJRQmkGtNCBFcgeMFPNCpVRLjcLRXpMeypVNjBbR0AUQ6hKhdPzLGKpTsGoL1Qski0LcRT9A0ZmKNXccu9//q6rNRCqGK3vgRwbl+lQMwlSMQhaCbgfl2uiZjo1LJeGuTGxXEivY3e9aH4j3a4gaJCa8Vg/3e3vqdFRCdrMAj5HfuO6t29QNDVdBo6UycwrBNgQliusGGARFom14vTKYvVjYlOOZIIRbcemANiV3Ht0Zs28+2b+fQufuL8RIUs2sbrfArvYGgixTxOErX4gMrxCL415nWS9PfCvWF/U8id6CJMhDh/s7ibcLxDGKXZEauLPa1WDTI/NbEUFFYr0drv6AaE+lRLWu5XhCHMVBkA4SolTmwJuMCMj49SaPIFQx2BIk1JYdIYSOEmlpmWSmRUyU0w0NT6BmZDEFoqMSqU52C8hITALbAeehtsj3MnhmWcVTanZZRqhRCNUqAUK3DcnrUiZKSFIJ1ZqhHKVQJ7JdblRfFepYg2EUCph4QJ7HloG4Z+pv6+np3t1DJkM0CCwLtmamIH+7u4uaLJW53U3ew88LPp6u4vtBXn5NpxqWlpanGvLb3W6Skrs1TXVQ8NDBO69PS+Wv6YagwOo2Ni9Meykuf5dQHJwNiu2FAYpLavbPSkSIj4JJ6F+w3QoW6QnZUnleoLP5BBhMIqaJRLjzxBKTTKpMS42IzaOdjc8lcfH0aPZOHDP+zsq1ifoBxhIsZ7DPJ3JnDZqI4cG9nS2HWh3HujpOtjduSH1dB5qd+1vbtzb1LC3zYHEB7o696n4OquAUDu8I62BsK3NBXK1OUFkeIVcrhdiXjvZ+qLIjO1tMBdWlGOTU2lFFVz0y8vKyxqaGvNsuTALd3S2v2Y1UDj6RFl5MSCM989KCNRH+siDb/FgQ4i+owSiOlYPqT0BolgXZiQYpLJMsTiLmAiV2QAPEK4j7D6WSs2YEfFWIFKnRGQWKR4S9ufnuxvRLcy8B9bM6IHeve2OI66WI11tRztdG1J32xG7dY9e9pFK9ZEt7+OejqOd7fv1YmOu+JHbFeqdUFwDYb6tcJupsLC4qLC4sMBeWEAGimx5qEPRG1UD62WFVI8VCNb15BIeUj6cbpgxxVgOAksgGuEjTw423/6eEhERq1SYU1K5QYFRHt53MZDKpCYgupqkEuPzRyNPoFRzmgrkC4ANPE1wIbHfeDwhsEDEuzzYexj4tTYd6XAebXcsU1vr0XWEt+VF+yqK95fZ99mL9gFsoJgUEyJOacewv5UQ8hPqdyJx42qg717XFmhx0jqBERWLRZgUeIk1Qbc44XdjoJRJSWL6+UeERlDYbI2bBZchFIkMQmEmh6uRiLMQFomy+EJ1VAA/izuMQlhxpXDngWEk+Kbo5DEPm+36owdwujw9N3nq4f2zD+bOgBZnX04P5s8+Wjj76P7Zh/NnF+dOP1o8n5J6JdxHa1c/tAjmTdx5M2/e9KbEvW8Vzq7hwopiJ6jSff+Z7A7ErItcjrE7Nktmd1SVuGrK2qtL2xBYudeWdxClrcr7WqW567AuI1nbqlKHRdX8Uis/2cEBJwAGDxXKH9ASswRijXucJCZCsdgA/Q6PpxMK9UK+FswnEmjvhqdwuDo3nAak8fW//e3pUAgy8K6AxkfD7AQjsmJcBdm3hrsO9PafeLZwpiT/48a6w41VB4eHTy4tfbX0/77YjP4Ob+mz9ORYLX3cxB9R8dQ6iVBDyL6vIOxqz5RKDHIp7joklvDV3Pw1EE7PTIAmp+6RgWWaJWKmpsdXR07NjBPJZjdLNjs3hTNk4MvkbHMMDPZ2djoHhgcGh/udbS1Eaavyvk5p+DpyrfvozOzk+MTooycLWVmGWH+d2wljs3kFMFPidAKRisfTcLlakRB8pmexNJ9+HnL0WIBPAEshN4lFehpNAkYEqAKBni9Qhdym6pi95Cjqlo8msRzUM+cbK+6OD+wdHT3x7P6p8mJMikc7mg9PTgDCL5YA0iZEOLx/ivVprugnWUZjXc3Jwb69Ha79EIggFm1EvV0HMYM6WvY21n/sbN3X3XlgeHBPniVgDYSkDxJcH1ackcjAipPLSjzptrR5Mjil1dXWmMwmi8UKLzzi/wrU1uM/DcBlDQfNrHZ5ep3S8C0kQ01e/CiWIUaz9vqlILehf8O1NlYCSSGGkNAIiVh/2yvg2g3fGx5BcfGczMycg4cC/tuvL/6vU6oz3hohXw1eFAoy+XwdGJTFkcrotZgLV3cOQJjJnMk3h8wvHJmbOjE9/vnDhVOLcwQtzJxEzBxc2jehGXi+H9QK5DnCZ3JaY1316d7OQ66Ww5gyN5GJeruOVdn35un+rJD80WL5a2P94cHefTZL4BoI6xurt5YaGmtQIDZeY+NubX1VY1NtVU1ZSVkRXC628EMOVwOfK+HEVkMHtgkX5hOuEjnBQRESiSE5gZGQQA+9m5RGEctkxuQk/r//0e9f/nf0n0+ligRKYlAVYHTV8viZTJaYm1KCpf3KFi0ESGWbAT4czFIVq1zFLAMpmaVKRqmCUUIQnaRl9/Z1ATm9WE6zZ/H686TzSkZzdcWpno5DjqbDEIIIVnYe63guGa2ISAh0uo7VVx6ATFRbcaC4cG9z45H+7hcglNDK3gOVS2grVIbtuzjNYmu/Isoo1rCc8M1Z7RvxMizHbNL7GQlZHJ4CkxymOrHYKBDoOByNXJ4VFSf85HDo1VvJUrEuJDDcwyuMydYI+DoeX+3nE54cbBEk1cCxChu1sEAUJNcKkmskaa0ySqcyo0dN79cxhwzsMRNvwiqcgXt7nmTBJoN4/LhQ8YQg5ZMi5dPn9KxI+cyuelaoXCzWPOUmlvb3nHu4SIhF96dPP14499AtE0HqeTB3FkLQzzR3BkITZKIni+ceu8Wix49OFOV6r+FCg7hlC8kodayQSebMkrSSj1v4CRSVRdS5OUvU9jrSOebClCglIORyYf3QcDmYEQkCiiKhTiICZmrAFh2RHAJfXq6Wx9UKBNo7t/3hKgdfZBjrCfJVQ8GN5QosWZBxoIOFyhv2LKjxIKxiDRN0k4cwImHHgB861jNIDFGIzA4tD0mJQYagG2Ivjzv3J77F1rAnTy5M9n/WUnmgqnh/Y82hH55hNt1UJoLEtHShuvLaGggnp8empu/h7qaVgPtxioxcoXtkzKr0q5MReYdH+4dH+geHeodG+voGusYnRxEzMjowhT2gRN7V5S+Xtqb85Y9uVg18HcXOL0yVV5TDlWFzD+BCzIXB+qCgEL4gUyDIjIxIunThVkQUDWEORw1yY6lmc9SYApcjuRoaQ5QakWVXEYfgrBCMHlCa58seZwsf54hwf2jhL5p497M4c3rWNORMVcaInDIgSekRJnXyElycOAcrppkR1QDKCK8hiR1XnRKSe8crbGbsS1fLoSePL4x0Ha8o2ddQe6i99dgPTy8u/XRx6cdNael8eenlddoZ4hQY0s8a5/iQh8KQF4SJ1Y94C7ECyVZHrk7W3uYqg9eL3Y6NLzk52VlZxsrq2uxsK3bAQMxB3tXlu0trRfxKaYgh5Z3XqQYUcbV1Vde/99Ey4Bm2oTdDvnw+IzIvMOAuj6/lctRUCj82Mj0lhQ/k2GzVasIsSEYC0XSaQE6vL5CvOSMFCjYTf1zF0+sVjEwpO1PK0cs4ejlJXANIwctS8LOUfKNSQJBKaNaIrFpxtk6Mu1ktMqn5BmGNXfWThFI9OXYOQuxPj88v/XhhaelLgsB/r8QP6C6dqSr2WQthu6MN1OG+r6MXIxHz0kh3Rmwww+IB7r7QXuI0p/qGWqerFSeWVFaVtXc6N8m45rsbl/9zsg5nX39XXr412IsBH+pNrT9jsBdmxBsYLDEJD6DCncVSriJgqYyPoycn8sCOSEaji0Ju0+CUDeuVm8sJiZfYmJcxVJR/ZWRoT1f7/q6O/b3dBzah/p4DHW37Whr3NNTtcbXu7es+MDz0V4MyxcR9rKDXTt0DhBd+fHz+7z9ceAXbrWPKpdMNFb5rINQqcraQdMpcUKYqD6RX2RDWq22gN/1EprJgczKoC+R8m0X46tMvsO00/q6UyZIw6Ng/RgyeAInJxP+JWSElm63wugWntWQuT8tkKrlctfdtz2/PhMb76yDIwF4PjQ8WiJmsicLcq/09+9taj4A2WQzgFdYDpbkfW1R/Usj+w2rd42w92t+z16ikZAt/ktGqpu5ha/tbQlhfsZYLDax7HwaN6FlDKyROaxCmVYrSqkASKg48qZNl1ONOxoAEqRXYm/Ki98M6obRQsZAYrAsIDGYzpdeueHj5hHt7h4SEpkKuWYuiHExJxiCQQROG+NBUtE7gB8kF288ghgiS6oI8hNnmC24d6VEQsRIAuXAnwp3uRywDyPju9uNYD9SUH6irPFhq39fmODbUd5jNuEa5W61m1k9PYIP7p3//8djS348vLX32JnSovvLKGi7UcJrejqAI1nCbtNzmZeI1a3nNKAqPb1qgit1gEQ278RiHLR7GuWJ7RU8fDintamvvrK2rLyktKywqIk5xa+vo6OzuBPV0WvSlRu4rVP5YydGjC/z9wul0cUw0JS6ecds76I5fPKY9BkO+mkj8EIN7GpUjTq8uUjyA6gf8B7sHPGjCPGQXzt5sd119uHhyYfYMFgMP7p9ZhNAPQX/hHKkIhb50ZpzQnT6CUnT2DKFHXTj39OH5pw/OPcbC4PEZlery7atsuEnoJSyzJs2kpFrUb0YmdbJOoFsD4cjo0NvR6Njw4BAMh7Ay9sKZHU7uvf09o/eGcb7FyOjg65c5PDJwb2JQxLSaeYQLr131MO2uRa02ajUWlSbHYimx5RfBQIj/WajR6LKyCrVqk0JlLi6po6eLufGvWNpj1QglS3pcVgZdiFGUnA7BZ3S67KUQIh4QpqaxGXE2HMu4om6FOIozBOhRtY76rxx1eyemzty/d9JVeail4VBBzp6JqbNzQ58X5O8d7vzUUXe4rvJAWeFeGCjKivdPjJ8mRJW/fUHQ0lmNxFecPIC1kIm3mMVZNHKI+5sSVORrICRt6BACcToowriwbbO9ox2Ry6862smNnORLpCRfwTLf3ET8376CAsJ+C1E0N8/W0NRssZjhS4k0L82FeGwIxS41shBc+Na9e2MsNv3SuRAYyu9cZn536YpEqgnwDb/tHwvPa7M5x8/PFxrRkpIyCkUY5H/XwztcLLakUameV8M2V7C5/ammYoKFgJCAjY4TbLkUqhjh1QRofX0Cg8PS2CwloKXRxN4egenhNjDx8z0bhDijog33t38/OnDw4cMzD6c/dzUcHBs83tN5eHbm5MzIp93tRwa6joI1Z+596mg52OlA/Kmlv53HnPecPrNnJxjYi69SR7zalLgGwvZ2HArqanPfV4h47HA/dmz6qs3R6sBZ2/ivZ7XYUN/QWNfc0pRfkFdbV41usL5AsvwXCmzvaMPx+Gmp1DBPsTStWU51hvowKBQOFgBoawgXGRlM/K+8x48fms3WhAT42WKukvL4uvC7SVjz5W2q5oZnW0KQ1tfP3w2MlM2SX/nOIyySBlbD4yqShIXERURm0BlyQAuVt7eXH3aeYs0OBQ3pL+o++Wqown5jcurU2ODpsaGz0xPnIVhOj5+fHD03MXZuBoGxcxOjZ6fvnZudOD+Dt2PnxkfO3hteprGxYyYVTlfaaqu9KSv3LcmAjHlmY57FZAOZjeQdj/kWo81EvH09MuQasyxiWjE8JMidvRpmR1R0KviGms5Lo3Jj49MSklLjE1MjoxNTUlmUdB4oLZ0dG8nKITYCbtZnwUbMWPsdn1AaXZqRIaHTpRHhyQmJHATwuJrQVwAzYoBrUjIjNdxYqnkKicnrUhrOmiZPYIRoigM8cJIcZCuQ/E2IyJJeq+dgFbsFu9TWcCF8lreWNG9RIK0LizByeYc79pilx5pSozVpMToQJTYzLSYzJUpLicnEZmgyMiVKxUkqeuXWWeKMb/kDaqwhlcJJTxeD8I8n6TQpGV5NJH6IwT0hkSaiVhUoiEUhNtfB9x62X3KXk/tkIHjpw/w0C2+2NyMJXFKJ3VvvaLJf7wpMbLv6AGi1wYjYTCudy5PMbkpzr7N13b01bjI8gJNG5VGpIoIowrQ0AZUqXn4kIsUZ6SLfO+FxiZyMDALX5BSWn0eygTMIjsFyEM4c7rP7tmAAXAve2/ujfrje3O/ePdevC5UL8UEanzt30qliiEKALTmJFXI3NT1dgsfnBFz53j5hicm8dBJmquimxw0cEwYVq/vApAlsO8XSYotOjcGAPJnFntWzZgzu+xvSrFU4/Q8EoU0+x44r9fYIoqYvY0NJEyQlc6npq7mQeEWOogjgnpBID/KkWYmxnZi3wIg4RBNWiy1hRAzFWnaLXpFq0iZlqZKNmpTNSJ1i1qZYM1Oz9akWXYpJg/QJGi72oi79E3khtOUd/4MqEOI79pglhWvDIuOiYyigmFhqbByVDK+mmNjlRyQIDo3hp1a4WXDZDcfA6cdeVGKqfu4hgECOe9cL7i8lckPMi/rbbNF9GdPS2bEPzoyd7XuhrtuEBvr2t7s+aar7S03Vnx0tH/f37hsZ/otRRf0HgpBUT+OAO2Z8ASuxiP0axEooZCfajbzB1cclgP9g/0uPyIfimxBNRePYV6yktSjozSAlvYXYZcDCPgKnikFEKt3xClrzi0cdA0I50+psPdzpOuJsPkLo5zam3s7jJYSi9c8K+f81W/a4HEf7evYblRn/WBCixYFivgymvrnXp3XHXaAEA7cfoilmROJAI/GMmtNQU1uH86taW1yNja0lJeXFxeV2e2ldXVNLK4x3OGHH1djUqBXUrnOzyxEvqDh5ztZDcCt1Nh3paj8ObWpXG6Fc7Wojwz/H9HQeb6o9VF99qLnuUGX5AYDd17PPoqH/o0H4amXH6wz+WGLi+CKcbsNPqskWTadFawuLSgyG3PzCmtzc4oaGevxzdQolLcuYa7fXGPS5+QXVpWU1lDgFjooA6sQ2ORiNFfDPeMRIFCzOnYRnKRwsoFmFuhVq1WePzj9dPIcw9K6Eb+rcmR+fXIBDBlwxfnxM2DRgXHz28NwPz06pxeG7EL4dqMS/W8A51Xe9pN+cDvYPCITHxjdfX0tMFYpFWj6fl5aWZrcXcThyOk189ert+GSeVGKKiIz47nxI9B11uLcEBK/iy+cS4uI9FsfOlpXs+/HJxXzzX83mPSOjp2DvzTP+Od/6SVX5vuysPY21h0psn5Tn72tqOkI4qZJaVkLRelGrvb4L4dtBSJxuAw019p+Kkht8vSJZbDmWJXS6nMOBiYqZkpJUU1OVQeNjnyl22NAZCh5fE+gbnRpmxckc2KoPkqc70sPL4yKDH82e7u0+/sPjCz3OoxUVB8bHTj1ZONPuPOJqPjrS91lr/ZHBvs8HOo7XVx3s6vp06W9f/mwWXrogE+9C+G5bUgCkXfmQHp+bmJJOY0gyaCIKlZuSmh4ZHRcbn5SQlIEYBhPxghQKHRolWDyg2VmhfNlTDdf8w1PCe/iHR1CCw+vC7Qn+Ezjsq2UnjHWB1Yb7pRO2rNRdLnxrLlzOiKMPFfTW+HBxUpSMpMRIkDwhQpocLV+JjA8Xiqm1SLxmrhUuqLn6Z48/X/rbRQLCzZ2dXny7dCLfmLQGQjzsXjuxBZaX9rt/dnQL/H8vKf57xZJDFgAAAABJRU5ErkJggg==