I am trying to model some building search in Netlogo, but now I am stuck, because I have no idea how to solve seeing through walls. My agent can see in cone lets say 60 degrees and 5 patches ahead. I can detect wall somewhere in my sight and i can detect other objects as well, problem is to detect if the obejct is behind wall or not. How can I solve it? Any ideas?
Here's a full working example. You can do some optimizations regarding which walls or patches need to be checked, rather than all of them, but I'll leave that to you...Essentially, You can imagine that you draw a line between the agent and all other patches that are in the vision of the agent and remove the patches such that there is an intersecting wall. The line-intersection problem is well studied and I put a link for you to look at. To make my calculations easier, I store the end points of the wall--you could use trig to calculate the end points if the wall wasn't vertical like in my case. I use some aesthetics too...
breed [ walls wall]
walls-own [first-end second-end]
to setup
ca
reset-ticks
set-default-shape walls "line"
crt 1 [ setxy 4 0]
ask turtles [facexy 0 0]
;;color all cones in radius blue by default
let dist 10
let angle 30
ask turtles [ ask patches in-cone dist angle [set pcolor blue]]
;; place a wall down...the line of sight is blocked (keyword: line)
create-walls 1 [ setxy 0 0 ]
;;This is an interpretation of a wall. Two points that define the edges.
ask wall 1 [set size 10]
ask wall 1 [set first-end (list 0 (size / 2))]
ask wall 1 [set second-end (list 0 (-1 * size / 2))]
;;my wall is vertical. You can do trig above and below to adjust for not vert lines.
ask wall 1 [ set heading 0]
ask wall 1 [set color hsb 216 50 100] ;;pretty blue =)
ask turtle 0 [ ask in-sight dist angle [ set pcolor green]]
end
;;a turtle can see a patch if the line from the patch to the turtle isn't intersected by a wall.
to-report in-sight [dist angle]
let turtle-x xcor
let turtle-y ycor
report patches in-cone dist angle with
[
not any? walls with [intersects [pxcor] of myself [pycor] of myself turtle-x turtle-y ;; line 1
(first first-end) (last first-end) (first second-end) (last second-end)] ;; line 2
]
end
;; See http://stackoverflow.com/questions/3838329/how-can-i-check-if-two-segments-intersect
;;counter clockwise method (doesn't consider colinearity)
to-report counter-clockwise [x1 y1 x2 y2 x3 y3]
;;returns true if triplet creates counter clockwise angle (uses slopes)
;(C.y-A.y) * (B.x-A.x) > (B.y-A.y) * (C.x-A.x)
report (y3 - y1) * (x2 - x1) > (y2 - y1) * (x3 - x1)
end
to-report intersects [x1 y1 x2 y2 x3 y3 x4 y4]
;;line 1: x1 y1 x2 y2
;;line 2: x3 y3 x4 y4
;;DANGER: Doesn't work for colinear segments!!!
;ccw(A,C,D) != ccw(B,C,D) and ccw(A,B,C) != ccw(A,B,D)
report (counter-clockwise x1 y1 x3 y3 x4 y4) != (counter-clockwise x2 y2 x3 y3 x4 y4)
and (counter-clockwise x1 y1 x2 y2 x3 y3) != (counter-clockwise x1 y1 x2 y2 x4 y4)
end
Related
I want to create a semicircle, the center of my semicircle is at the end of the world, for example I want that the center of my semicircle is in the 50,20 position, and goes from 20 to -20.
I try with this, but I got an exception:
The point [ 60 , 20 ] is outside of the boundaries of the world and
wrapping is not permitted in one or both directions.
to mysemicircle
let cx 50 ;; x coordinate of patch you want to circle
let cy 20 ;; y coordinate of patch you want to circle
let r 10 ;; radius of the circle you want
let p2r ( 2 * pi * r ) ;; get circumference of the circle
let step p2r / 360 ;; make step lengths 1/360th of the circumference
crt 1 [ ;; create a single drawing turtle
setxy cx + r cy ;; move it to the highlight patch + the radius
pd ;; put the pen down
set heading 0 ;; make it face along the tangent
while [ p2r > 0 ] [ ;; make the turtle continue to move until the circle is drawn
lt 1
fd step
set p2r p2r - step
set color white
]
]
end
And If i use cx 40 and cy 20 the circle is not from y -20 to y 20, but is only from y 0 to y 20.
How Can I do that?
Maybe a procedure with arguments would be better for this, something like:
to setup
ca
resize-world -20 20 -20 20
draw-semi-circle 0 0 15 45 blue
draw-semi-circle 5 5 5 270 red
draw-semi-circle -10 -10 8 135 green
reset-ticks
end
to draw-semi-circle [ x y r a col ]
; Give arguments for x, y, radius, and angle of the semicircle
let half-p ( pi * r )
let step half-p / 180
ask patch x y [
set pcolor col
]
crt 1 [
setxy x y
set heading a
lt 90
set color col
back r
pd
fd 2 * r
rt 90
while [ half-p > step ] [
rt 1
fd step
set half-p half-p - step
]
]
end
To get an output like:
I am new to posting in stackoverflow.
Before I had a problem with agents/turtles seeing through the walls I make, but I have found the solution here:
Not see through the walls
The problem now is when there is another wall within the vision-cone, the valid line of sight (green patches) are incorrect. I'm currently still tinkering on how to fix this.
Here is my current code that I have been working on,
breed [walls wall]
walls-own [first-end second-end]
to setup
ca
reset-ticks
set-default-shape walls "line"
crt 1 [setxy 4 0]
ask turtles [facexy 0 0]
;color all cones in radius blue by default
let dist 10
let angle 80
ask turtles [ask patches in-cone dist angle [set pcolor blue]]
;; place a wall down.... the line of sight is blocked (keyword: line)
create-walls 1 [setxy 0 0]
;;This is an interpretation of a wall. Two points that define the edges.
ask wall 1 [set size 10]
;;my wall is vertical. you can do trig above and below to adjust for not vert lines.
ask wall 1 [set heading 45]
ask wall 1 [set color hsb 216 50 100]
;; I made it so that it could consider not vertical lines
ask wall 1 [ set first-end (list (round (sin heading * (size / 2))) (round (cos heading * (size / 2))))]
ask wall 1 [ set second-end (list (round((-1 * (size / 2) * sin heading))) (round ((-1 * (size / 2) * cos heading))))]
;;Test wall. UN-COMMENT THE SET BELOW TO SEE THE PROBLEM
; create-walls 1 [setxy 4 4]
; ask wall 2 [set size 10]
; ask wall 2 [set heading 90]
; ask wall 2 [ set first-end (list (round (sin heading * (size / 2))) (round (cos heading * (size / 2))))]
; ask wall 2 [ set second-end (list (round((-1 * (size / 2) * sin heading))) (round ((-1 * (size / 2) * cos heading))))]
; ask wall 2 [set color hsb 216 50 100]
ask turtle 0 [ask in-sight dist angle [set pcolor green]]
end
;;a turtle can see a patch if the line from the patch to the trutle isnt intersected by a wall.
to-report in-sight [dist angle]
let turtle-x xcor
let turtle-y ycor
report patches in-cone dist angle with
[
not any? walls with [intersects [pxcor] of myself [pycor] of myself turtle-x turtle-y ;; line 1
(first first-end)(last first-end)(first second-end)(last second-end)] ;; line 2
]
end
to-report counter-clockwise [x1 y1 x2 y2 x3 y3]
;; returns true if triplet creates counter clockwise angle (uses slopes)
;; (C.y-A.y) * (B.x-A.x) > (B.y-A.y*(C.x-A.x)
report (y3 - y1)*(x2 - x1)>(y2 - y1)*(x3 - x1)
end
to-report intersects [x1 y1 x2 y2 x3 y3 x4 y4]
;; line 1: x1 y1 x2 y2
;; line 2: x3 y3 x4 y4
;;DANGER: Doesnt work for colinear segments
report (counter-clockwise x1 y1 x3 y3 x4 y4) != (counter-clockwise x2 y2 x3 y3 x4 y4)
and (counter-clockwise x1 y1 x2 y2 x3 y3) != (counter-clockwise x1 y1 x2 y2 x4 y4)
end
This is what it looks like if you would uncomment the set of code for the test wall.
Problem
Any suggestions or tips would be very helpful!
Thank you in advance.
Obviously, any shape drawable by other means can be drawn by a turtle. Circles and squares are easy
rt 1 fd .0
and
if ticks mod 100 = 0 [rt 90]
fd 1
Super-ellipses not so much. (regular ellipses are not trivial either.)
The Wikipedia article on super-ellipses if you need to be refreshed on the topic.
Any input is appreciated.
Using a pendown turtle is there way to make a super-ellipse that emerges from turtle movement?
I have 1/4 of it, I suppose you could piece-wise put the other three together. Other values of n are not tested here. (using the Wiki notation, plus phi as an angle of rotating the whole thing.) And the placement of reset-ticks, pen-down, is sloppy, I know.
to go2
clear-all
reset-ticks
let a 6
let b 5
let phi 0
let n 3.5
create-turtles 1 [
let iNdx 1
repeat 90 [
show iNdx
show cos(iNdx)
if cos(iNdx) > 0 and sin(iNdx) > 0 [
let tx (a * (cos(iNdx) ^ (2 / n)))
let ty (b * (sin(iNdx) ^ (2 / n)))
let tx2 tx * cos(phi) - ty * sin(phi)
let ty2 tx * sin(phi) + ty * cos(phi)
setxy tx2 ty2
]
pen-down
set iNdx iNdx + 1
]
]
end
The ellipse looks simpler, but you be the judge
to go
clear-all
reset-ticks
let a 6
let b 5
let phi 45
create-turtles 1 [
let iNdx 1
repeat 360 [
let tx (a * cos(iNdx))
let ty (b * sin(iNdx))
let tx2 tx * cos(phi) - ty * sin(phi)
let ty2 tx * sin(phi) + ty * cos(phi)
setxy tx2 ty2
pen-down
set iNdx iNdx + 1
]
]
end
a generalization and simplification as a procedure.
to Super-ellipse [x y a b m n]
create-turtles 1 [
let iNdx 1
repeat 360 [
setxy (x + (abs cos iNdx)^(2 / m) * a * (sgn cos iNdx))
(y + (abs sin iNdx)^(2 / n) * b * (sgn sin iNdx))
pendown
set iNdx iNdx + 1]
]
end
The generalized form of another answer seems to produce the sort of thing I was thinking of. the closer the pen starts to one of the foci the closer the drawing is to a square. the n<1 super-ellipses are not achieved.
globals[c]
breed [pens pen]
breed [foci focus]
foci-own [dist distx disty]
to setup
ca
create-pens 1 [set heading 45 fd 10 pendown set C self]
;create-foci 1 [setxy (random-xcor / 2) (random-ycor / 2)]
create-foci 1 [setxy 10 10]
create-foci 1 [setxy 10 -10]
create-foci 1 [setxy -10 -10]
create-foci 1 [setxy -10 10]
end
to go
repeat 5100
[
ask foci [
set dist distance c
set distx xcor - [xcor] of c
set disty ycor - [ycor] of c
]
ask c
[
set heading 90 + atan ( sum [distx / dist] of foci / sum [dist] of foci)
( sum [disty / dist] of foci / sum [dist] of foci)
FD .0125
]
]
end
This is an answer to a question posed in the comments in my possibly poorly worded question about super-ellipses.
in Netlogo it is natural to draw geometric shapes in ways that may seem strange in other languages.
ask turtle 1 [pendown
let d (pi * distance turtle 2) / 360
repeat 360 [face turtle 2 rt 90 fd d]
]
for instance inscribes makes turtle 1 draw a circle [360-gon] around turtle 2. I did not invoke any of the standard circle formulas but still get a circle.
Is it possible to draw an ellipse in this same vernacular with say one turtle drawing an ellipse (or super-ellipse)round two other turtles using them as the foci?
Essentially to make an ellipse you set the turtles heading to the weighted mean heading of the foci and update each step. It could be done in one line but that would be one ugly line.
globals [a b c]
to setup
ca
crt 1 [set heading 90 fd 10 pendown set C self]
crt 1 [setxy 5 10 set A self]
crt 1 [setxy 0 -10 set B self]
end
to go
repeat 5100 ;; ad hoc number
[
ask c
[
let Ax [xcor] of A - xcor
let Ay [ycor] of A - ycor
let Bx [xcor] of B - xcor
let By [ycor] of B - ycor
let da 1 / distance a
let db 1 / distance B
set heading 90 + atan ((ax * da + bx * dB) / (da + db))
((ay * da + by * db) / (da + db))
FD .0125 ;;
]
]
end
I was wondering if by using same random seed, the result of following functions differs significantly in randomness! and which one is better? provided Code is just an example.
let b random 3
if b = 0 [set Output "Output1"]
if b = 1 [set Output "Output2"]
if b = 2 [set Output "Output3"]
Or this one :
set output one-of ["Output1" "Output2" "Output3"]
UPdate:
I just checked it with a simple netlogo program:
turtles-own [X Y A]
to setup
__clear-all-and-reset-ticks
create-turtles 50
[set A random 3000
set y random-normal 0.5 0.1
set x random-normal 0.5 0.1
move-to patch random 20 random 20]
end
to go
ask turtles
[ set A A + 1
fd 1
rt random 10
if A > 4000 [die]
if random-float 1 < 0.003 and a > 1000 and A < 3000 [
let xx x
let yy y
hatch 1
[ set A 0
set x one-of (list (random-normal 0.5 0.1) (xx + 0.1) (XX - 0.1))
let b random 3
if b = 0 [set y random-normal 0.5 0.1]
if b = 1 [set y yy + 0.1]
if b = 2 [set y yy - 0.1 ]
]
]
]
tick
end
The results is as follow:
There is not much difference is using any of these methods :)
There is a bug in your measurement code. Change b = 3 to b = 2 and I predict you will see any difference go away.
Unless there is some weird bug in NetLogo (or the JVM) that no one has discovered yet, it shouldn't make any difference whether you use one-of or random. To my knowledge, there is no such bug.
The relevant source files are:
https://github.com/NetLogo/NetLogo/blob/5.0.x/src/main/org/nlogo/prim/_randomconst.java
https://github.com/NetLogo/NetLogo/blob/5.0.x/src/main/org/nlogo/prim/_oneof.java
The only difference is that the first calls context.job.random.nextLong and the latter context.job.random.nextInt (because the size of a NetLogo list is an int, not a long, while the input to random is a long). But both nextInt and nextLong are of equally high quality; they're just calls into the standard MersenneTwisterFast class which is widely used by people doing simulation work.