Hi,
I am pretty new to Grasshopper, but i am trying to use VB.net script in a project at school...
I am creating an amount of points randomly placed.
What i want is that the still are being placed randomly, but i want them to be attracted to some other points... So the majority of points will go near the points picked by me...
This is how i would do it:
- Create a random set of points (it should be as dense as the maximum density you want for the points near the attractors).
- Calculate the distance from the random points to the attractor points
- For every random point, create a number that ranges from 0 to the maximum distance found.
- So for every random point, you've got two numbers: a random number and a distance number
- If the random number is smaller than the distance number, filter the point out.
It's not really a VB.NET question, this about algorithms. If you can some up with an algorithm that does what you want, chances are you'll be able to implement it in pretty much any programming language out there.
Damien gave you a two-step approach, which should work reasonably fast. If you are also concerned about two random points coming too close together then you'll need additional logic. I have an algorithm which might work well, but it's much slower than Damiens solution:
1) Declare a new list of Circles [C], empty at the start
2) Declare a new list of Points [P], empty at the start
3) Create a new random point [p] inside your region.
4) If [p] is inside any of the circles contained in [C], discard it and go back to step (3)
5) If [p] is in unoccupied space, then measure its distance to all your attractor points.
6) Based on these distances (or maybe just the shortest distance, depends on how you define your contracting behaviour), compute a new Radius [r] for [p].
7) Add [p] to [P], and add a new circle (center = [p], radius = [r]) to [C].
8) Go back to step 3, repeat.
You'll need a way to abort this infinite loop. You should probably count how often in a row you failed to find an empty spot (step 4), if you failed more than -say- a hundred times in a row, you short-circuit the entire loop.
I wrote a basic implementation of my proposed algorithm. I cannot send you the file since I'm using a newer version of Grasshopper and the ghx file probably won't load in the old version.
The x_range has an OnInterval hint
The y_range has an OnInterval hint
The attractors has an On3dPoint hint and it's a List parameter
The factor has a Double hint.
I've included two vb files, one contains the contents of the RunScript function, the other contains two additional functions I wrote.
Class Grasshopper_Custom_Script
#Region "members"
Private app As MRhinoApp
Private doc As MRhinoDoc
Public P, C As System.Object
#End Region
Sub RunScript(ByVal x_range As OnInterval, ByVal y_range As OnInterval, ByVal attractors As List(Of On3dPoint), ByVal factor As Double)
'''
If (attractors.Count = 0) Then Return
If (factor <= 0.0) Then Return
Dim Rnd As New Random(123456)
Dim failed As Int32 = 0
Dim Pts As New List(Of On3dPoint)
Dim Rad As New List(Of Double)
Dim Crc As New List(Of OnCircle)
Do
If (failed > 100) Then Exit Do
Dim x As Double = x_range.ParameterAt(Rnd.NextDouble())
Dim y As Double = y_range.ParameterAt(Rnd.NextDouble())
Dim pt As New On3dPoint(x, y, 0.0)
If (IsTaken(pt, Pts, Rad)) Then
failed += 1
Continue Do
End If
failed = 0
Dim d As Double
Dim i As Int32 = NearestAttractor(pt, attractors, d)
Dim radius As Double = factor * (Math.Pow(d, 0.8) + 0.5)