Is it possible to create random shapes (see below for example) of a given area in NetLogo?
A first stab at Seth's suggestion #1. It creates a neat visual too!
patches-own [ height ]
to blobbify
clear-all
repeat (ceiling 2 * (ln (world-height * world-width))) [
ask patch (round (random (world-width / 2)) - world-width / 4)
(round (random (world-height / 2)) - world-height / 4)
[ set height world-width * world-height ] ]
while [ count patches with [ height > 1 ] < (world-width * world-height / 4)]
[ diffuse height 1
ask patches with [ height > 0 ] [ set pcolor height ]
]
ask patches with [ height > 1 ] [ set pcolor white ]
end
I found a really simple approach that produces pretty nice results.
Create a turtle. The turtle performs a random walk. After each step, they set the uncolored patch closest to them to the desired color. The turtle does this a number of times equal to the desired area.
Here's the code:
to make-blob [ area ]
let blob-maker nobody
crt 1 [ set blob-maker self ]
repeat area [
ask blob-maker [
ask min-one-of patches with [ pcolor = black ] [ distance myself ] [ set pcolor blue ]
rt random 360
fd 1
]
]
ask blob-maker [ die ]
end
This naturally produces nicely curved blobs.
Making the turtle's step size smaller makes the blob more circle-y. Making it bigger results in thinner, more sporadic blobs (though you run the risk of getting disconnected patches).
Edit:
I noticed that my answer runs quite slowly when you have a gigantic number of patches. Here's a much faster version:
to make-blob [ area x y ]
let blob-maker nobody
crt 1 [ set blob-maker self setxy x y ]
let border patch-set [ patch-here ] of blob-maker
repeat area [
ask blob-maker [
ask min-one-of border [ distance myself ] [
set pcolor green
set border (patch-set border neighbors4) with [ pcolor = black ]
]
rt random 360
fd .8
]
]
ask blob-maker [ die ]
end
Generating random blobs is a hard problem with no obvious solution. Fixing the area of the blob makes it even harder.
You'll need to pick an approach, then try to figure out how to express that approach in NetLogo code.
As for what approach to pick, I imagine there's literature on this if you search. But just off the top of my head, I have three ideas:
Scatter random points around the world, use diffuse to make a smooth landscape around these peaks. (See the Diffusion Graphics model, in the Art section of NetLogo's Models Library, for code for this; you'll want to turn world wrapping off, though.) Then select only those patches where the "elevation" exceeds some threshold. To get the desired area, vary the threshold until the target is reached.
Draw a curve around the center point using polar coordinates, where theta goes from 0 to 360 and 4 varies randomly. You'll need a way to get smooth random variation in the radius, perhaps by generating random numbers and then applying a smoothing function to them. In order to force the blob to have the desired area, first generate the whole curve, then scale it as needed. You'll need some trick to avoid a discontinuity where theta = 0, perhaps by using a smoothing function that wraps.
Generate a random polygon by scattering points around the world, then discarding some or all points in the middle. (You could take the convex hull, but then you'll always get a convex shape, which might not be "blobby" enough for you. So you might want to something like like generating n random points and then keeping the m points that are farthest from the center, without regard to convexity.) Once you've got the random polygon, apply some smoothing function to turn it into a curvy blob. Then scale the whole thing as necessary to get the desired area.
Related
I am new to Netlogo and learning a model is about animals moving around to eat grass based on the grazing model from NetLogo. The moving behavior is based on the biomass's richness, so it is not just impacting at right angles.
Given the conditions, I don't know how to add a monitor in my model that calculates the total distance a turtle moved by traveling each pixel.
Move specifically, I wonder if there is a way to calculate the total length of the pen-marked lines. (Show in the picture)
enter image description here
The basic setting of move is
to move-turtles
uphill-biomass
forward 1
set distance-traveled (distance-traveled + 1)
if not can-move? 1 [ rt random 150 ]
end
to uphill-biomass
let biomass-ahead biomass-scent-at-angle 0
let biomass-right biomass-scent-at-angle 35
let biomass-left biomass-scent-at-angle -35
if (biomass-right = biomass-ahead) and (biomass-left = biomass-ahead) [ wiggle ]
if (biomass-right > biomass-ahead) or (biomass-left > biomass-ahead)
[ ifelse biomass-right > biomass-left
[ rt 35 ]
[ lt 35 ] ]
end
Thank you very much for any helps!
You need to use some turtle variables with the turtles-own primitive and do the distance calculation by hand.
The easiest way to do such a calculation is to save the coordinates between a turtle's previous coordinates with turtle variables and then use the distancexy primitive (link for dictionary entry: https://ccl.northwestern.edu/netlogo/docs/dictionary.html#distancexy)
Here's a simple implementation:
turtles-own [last-x last-y distance-traveled]
move-turtle
uphill-biomass
set last-x xcor
set last-y ycor
forward 1
set distance-traveled (distance-traveled + (distancexy last-x last-y))
if not can-move? 1 [ rt random 150 ]
end
I hope this answers your question.
I want to move the current turtle one step closer to the others that fulfill a certain condition (e.g. have color = green).
I am doing this the hard way (because I don't know any better), by trying to calculate the the average distance of the current turtle from all others that fulfill the condition, and calculate the average from x+1, x-1, y+1, y-1. Then whichever is the smallest would indicate the direction of the move. Not very elegant, I know, and limits movements to horizontal and vertical, but I couldn't come up with anything better (the only other idea that struck me was to calculate average x and y coordinates of all turtles that fulfill the condition and move the current turtle towards that, but that seemed even more ridiculous to me)
Problem is that even with my clumsy solution, I am not getting anywhere, since I am struggling with how to calculate the average distance from the "green" turtles.
If you want to calculate the mean distance, you can have the asking turtle call mean and [distance myself].
With this setup:
to setup
ca
crt 10 [
set color green
move-to one-of patches with [ pxcor < 0 ]
]
crt 1 [
set color red
move-to one-of patches with [ pxcor > 10 ]
]
reset-ticks
end
Calling the function below will have the red turtle print out first all distances between itself and all green turtles, then the mean of those distances:
to calc-mean-distance
ask turtles with [ color = red ] [
print [ distance myself ] of turtles with [ color = green ]
print mean [ distance myself ] of turtles with [ color = green ]
]
end
Beyond that, I'm not 100% sure what you're trying to do- are you hoping to move the asking turtle towards the nearest turtle that meets some condition? If so, this might work for you:
to go
ask turtles with [ color = red ] [
let target min-one-of ( turtles with [ color = green ] ) [ distance myself ]
face target
ifelse distance target > 1 [
fd 1
] [
move-to target
]
]
tick
end
If you want the asking turtle to move instead towards the geographic center of those turtles that meet a condition, you could indeed get the mean x and y coordinates of those turtles as you describe, then have the asking turtle move towards that point:
to go
let central-x mean [ xcor ] of turtles with [ color = green ]
let central-y mean [ ycor ] of turtles with [ color = green ]
ask turtles with [ color = red ] [
facexy central-x central-y
ifelse distancexy central-x central-y > 1 [
fd 1
] [
setxy central-x central-y
]
]
tick
end
If those aren't quite what you're trying to achieve, feel free to leave a comment for clarification!
In my model I have some agents collecting from another agent who they bump into at random after which they move back to their base. As they move back they drop off some material as defined by the random function. Here's some sample code
to go
ask searchers
[ set energy energy - 1
fd 0.0125
if random-float 1 < (1 / 50)
[ ifelse random 2 = 0
[ rt 45 ]
[ lt 45 ]
]
search
]
end
to search
if any? depots in-radius vision with [color = yellow]
[spread
set energy 0] ;; makes them to back to base
end
to spread
if random 10000 = 1 [hatch-rubbish 1 [ set color white
set shape "circle"
set size 0.5]]
end
If I set the visual radius to something enormous so they can always see the depot the number of bits of rubbish works out.
However if I allow them to move around with a radius of 1, the count of rubbish is much higher than 1 in 10,000.
Why would that make a difference?
Thanks
I used the code from How to create cluster patches that do not overlap between them to build patches as shown in the first figure below.
Here is the code :
to make-cluster
loop [
let cluster [patches in-radius (2 + random-float 2)] of one-of patches
if all? (patch-set [neighbors] of cluster) [pcolor = black] [
ask cluster [ set pcolor green ]
stop ] ]
clear-all repeat 20 [ make-cluster ]
When I use this code in a large spatial extent (i.e. 1000 x 1000 patches with patch size = 1 pixel), green patches are like circles (see the second figure below).
How can I have patches as shown in the first figure ?
Thank you very much for your help.
If your goal is to simply have heterogeneous regions (rather than specifically blocky, symmetric things), you might play around with some of the answers here: Creating a random shape (blob) of a given area in NetLogo
Frank's solution and my first solution will probably run pretty slow on that large of a world. I just added a solution that should scale to a world of your size. I've put it here too for convenience:
to make-blob [ area x y ]
let blob-maker nobody
crt 1 [ set blob-maker self setxy x y ]
let border patch-set [ patch-here ] of blob-maker
repeat area [
ask blob-maker [
ask min-one-of border [ distance myself ] [
set pcolor green
set border (patch-set border neighbors4) with [ pcolor = black ]
]
rt random 360
fd .8
]
]
ask blob-maker [ die ]
end
That said, if you like the blockiness, it's often the case that models with a large number of patches in a blocky formation can be reworked into models with a smaller number of patches that behave quite similarly. For example, one strategy is to scale down the size and movements of the turtles so that the world is still relatively large to them.
I've made a model that aranges factions (turtles in different colours) in a circle.
At the moment they arrange randomly, was wondering if someone could help me arrange them so, for example, red occupies the first 90 degrees, blue the next 90 degrees, etc (on setup).
Here's my code...
ask patch 0 0
[ ask patches in-radius ( max-pxcor * .9) with [ random-float 100 < density ]
[ sprout 1
[ set breed cons
set shape "circle"
set faction random factions
set heading random 360
set size 1
]
]
]
.. guessing I will have to do 360 / fractions, but not sure how to phrase it, if someone could help me out that'd be great. Thanks!
The NetLogo primitive that's the closest to what you want to do is in-cone, which reports the set of turtles that are in the "cone of vision" of another turtle. But your "pie slices" should just be relative to patch 0 0, not to another turtle! No problem: just make a temporary turtle at patch 0 0, use it to get turtles in-cone with the appropriate angle, and kill your temporary turtle.
The following procedure can be used "as is" with your code (just call it from your setup procedure after creating your turtles exactly as you were doing before):
to assign-factions
let angle 360 / factions
foreach n-values factions [?] [
ask patch 0 0 [
sprout 1 [
set heading ? * angle
ask turtles in-cone max-pxcor angle [ set faction ? + 1 ]
die
]
]
]
end
The code is pretty straightforward, except for maybe the more obscure n-values. You could replace it with a while loop if you prefer, but it's really just counting from 0 to factions.
Here is what you'd get with 5 factions: