Hi Andy,
Jarek posted a tool for distributing trees some years before (maybe you can found it at the old Rhino Forum Archive too). Attached two button scripts from this tool. one for placing random points on a surface and one for copy trees to the points.
Ciao,
Micha
-Runscript
(Option Explicit
’Script written and copyrighted by Jaroslaw Bieda
'Script version August 19, 2007 6:10:31 PM
Call RandomPointsOnSurf()
Sub RandomPointsOnSurf()
Dim strSurface, strSurfaceShrunk
Dim arrPoints()
Dim arrCurves, idCurve
Dim dblCrvDist : dblCrvDist=0
Dim arrDomU, arrDomV
Dim t(1), pt, strPoint
Dim a, m, j
Dim idDistTest
Dim intM : intM = 0 'level of point count match
Dim blnSkip : blnSkip = vbFalse 'skipping regenerating points while MinDist=0 and switching strMatch levels
strSurface = Rhino.GetObject("Select surface to generate random points on",8)
If IsNull(strSurface) Then Exit Sub
arrCurves=Rhino.GetObjects("Select edge curves ( ENTER if none )",4)
Dim l : l=1
If Not IsNull(arrCurves) Then l=0
Call Rhino.EnableRedraw(vbFalse) 'shrinking surface to speed up the process
strSurfaceShrunk=Rhino.CopyObject(strSurface)
If Rhino.IsSurfaceTrimmed(strSurfaceShrunk) Then Rhino.ShrinkTrimmedSurface(strSurfaceShrunk)
arrDomU = Rhino.SurfaceDomain(strSurfaceShrunk, 0)
arrDomV = Rhino.SurfaceDomain(strSurfaceShrunk, 1)
Call Rhino.DeleteObject(strSurfaceShrunk)
Call Rhino.EnableRedraw(vbTrue)
If Not IsArray(arrDomU) Or Not IsArray(arrDomV) Then Exit Sub
'OPTIONS
Dim strResult, arrOptions() : ReDim arrOptions(5-l)
Dim intQuantity : intQuantity = 10 'Initial points number
Dim dbDist : dbDist=0
Dim strMatch : strMatch="Disabled"
Do
arrOptions(0)="Randomize"
arrOptions(1)="PointCount_" & intQuantity
arrOptions(2)="MinPtDist"
If dbDist<1 And dbDist>0 Then arrOptions(2)="MinPtDist_between_0_and_1"
arrOptions(3)="MatchPointCount_" & strMatch
arrOptions(4)="CurveMinDist"
arrOptions(5-l)="CREATE"
If blnSkip=False Then
ReDim arrPoints(0) : j=0
'GENERATING RANDOM POINTS
Call Rhino.EnableRedraw(vbFalse)
For a = 1 To intQuantity
For m = 0 To intM '-loop for iterations for point count match
Do
t(0) = arrDomU(0) + (((arrDomU(1) - arrDomU(0))*Rnd))
t(1) = arrDomV(0) + (((arrDomV(1) - arrDomV(0))*Rnd))
pt = Rhino.EvaluateSurface(strSurface, t)
If Rhino.IsPointOnSurface(strSurface,pt) Then Exit Do
Loop
strPoint = Rhino.AddPoint(pt)
'testing for existing points withing given minimum distance
If dbDist > 0 Then
If IsArray(Rhino.SelectedObjects) Then
For Each idDistTest In Rhino.SelectedObjects
If FastDistance(pt,Rhino.PointCoordinates(idDistTest)) < dbDist Then
Rhino.DeleteObject(strPoint)
Exit For
End If
Next
End If
End If
'testing distance to curves
If l=0 And dblCrvDist>0 And Rhino.IsObject(strPoint) Then
For Each idCurve In arrCurves
If FastDistance(Rhino.PointCoordinates(strPoint),Rhino.EvaluateCurve(idCurve,Rhino.CurveClosestPoint(idCurve,Rhino.PointCoordinates(strPoint)))) < dblCrvDist Then
Rhino.DeleteObject(strPoint)
Exit For
End If
Next
End If
If Rhino.IsObject(strPoint) Then
ReDim Preserve arrPoints(j)
arrPoints(j)=strPoint
j=j+1
Exit For
End If
Next
Call Rhino.SelectObject(strPoint)
'process percentage and points generated
Call Rhino.Prompt("Generating points... "&CStr(Int((100*a)/intQuantity))&"% | Generated " & CStr(UBound(arrPoints)+1)&" points. Press ESC to cancel")
'refresh every 10%
If a Mod (intQuantity/10) = 0 Then
Call Rhino.EnableRedraw(vbTrue)
Call Rhino.EnableRedraw(vbFalse)
End If
Next
Call Rhino.Print("Generated " & CStr(UBound(Rhino.SelectedObjects)+1)&" points...")
Call Rhino.EnableRedraw(vbTrue)
End If
'OPTIONS
strResult = Rhino.GetString("Generate random points on surface","CREATE",arrOptions)
Select Case Left(UCase(strResult),2)
Case "CU"
dblCrvDist=Rhino.GetReal("Minimum distance from curve?",dblCrvDist,0)
If IsNull(dblCrvDist) Then dblCrvDist=0
Call Rhino.DeleteObjects(Rhino.SelectedObjects)
If dblCrvDist>0 Then blnSkip=False
Case "CR"
Exit Do
Case "PO"
intQuantity = Rhino.GetInteger("Number of points to generate",intQuantity,1)
Call Rhino.DeleteObjects(Rhino.SelectedObjects)
Case "RA"
Call Rhino.DeleteObjects(Rhino.SelectedObjects)
Case "MI"
dbDist=Rhino.GetReal("Minimal point to point distance",dbDist,0)
Call Rhino.DeleteObjects(Rhino.SelectedObjects)
If dbDist>0 Then blnSkip = False
Case "MA" ' setting the level of point count match while minimal distance is defined
If dbDist=0 Then blnSkip = vbTrue
strMatch=Rhino.Getstring("Select point count match attempt level",strMatch,Array("Disabled","Low","Med","High","Max"))
Select Case Left(UCase(strMatch),2)
Case "DE"
intM = 0
Case "LO"
intM = 10
Case "ME"
intM = 50
Case "HI"
intM = 100
Case "MA"
intM = 300
Case Else
strMatch="Disabled"
intM=0
End Select
If Not blnSkip=True Then Call Rhino.DeleteObjects(Rhino.SelectedObjects)
Case Else
Call Rhino.DeleteObjects(Rhino.SelectedObjects)
Exit Sub
End Select
Loop
Call Rhino.Command("!_Group")
End Sub
Function FastDistance(byref P1,byref P2)
FastDistance=Sqr((P1(0)-P2(0))(P1(0)-P2(0))+(P1(1)-P2(1))(P1(1)-P2(1))+(P1(2)-P2(2))*(P1(2)-P2(2)))
End Function)
-runscript
(Option Explicit
Call CopyToPoints()
Sub CopyToPoints
Dim idObjs : idObjs = Rhino.GetObjects(“Objects to copy”, ,True, True, True)
Dim ptFrom : ptFrom = Rhino.GetPoint(“Point to copy from”)
Dim ptTarget : ptTarget = Rhino.GetPointCoordinates(“Points to copy to”, False)
Dim i
For i = 0 To UBound(ptTarget)
Call Rhino.CopyObjects(idObjs, ptFrom, ptTarget(i))
Next
End Sub)