Here is a quick rendering of some of the formations that are resulting as I’m trying to understand all the variation that is going on…
Here is a quick rendering of some of the formations that are resulting as I’m trying to understand all the variation that is going on…
→ Leave a CommentCategories: Joe McGrath
A number of variables are incorporated into the most recent set of scripts to allow for variations in such things as step height, maximum stepover, radius size, maximum height, etc. The formation can vary considerably when any of these variables are altered, so the code needs to be revised and streamlined to make sure it is clear what is causing what…
→ Leave a CommentCategories: Joe McGrath
Friendly Neighbor (Persp)Now that the tower formation is a bit sloppier, and approximates the dripping of the material a bit, a method of colonization can begin to be developed. In this version, material is dripped down from a source–the robot–at each individual formation. After a layer is deposited, the robot checks to see where its closest neighbor is and then drips down the next layer of material a bit closer to that neighbor. Thus, the formations rise up and begin to bridge towards each other in unexpected ways.
→ Leave a CommentCategories: Joe McGrath
Now that the drops can be made “goopier” the towers can begin to approximate growth in a more random way. The variation in each layer can begin to display a sloppier accumulation of material.
→ Leave a CommentCategories: Joe McGrath
In order to simulate the random drip, or deposition, of material, the initial shape had to be transformed into something irregular. A script was developed to take an intial shape–a circle, for example–and then divide the curve, randomly translate those points, and then redraw a curve through those modified points.
→ Leave a CommentCategories: Joe McGrath
In this version, the drops are still simulated from overhead along a path. Each layer of the stalagmite is randomly sized, but is scaled down somewhat from the next. There is also a minimum radius imposed on the formation so that when construction hits that point, the formation grows outward until it reaches a maximum radius.
→ Leave a CommentCategories: Joe McGrath
→ Leave a CommentCategories: Matthew Lutz
Tagged: trajectories
→ Leave a CommentCategories: Matthew Lutz
Tagged: aggregation, growth, rhinoscript
This iteration builds off the previous attempts, by simulating dripping from a path overhead. Each “stalagmite” is built one at a time. The drip size is random, but each successive drip is scaled smaller than the last.
→ Leave a CommentCategories: Joe McGrath
→ Leave a CommentCategories: Eduardo Mayoral
Tagged: columbia, Eduardo Mayoral, ncertainties, nylon, rubber, steel, tire, tire cmetery, tires
→ Leave a CommentCategories: Eduardo Mayoral
Tagged: balls, columbia, Eduardo Mayoral, ncertaninties, rubber, spheres, tire
→ Leave a CommentCategories: Eduardo Mayoral
Tagged: columbia, Eduardo Mayoral, ncertainties, script, tires
DRIPPING SPHERES
→ Leave a CommentCategories: Joe McGrath
Option Explicit
‘Script written by Ado
Call Main()
Sub Main()
Dim inLayer
inLayer = Rhino.GetString(“Introduce new Layers?”,”yes”,array(“yes”,”no”))
If inLayer = “yes” Then
Call AddLayers
End If
Dim arrPtSeed : arrPtSeed = Rhino.GetObject(“Base Point”,1)
arrPtSeed = Rhino.PointCoordinates(arrPtSeed)
Dim n : n = Rhino.GetInteger(“nr of points”, 10)
” SPEED:
’Dim bbox : bbox = Rhino.BoundingBox(strSrf)
Dim min : min = -500 ‘Rhino.Distance(bbox(0),bbox(6))/8
Dim max : max = 200 ‘Rhino.Distance(bbox(0),bbox(6))/4
Dim Density : Density = 2
Dim i, j, k : k = 1 : i = 0
Dim arrPt, arrLines()
Dim arrPtsCollect()
ReDim Preserve arrPtsCollect(0)
arrPtsCollect(0) = arrPtSeed
Do Until k = n+1
arrPt = array(arrPtSeed(0)+arbitraryValue(min, max),arrPtSeed(1) + arbitraryValue(min, max),arrPtSeed(2)- abs(1/2*arbitraryValue(min, max)))
Dim arrPtNeighBor : arrPtneighbor = shortestPt(arrPtsCollect, arrPt)
If arrPtneighbor(2) < min/2 Then
arrPtneighbor(2)=0
End If
ReDim Preserve arrLines(k-1)
arrLines(k-1) = Rhino.AddLine(arrPt, arrPtNeighBor)
ReDim Preserve arrPtsCollect(k)
arrPtsCollect(k) = arrPt
k = k + 1
Loop
Dim arrPoly : arrPoly = Rhino.JoinCurves(arrLines,True)
Rhino.Print “From ” & Ubound(arrLines)+1 & ” segments ” & Ubound(arrPoly)+1 & ” polylines were extracted. Segments erased”
For j=0 To Ubound(arrPoly)-1
Dim StrtPt, EndPt
StrtPt = Rhino.CurveStartPoint(arrPoly(j))
EndPt = Rhino.CurveEndPoint(arrPoly(j))
Dim strtvl, endvl, endvllength
’sometimes complains it does not find a string!!!
If StrtPt(2)<>0 Then
strtvl = Rhino.AddLine (StrtPt,array(StrtPt(0),StrtPt(1),0))
End If
If EndPt(2)<>0 Then
endvl = Rhino.AddLine (EndPt, array(EndPt(0),EndPt(1),0))
endvllength= Rhino.CurveLength(endvl)
Rhino.Print endvl
End If
If Not IsNull(strtvl) Then
ReDim arrPolyfinal(j)
’—————————————————————
’arrPolyfinal is a temp array to store the result, since the method joinCurves returns an array… this way we can avoid having nested arrays.
arrPolyfinal(j) = Rhino.JoinCurves(array(arrPoly(j),strtvl),True)
arrPoly(j) = arrPolyfinal(j)(0)
Rhino.Print “so far, index j is ” & j
If endvllength > Rhino.UnitRelativeTolerance Then
If Not IsNull(endvl) And IsCurve(arrPoly(j)) Or IsPolyCurve(arrPoly(j)) Or IsPolyline(arrPoly(j)) Then
ReDim arrPolyfinal(j)
arrPolyfinal(j) = Rhino.JoinCurves(array(arrPoly(j),endvl) ,True)
arrPoly(j) = arrPolyfinal(j)(0)
End If
End If
Else
If Not IsNull(endvl) Then
arrPolyfinal(j) = Rhino.JoinCurves(array(arrPoly(j),endvl) ,True)
arrPoly(j) = arrPolyfinal(j)(0)
End If
End If
Dim Length
Length = Rhino.CurveLength(arrPoly(j))
If Length < max/density Then
Rhino.DeleteObject(arrPoly(j))
j=j-1
End If
Dim hl
’Add a (horizontal) line between end and start points
StrtPt = Rhino.CurveStartPoint(arrPoly(j))
EndPt = Rhino.CurveEndPoint(arrPoly(j))
hl = Rhino.AddInterpCurve (array(StrtPt,EndPt))
’Add annotation text
Dim txt1: txt1 = Rhino.AddText (“Curve: ” & j & “, (StrtPoint).” & vbCrLf & “Length: ” & Length,StrtPt,CInt(Length/75),”Verdana”)
Dim txt2: txt2 = Rhino.AddText (“Curve: ” & j & “, (StrtPoint).” & vbCrLf & “Length: ” & Length,EndPt,CInt(Length/75),”Verdana”)
’Change layers
Rhino.ObjectLayer hl,”annotations”
Next
Rhino.ObjectLayer arrPoly,”Polylines”
End Sub
Function shortestPt(arrPtsCollection, arrPtTest)
Dim i
Dim dblDistMin : dblDistMin = 100000000
For i = 0 To UBound(arrPtsCollection)
Dim dblDist : dblDist = rhino.Distance(arrPtTest, arrPtsCollection(i))
If dbldist <> 0 Then
If dblDist < dblDistMin Then
dblDistMin = dblDist
shortestPt = arrPtsCollection(i)
End If
End If
Next
End Function
Function arbitraryValue(min, max)
Randomize
arbitraryValue = Int((max – min + 1) * Rnd + min)
End Function
Function AddLayers
If Not IsLayer(“Script”) Then
Rhino.AddLayer “Script”,RGB(0, 0, 0),True,False
End If
If Not IsLayer(“Polylines”) Then
Rhino.AddLayer “Polylines”,RGB(128, 0, 128),True,False,”Script”
Rhino.LayerLinetype “Polylines”, “Continuous”
End If
If Not IsLayer(“Points”) Then
Rhino.AddLayer “Points”,RGB(0, 0, 0),True,False,”Script”
Rhino.LayerLinetype “Polylines”, “Continuous”
End If
If Not IsLayer(“Annotations”) Then
Rhino.AddLayer “Annotations”,RGB(128, 128, 128),True,False,”Script”
Rhino.LayerLinetype “Polylines”, “Dots”
End If
If Not IsLayer(“Helix”) Then
Rhino.AddLayer “Helix”,RGB(128, 128, 128),True,False,”Script”
Rhino.LayerLinetype “Polylines”, “Dashed”
End If
End Function
<br>
<hr>
→ Leave a CommentCategories: Adolfo Nadal
Option Explicit
‘Script written by Ado
Call Main()
Sub Main()
‘Dim strSrf : strSrf = Rhino.GetObject(“closed surface”,16)
Dim arrPtSeed : arrPtSeed = Rhino.GetObject(“Base Point”,1)
arrPtSeed = Rhino.PointCoordinates(arrPtSeed)
Dim n : n = 1000 ‘Rhino.GetInteger(“nr of points”, 10)
” SPEED:
‘Dim bbox : bbox = Rhino.BoundingBox(strSrf)
Dim min : min = -500 ‘Rhino.Distance(bbox(0),bbox(6))/8
Dim max : max = 500′ Rhino.Distance(bbox(0),bbox(6))/4
Dim i, k : k = 1 : i = 0
Dim arrPt
Dim arrPtsCollect()
ReDim Preserve arrPtsCollect(0)
arrPtsCollect(0) = arrPtSeed
Do Until k = n+1
arrPt = array(arrPtSeed(0)+arbitraryValue(min, max),_
arrPtSeed(1) + arbitraryValue(min, max),_
arrPtSeed(2)- abs(arbitraryValue(min, max)))
Dim arrPtNeighBor : arrPtneighbor = shortestPt(arrPtsCollect, arrPt)
Call rhino.AddLine(arrPt, arrPtNeighBor)
ReDim Preserve arrPtsCollect(k)
arrPtsCollect(k) = arrPt
k = k + 1
Loop
Dim strCrv : strCrv = rhino.AddInterpCurve(arrPtsCollect)
Call rhino.ObjectColor(strcrv, vbred)
End Sub
Function shortestPt(arrPtsCollection, arrPtTest)
Dim i
Dim dblDistMin : dblDistMin = 100000000
For i = 0 To UBound(arrPtsCollection)
Dim dblDist : dblDist = rhino.Distance(arrPtTest, arrPtsCollection(i))
If dbldist 0 Then
If dblDist < dblDistMin Then
dblDistMin = dblDist
shortestPt = arrPtsCollection(i)
End If
End If
Next
End Function
One more of the series… this one is almost working… i guess what i wanted is to have different possibilities to explore boundary populations, starting from surfaces to go to closed lines and finally redefine those conditions in the polysurfaces.
→ Leave a CommentCategories: Adolfo Nadal
Option Explicit
‘Script written by
‘Script copyrighted by
‘Script version domingo, 05 de octubre de 2008 20:28:50
Call Main()
Sub Main()
Dim strCrv, bbox, strBBCrv
strCrv = Rhino.GetObject(“Curve”, 4)
If isNull (strCrv) Then Exit Sub
bbox = Rhino.BoundingBox(strCrv)
strBBCrv = Rhino.AddPolyline (array(bbox(0),bbox(1),bbox(2),bbox(3),bbox(0)))
Dim radius, centBBPt, centPtCrv
centBBPt = Rhino.CurveAreaCentroid(strBBCrv)(0)
centPtCrv = Rhino.CurveAreaCentroid(strCrv)(0)
radius = Rhino.Distance(centBBPt,bbox(0))
Rhino.Print “radius” & radius
Dim arrItems, arrBoolean, blnVal
arrItems = array(“Stepmode”,”Steps”,”Width”)
arrBoolean = Rhino.GetBoolean(“Select mode of population”,arrItems,array(True))
Dim steps, width, n
For Each blnVal In arrBoolean
If blnVal = True Then
steps = Rhino.GetInteger(“Number of steps for machine”,10)
n = steps
Else
width = Rhino.GetReal(“Width of the machine”)
n = CInt(radius/width)
End If
Rhino.Print n
Next
Dim Rad, crvDomain, t, m, i, p, crvCurvature
Dim crvPt()
‘Rhino.AddLine centBBPt,array((bbox(0)(0)+bbox(1)(0))/2,(bbox(0)(1)+bbox(1)(1))/2 ,(bbox(0)(2)+bbox(1)(2))/2 )
Rad = Rhino.AddLine(centBBPt,bbox(0))
Dim arrPlane, circ(), arrPts(),arrPtsCoord(), arrPtsCrv(), a, arrCCX()
arrPlane = Rhino.PlaneFromFrame(centBBPt,array(1,0,0),array(0,1,0))
m=-1
crvDomain = Rhino.CurveDomain(Rad)
For t = crvDomain(0) To crvDomain(1)+1e-9 Step (crvDomain(1)-crvDomain(0))/n
m=m+1
crvCurvature = Rhino.CurveCurvature(Rad, t)
If isNull (crvCurvature) Then
ReDim Preserve crvPt(m)
crvPt(m) = Rhino.EvaluateCurve (Rad,t)
‘——————————————————————
‘IS THERE ANY WAY OF NOT REPEATING ALL THESE???
radius = CDbl(Rhino.Distance(centBBPt,crvPt(m)))
If radius < 1 Then
radius = 1
End If
Rhino.Print “radius :” & radius
p = -1
For a=0 To 2*PI +1e-9 Step PI/8
p = p+1
ReDim Preserve arrPts(p)
arrPts(p) = Rhino.AddPoint(array(radius*sin(a)+centPtCrv(0),radius*cos(a)+centPtCrv(1),centPtCrv(2)))
ReDim Preserve arrPtsCoord(p)
arrPtsCoord(p) = Rhino.PointCoordinates(arrPts(p))
Next
Rhino.DeleteObjects arrPts
Rhino.AddPoint crvPt(m)
ReDim Preserve arrPtsCrv(m)
arrPtsCrv(m) = arrPtsCoord
ReDim Preserve circ(m)
circ(m) = Rhino.AddInterpCurve (arrPtsCrv(m))
Rhino.ObjectColor circ(m),ParamColor(t)
ReDim Preserve arrCCX(m)
arrCCX(m) = Rhino.CurveCurveIntersection(circ(m),strCrv)
If isArray(arrCCX(m)) Then
Call Rhino.Print (“curves intersect”)
For i = 0 To UBound(arrCCX(m))
Dim strText
If arrCCX(m)(i,0) = 1 Then
Call Rhino.AddPoint (arrCCX(m)(i,1))
strtext = Rhino.AddText (“Point: ” & m+i & “Crv: ” & m & ” Intr: ” & i, arrCCX(m)(i,1),.5)
Rhino.ObjectColor strtext,ParamColor(t)
Else
Call Rhino.Print (“no intersections”)
End If
Next
End If
‘——————————————————————
Else
ReDim Preserve crvPt(m)
crvPt(m) = crvCurvature(0)
‘——————————————————————
‘IS THERE ANY WAY OF NOT REPEATING ALL THESE???
ReDim Preserve circ(m)
circ(m) = Rhino.AddCircle(arrPlane,Rhino.Distance(centBBPt,crvPt(m)))
Rhino.AddPoint crvPt(m)
ReDim Preserve arrCCX(m)
arrCCX (m) = Rhino.CurveCurveIntersection(circ(m),strCrv)
If isArray(arrCSX(m)) Then
Call Rhino.Print (“curves intersect: ” & “Circle: ” & m)
For i = 0 To UBound(arrCSX(m))
If arrCSX(i,0)(m) = 1 Then
Call Rhino.AddPoint (arrCSX(i,1)(m))
Else
Call Rhino.Print (“no intersections”)
End If
Next
End If
‘——————————————————————
End If
Next
End Sub
Function ParamColor(t)
Dim RedComponent : RedComponent = 255 * Abs(t)
If RedComponent <0 Then RedComponent=0
If RedComponent <255 Then RedComponent=255
ParamColor = RedComponent + 0*256 + (255-RedComponent)*65536
Rhino.Print ParamColor
End Function
Function ObtenerRGB(ByVal Color,ByVal Rojo,ByVal Verde,ByVal Azul)
Azul = (Color And 16711680) / 65536
Verde = (Color And 65280) / 256
Rojo = Color And 255
End Function
→ Leave a CommentCategories: Adolfo Nadal
Option Explicit
‘Script written by Ado
‘Script copyrighted by archi.o.logies
‘Script version Monday, September 29, 2008 2:37:08 PM
‘WHAT THE HELL IS GOING ON WITH THIS VARIABLE DECLARATION?
‘Dim arrPtPoly()
Call Main()
Sub Main()
Dim inPt,inPtCoord, newPt
Dim arrPt()
Dim boud, boudbox, speed, radius
Dim n, j
Dim arrPtCoord()
Dim arrLines()
Dim arrPtPoly()
inPt = Rhino.GetObject(“Please pick initial point”,1,True)
If IsNull (inPt) Then Exit Sub
inPtCoord = Rhino.PointCoordinates(inPt)
n = Rhino.GetInteger(“Nr of iterations”,5,5)
boud = Rhino.GetObject(“please select boundary object”)
boudbox = Rhino.BoundingBox(boud)
speed = Rhino.GetInteger(“Speed”,5,5,10)
radius = Rhino.Distance(boudbox(0),boudbox(6))/speed
For j = 0 To n-1
Call RndPt (inPt, radius,j, n, boud, arrPtPoly)
Next
Rhino.Print(“i am so far2″)
‘——————————————————
‘QUESTION FOR MARK: HOW NOT TO HAVE AN ERROR HERE?????????
Rhino.AddPolyline(arrPtPoly)
‘——————————————————
End Sub
Function RndPt (inPt,radius,i,n, boud, arrPtPoly)
Dim inPtCoord, k
Dim alpha0, alpha1, alpha2, min
Dim Line
Dim intobjectType, strLayername
min = -radius
inPtCoord = Rhino.PointCoordinates(inPt)
alpha0 = arbitraryValue(min, radius)
alpha1 = arbitraryValue(min, radius)
alpha2 = arbitraryValue(min, radius)
‘Rhino.AddPoint array(0,0,inPtCoord(0))
ReDim Preserve arrPt(i)
arrPt(i) = Rhino.AddPoint (array(inPtCoord(0)+alpha0,inPtCoord(1)+alpha1,inPtCoord(2)))
ReDim Preserve arrPtPoly(i)
arrPtPoly(i) = Rhino.PointCoordinates(arrPt(i))
Rhino.Print Pt2Str(arrPtPoly(i))
If i>0 Then
k=i-1
‘——————————————————
‘MARK: HERE IT DOES NOT MAKE LINE BETWEEN 1ST AND 2ND POINTS
ReDim Preserve arrLines(k)
arrLines(k) = Rhino.AddLine (arrPtPoly(i), arrPtPoly(i-1))
‘——————————————————
‘USE CASES to call funtions according to objecttype(boud)
intObjectType = Rhino.ObjectType(boud)
Select Case intobjectType
Case 1, 2
strLayername = “Points”
inPt = arrPt(i)
Case 4
strLayername = “Curves”
inPt = arrPt(i)
Case 8
strLayername = “Surfaces”
inPt = arrPt(i)
Case 16
Call CSX (arrLines(k),boud, i, inPt, arrPt(i))
’strLayername = “PolySurfaces”
Case 32
strLayername = “Meshes”
inPt = arrPt(i)
Case Else
strLayername = “Not suported object type, please enter (poly)surface/s”
End Select
If i = (n-1) Then
Rhino.Print(“i am so far 1…”)
Rhino.Print(“n is: ” & n & ” ||| i is :” & i)
‘Poly = Rhino.AddInterpCurve (arrPt)
End If
End If
‘inPt = arrPt(i)
End Function
Function arbitraryValue(min, max)
Randomize
arbitraryValue = Int((max – min + 1) * Rnd + min)
End Function
Function CSX (arrLines,boud,i,inPt, Pt)
Dim arrSrf
Dim arrCSX()
Dim l, m
Dim newPt
arrSrf = Rhino.ExplodePolysurfaces(boud,True)
If IsArray (arrSrf) Then
‘——————————————————
‘MARK: WHY DOES IT ONLY DO IT WITH THE FIRST SURFACE…????
For l=0 To Ubound(arrSrf)
ReDim Preserve arrCSX(l)
arrCSX(l) = Rhino.CurveSurfaceIntersection(arrLines, arrSrf(l))
If Not IsArray(arrCSX(l)) Then
Rhino.Print “Curve and surface ” & l & ” do not intersect.”
boud = Rhino.JoinSurfaces(arrSrf)
Rhino.DeleteObjects(arrsrf)
inPt = Pt
Rhino.AddText “Point number ” & i & “.” & vbCrLf & “ID: ” & inPt & “.” & vbCrLf & “Coordinates: ” & Pt2Str(Rhino.PointCoordinates(Pt)),Rhino.PointCoordinates(Pt),0.5,”arial”
Exit Function
Else
‘if the object intersects with the surface, then tell and do new point on surface instead of the calculated one
For m = 0 To UBound(arrCSX(l))
If arrCSX(l)(m,0) = 1 Then
Rhino.Print “Point”
Rhino.Print “Intersection point on curve: ” & Rhino.Pt2Str(arrCSX(l)(m,1))
Rhino.Print “Intersection point on surface: ” & Rhino.Pt2Str(arrCSX(l)(m,3))
Rhino.Print “Curve parameter: ” & CStr(arrCSX(l)(m,5))
Rhino.Print “Surface parameter: ” & CStr(arrCSX(l)(m,7)) & “,” & CStr(arrCSX(l)(m,8))
‘here we assign the new point to the variable for the line to be further made
newPt = Rhino.AddPoint (arrCSX(l)(m,1))
Else
Rhino.Print “Overlap”
Rhino.Print “Intersection start point on curve: ” & Rhino.Pt2Str(arrCSX(l)(m,1))
Rhino.Print “Intersection end point on curve: ” & Rhino.Pt2Str(arrCSX(l)(m,2))
Rhino.Print “Intersection start point on surface: ” & Rhino.Pt2Str(arrCSX(l)(m,3))
Rhino.Print “Intersection end point on surface: ” & Rhino.Pt2Str(arrCSX(l)(m,4))
Rhino.Print “Curve parameter range: ” & CStr(arrCSX(l)(i,5)) & ” to ” & CStr(arrCSX(l)(m,6))
Rhino.Print “Surface parameter range: ” & CStr(arrCSX(l)(i,7)) & “,” & CStr(arrCSX(l)(m,8)) & ” to ” & CStr(arrCSX(l)(m,9)) & “,” & CStr(arrCSX(l)(m,10))
End If
Pt = newPt
Next
End If
Next
End If
boud = Rhino.JoinSurfaces(arrSrf,True)
Rhino.DeleteObjects(arrsrf)
End Function
→ Leave a CommentCategories: Adolfo Nadal
Call Main()
Sub Main()
Dim strSrf : strSrf = Rhino.GetObject(“closed surface”,16)
Dim arrPtSeed : arrPtSeed = Rhino.GetObject(“Base Point”,1)
arrPtSeed = Rhino.PointCoordinates(arrPtSeed)
Dim n : n = 200 ‘Rhino.GetInteger(“nr of points”, 10)
” SPEED:
Dim bbox : bbox = Rhino.BoundingBox(strSrf)
Dim min : min = -50 ‘Rhino.Distance(bbox(0),bbox(6))/8
Dim max : max = 50′ Rhino.Distance(bbox(0),bbox(6))/4
Dim i, k : k = 1 : i = 0
Dim arrPt
Dim arrPtsCollect()
ReDim Preserve arrPtsCollect(0)
arrPtsCollect(0) = arrPtSeed
‘For i=0 To n-1
Do Until k = n+1
arrPt = array(arrPtSeed(0)+arbitraryValue(min, max),_
arrPtSeed(1) + arbitraryValue(min, max),_
arrPtSeed(2)+ arbitraryValue(min, max))
If Rhino.IsPointInSurface (strSrf, arrPt) then
ReDim Preserve arrPtsCollect(k)
arrPtsCollect(k) = arrPt
Call rhino.AddLine(arrPtsCollect(k-1), arrPtsCollect(k))
k = k + 1
i = 0
Else
i = i + 1
End If
If i = 100 Then Exit Sub
Loop
‘Next
Call rhino.AddPolyline(arrPtsCollect)
End Sub
Function arbitraryValue(min, max)
Randomize
arbitraryValue = Int((max – min + 1) * Rnd + min)
End Function
→ Leave a CommentCategories: Adolfo Nadal