Is there a way to add a buffer zone to gis:set-world-envelope-ds gis:envelope-of *shapefile* - gis

Currently,
I am using gis:set-world-envelope-ds gis:envelope-of <shapefile> to set world. However, I am getting the error message: " Cannot move turtle beyond the world's edge. error while node 18469 running SET"
Hence, I would like to add a bufferzone around it. Does anyone know how?

You can manually adjust the envelope values, since they are x/y bounds. Calling gis:envelope-of just returns a list of the format [x1 x2 y1 y2] which represent the boundaries of the envelope. How to adjust those depends on how much boundary you want and your projection but: here is a quick and dirty way to add a tenth of a 'span' (x1 - x2 or y1 - y2) as a buffer:
extensions [ gis ]
to setup
ca
let shp_path "C:/gis_example/british_columbia_administrative.shp"
let prj_path "C:/gis_example/british_columbia_administrative.prj"
gis:load-coordinate-system prj_path
let shp gis:load-dataset shp_path
let base_envelope gis:envelope-of shp
print word "Base envelope: " base_envelope
let span_x abs ( item 0 base_envelope - item 1 base_envelope )
let span_y abs ( item 2 base_envelope - item 3 base_envelope )
let alternating_spans ( list span_x span_x span_y span_y )
let alternating_signs [ -1 1 -1 1 ]
let expanded_envelope (
map [ [ i span sign ] -> i + sign * ( 0.1 * span ) ]
base_envelope alternating_spans alternating_signs
)
print word "Expanded envelope: " expanded_envelope
gis:set-world-envelope-ds expanded_envelope
gis:set-drawing-color white
gis:draw shp 1
reset-ticks
end
Dataset downloaded from MapCruzin.com

Related

Error with netlogo gis extension vertex-lists-of

I want to extract points from line feature from shapefile.
I have search for solutions, it shows that most of people use gis:vertex-lists-of to do this.
For example,
However I got an error message below when I try to do that:
Extension exception: not a VectorFeature:
org.myworldgis.netlogo.VectorDataset#ca24265
error while observer running GIS:VERTEX-LISTS-OF
called by procedure DRAW-CITIES
called by Button 'draw-cities'
Code below:
to draw-cities
gis:set-drawing-color red
gis:draw cities-dataset 1
foreach gis:vertex-lists-of cities-dataset [
a ->
]
end
cities-dataset is a points collection shapefile from Netlogo library ""GIS general examples" model
I don't understand that even I put a points feature in the function, I just got an error.
Do I misuse the function? How can I corectly use it? Thank you.
The reason for the error is because your foreach function is missing the action steps a foreach function looks something like this:
foreach [1 2 3][a -> print a + 1]
If you wanted to do something like the code you linked to then it would look like this:
extensions [ gis ]
globals [ cities-dataset]
breed [ cities city ]
breed [nodes node]
cities-own [ name country population ]
to setup
set cities-dataset gis:load-dataset "C:/Program Files/NetLogo 6.2.2/app/models/Code Examples/Extensions Examples/gis/data/cities.shp"
draw-cities
end
to draw-cities
gis:set-drawing-color red
gis:draw cities-dataset 1
foreach gis:feature-list-of cities-dataset[
i ->
foreach gis:vertex-lists-of i[
j ->
let first-node-point nobody
let previous-node-point nobody
foreach j [
k ->
let location gis:location-of k
if not empty? location [
ifelse any? nodes with [
xcor = item 0 location and ycor = item 1 location
]
[]
[
create-nodes 1[
set xcor item 0 location
set ycor item 1 location
set size 0.23
set shape "circle"
set color 23
set hidden? false
]
]
;to create links
let node-here (nodes with [
xcor = item 0 location and ycor = item 1 location
])
ifelse previous-node-point = nobody
[set first-node-point node-here]
[let who-node 0
let who-prev 0
ask node-here
[create-link-with previous-node-point
set who-node who]
ask previous-node-point[
set who-prev who
]
set previous-node-point one-of node-here
]
]
]
]
]
end
I'm not entirely sure what you're looking to do, but feel free to ask for more help.

Distance Primitive not working with Raster information: Netlogo

This one is long so please bear with me. I have Two rasters in my world, one of a department and one of a very important lake (it was a shape file that I rasterized). I load both rasters and use them to set the variable lake (tota) and the elevation. Then Im trying to set the distance between non lake patches and lake patches but Im getting an error "DISTANCE expected input to be an agent but got NOBODY instead.
error while patch 571 969 running DISTANCE"
This error doesn't make sense to my as the variable im checking is only for those who have tota (water) I know the code will be long and i tried my best to simplify but it is still a bit cluttered
extensions [ gis ]
globals [ world lake show-lake water]
patches-own[
distance-water
tota
]
to draw-tota
let min-elevation gis:minimum-of world
let max-elevation gis:maximum-of world
ask patches [
set elevation gis:raster-sample worldself
if (elevation <= 0) or (elevation >= 0) [
set pcolor scale-color green elevation 2900 max-elevation
]
]
end
to draw-lake
ask patches [
set water gis:raster-sample lake self
if (water >= 0) [
set pcolor blue
set tota 1
]
]
end
to setup-map
set world gis:load-dataset "D:/Geografico/DEM_Lago_Tota.asc"
gis:set-transformation [-72.994844704 -72.835891153 5.418413284 5.648012857666661] [0 1000 0 1000]
set lake gis:load-dataset "D:/Geografico/Lago_Tota_Raster.asc"
draw-tota
draw-lake
end
;;set up conditions
to set-houses
ask patches [
set dano_suelo (1 + random 5) ;;
set distance-lake distance min-one-of patches with [tota = 1] [distance myself]
]; This is the line that is giving me trouble!
set-default-shape turtles "person"
create-turtles 100
end
to setup
ca
resize-world 0 1000 0 1000
;set-lago
; set-predios
set-houses
reset-ticks
end
It is a lot, and unfortunately i dont know how to show you a picture. Any guidance will be appreciated as Im really lost. Thanks in advance.
Edit: Now the names are in English, Tota is the name of the lake in question. Thanks Matteo for the tip.
What I know about your problem indicates that there is not always a patch that fulfills the requirements of min-one-of patches with [tota = 1] [distance myself]. You could try running the code with an added if statement to check for that.
ifelse any? patches with [tota = 1] [
set distancia_agua distance min-one-of patches with [tota = 1] [distance myself]
] [
set distancia_agua "na"
]
As an edit based on your comment:
In order to reduce the number of operations I introduced let tota-edge <...>. This means that you check only once which patches qualify as tota rather than doing it 1002001 times (since every single patch would do this same operation). So 1002001 times instead of 1.004006e+12.
I don't know how big tota itself is but if it is a sizable portion of the world, ask patches with [tota != 1] will speed up your program some more. Finally, I only used the edges of tota since the middle of the lake is never the closest part of the lake to a non-lake patch.
ifelse any? patches with [tota = 1] [
let tota-edge patches with [tota = 1 and any? neighbors with [tota != 1]]
ask patches with [tota != 1] [ set distancia_agua distance min-one-of tota-edge [distance myself] ]
ask patches with [tota = 1] [ set distancia_agua 0 ]
] [
ask patches [ set distancia_agua "na" ]
]

How to automatically crop an .OBJ 3D model to a bounding box?

In the now obsoleted Autodesk ReCap API it was possible to specify a "bounding box" around the scene to be generated from images.
In the resulting models, any vertices outside the bounding box were discarded, and any volumes that extended beyond the bounding box were truncated to have faces at the box boundaries.
I am now using Autodesk's Forge Reality Capture API which replaced ReCap. Apparently, This new API does not allow the user to specify a bounding box.
So I am now searching for a program that takes an .OBJ file and a specified bounding box as input, and outputs a file of just the vertices and faces within this bounding box.
Given that there is no way to specify the bounding box in Reality Capture API, I created this python program. It is crude, in that it only discards faces that have vertices that are outside the bounding box. And it actually does discards nondestructively, only by commenting them out in the output OBJ file. This allows you to uncomment them and then use a different bounding box.
This may not be what you need if you truly want to remove all relevant v, vn, vt, vp and f lines that are outside the bounding box, because the OBJ file size remains mostly unchanged. But for my particular needs, keeping all the records and just using comments was preferable.
# obj3Dcrop.py
# (c) Scott L. McGregor, Dec 2019
# License: free for all non commercial uses. Contact author for any other uses.
# Changes and Enhancements must be shared with author, and be subject to same use terms
# TL;DR: This program uses a bounding box, and "crops" faces and vertices from a
# Wavefront .OBJ format file, created by Autodesk Forge Reality Capture API
# if one of the vertices in a face is not within the bounds of the box.
#
# METHOD
# 1) All lines other than "v" vertex definitions and "f" faces definitions
# are copied UNCHANGED from the input .OBJ file to an output .OBJ file.
# 2) All "v" vertex definition lines have their (x, y, z) positions tested to see if:
# minX < x < maxX and minY < y < maxY and minZ < z < maxZ ?
# If TRUE, we want to keep this vertex in the new OBJ, so we
# store its IMPLICIT ORDINAL position in the file in a dictionary called v_keepers.
# If FALSE, we will use its absence from the v_keepers file as a way to identify
# faces that contain it and drop them. All "v" lines are also copied unchanged to the
# output file.
# 3) All "f" lines (face definitions) are inspected to verify that all 3 vertices in the face
# are in the v_keepers list. If they are, the f line is output unchanged.
# 4) Any "f" line that refers to a vertex that was cropped, is prefixed by "# CROPPED: "
# in the output file. Lines beginning # are treated as comments, and ignored in future
# processing.
# KNOWN LIMITATIONS: This program generates models in which the outside of bound faces
# have been removed. The vertices that were found outside the bounding box, are still in the
# OBJ file, but they are now disconnected and therefore ignored in later processing.
# The "f" lines for faces with vertices outside the bounding box are also still in the
# output file, but now commented out, so they don't process. Because this is non-destructive.
# we can easily change our bounding box later, uncomment cropped lines and reprocess.
#
# This might be an incomplete solution for some potential users. For such users
# a more complete program would delete unneeded v, vn, vt and vp lines when the v vertex
# that they refer to is dropped. But note that this requires renumbering all references to these
# vertice definitions in the "f" face definition lines. Such a more complete solution would also
# DISCARD all 'f' lines with any vertices that are out of bounds, instead of making them copies.
# Such a rewritten .OBJ file would be var more compact, but changing the bounding box would require
# saving the pre-cropped original.
# QUIRK: The OBJ file format defines v, vn, vt, vp and f elements by their
# IMPLICIT ordinal occurrence in the file, with each element type maintaining
# its OWN separate sequence. It then references those definitions EXPLICITLY in
# f face definitions. So deleting (or commenting out) element references requires
# appropriate rewriting of all the"f"" lines tracking all the new implicit positions.
# Such rewriting is not particularly hard to do, but it is one more place to make
# a mistake, and could make the algorithm more complicated to understand.
# This program doesn't bother, because all further processing of the output
# OBJ file ignores unreferenced v, vn, vt and vp elements.
#
# Saving all lines rather than deleting them to save space is a tradeoff involving considerations of
# Undo capability, compute cycles, compute space (unreferenced lines) and maintenance complexity choice.
# It is left to the motivated programmer to add this complexity if needed.
import sys
#bounding_box = sys.argv[1] # should be in the only string passsed (maxX, maxY, maxZ, minX, minY, minZ)
bounding_box = [10, 10, 10, -10, -10, 1]
maxX = bounding_box[0]
maxY = bounding_box[1]
maxZ = bounding_box[2]
minX = bounding_box[3]
minY = bounding_box[4]
minZ = bounding_box[5]
v_keepers = dict() # keeps track of which vertices are within the bounding box
kept_vertices = 0
discarded_vertices = 0
kept_faces = 0
discarded_faces = 0
discarded_lines = 0
kept_lines = 0
obj_file = open('sample.obj','r')
new_obj_file = open('cropped.obj','w')
# the number of the next "v" vertex lines to process.
original_v_number = 1 # the number of the next "v" vertex lines to process.
new_v_number = 1 # the new ordinal position of this vertex if out of bounds vertices were discarded.
for line in obj_file:
line_elements = line.split()
# Python doesn't have a SWITCH statement, but we only have three cases, so we'll just use cascading if stmts
if line_elements[0] != "f": # if it isn't an "f" type line (face definition)
if line_elements[0] != "v": # and it isn't an "v" type line either (vertex definition)
# ************************ PROCESS ALL NON V AND NON F LINE TYPES ******************
# then we just copy it unchanged from the input OBJ to the output OBJ
new_obj_file.write(line)
kept_lines = kept_lines + 1
else: # then line_elements[0] == "v":
# ************************ PROCESS VERTICES ****************************************
# a "v" line looks like this:
# f x y z ...
x = float(line_elements[1])
y = float(line_elements[2])
z = float(line_elements[3])
if minX < x < maxX and minY < y < maxY and minZ < z < maxZ:
# if vertex is within the bounding box, we include it in the new OBJ file
new_obj_file.write(line)
v_keepers[str(original_v_number)] = str(new_v_number)
new_v_number = new_v_number + 1
kept_vertices = kept_vertices +1
kept_lines = kept_lines + 1
else: # if vertex is NOT in the bounding box
new_obj_file.write(line)
discarded_vertices = discarded_vertices +1
discarded_lines = discarded_lines + 1
original_v_number = original_v_number + 1
else: # line_elements[0] == "f":
# ************************ PROCESS FACES ****************************************
# a "f" line looks like this:
# f v1/vt1/vn1 v2/vt2/vn2 v3/vt3/vn3 ...
# We need to delete any face lines where ANY of the 3 vertices v1, v2 or v3 are NOT in v_keepers.
v = ["", "", ""]
# Note that v1, v2 and v3 are the first "/" separated elements within each line element.
for i in range(0,3):
v[i] = line_elements[i+1].split('/')[0]
# now we can check if EACH of these 3 vertices are in v_keepers.
# for each f line, we need to determine if all 3 vertices are in the v_keepers list
if v[0] in v_keepers and v[1] in v_keepers and v[2] in v_keepers:
new_obj_file.write(line)
kept_lines = kept_lines + 1
kept_faces = kept_faces +1
else: # at least one of the vertices in this face has been deleted, so we need to delete the face too.
discarded_lines = discarded_lines + 1
discarded_faces = discarded_faces +1
new_obj_file.write("# CROPPED "+line)
# end of line processing loop
obj_file.close()
new_obj_file.close()
print ("kept vertices: ", kept_vertices ,"discarded vertices: ", discarded_vertices)
print ("kept faces: ", kept_faces, "discarded faces: ", discarded_faces)
print ("kept lines: ", kept_lines, "discarded lines: ", discarded_lines)
Unfortunately, (at least for now) there is no way to specify the bounding box in Reality Capture API.

NetLogo, how to hatch a turtle at a certain distance on Gis layers

My patches contain attributes such as elevation :
set mnt gis:load-dataset "F:/StageM2/Modelisation/Modele/mnt.asc"
gis:apply-raster mnt alt
gis:set-transformation (list 567887.504252 573503.504252 6183200.86463 6187628.86463) (list min-pxcor max-pxcor min-pycor max-pycor)
gis:set-world-envelope gis:envelope-of mnt
and turtles are created from raster of forest :
to import-foret93
set foret-93 gis:load-dataset "F:/StageM2/Modelisation/Modele/foret76_93.asc"
gis:apply-raster foret-93 f93
ask patches with [f93 = 1]
[
set pcolor black
set foret93? true
;ask n-of 2813 patches with [foret93? = true] [ hatch 2813 ]
sprout-arbres 1 [set color pink
set size 4]
]
end
The layers have the same spatial reference : RGF1993, so it is in meters.
Now, I want to create new turtles from existing turtles and randomly in a radius of 150m from the turtle (the new turtle can be hatch at 1m or at 130m). For instance, I ask just one turtle to hatch a turtle at a distance giving by an input box in the interface named dispersal-dist.
to disp-graines
ask turtle 2918
[
hatch-arbres 1
[
let seedX xcor
let seedY ycor
let ran-bear random 360
lt ran-bear
move-to one-of patches in-radius dispersal-dist
set color magenta
set size 15
]
]
end
But the created turtle go further then the dispersal distance giving in meters.
Did I forget something to transforme the netlogo scale in meters ? Or it is another problem?
Thank you in advance for your help !
While your raster dataset is expressed in meters in your case, your patches don't have a real world scale. Assuming your raster has square pixels, you can calculate a patch scale with something like:
let patch-scale (item 1 gis:world-envelope - item 0 gis:world-envelope ) / world-width
You could then use it in your existing code:
move-to one-of patches in-radius dispersal-dist / patch-scale
If your pixels in your raster have different real world height and width, you will have to do the patch-scale for the horizontal and vertical dimension separately.

NetLogo - applying values to patches within polygons

I have animals walk around and a line then connects all the locations that they walked to. The line forms a closed polygon. I also used the graphics extension to fill the polygon for visual purposes. But I don't know how to have all of the patches that fall within the polygon become the territory of the owner (i.e., the animal that formed the polygon). It is possible for patches to be owned by multiple animals. The code below illustrates overlapping polygons. I'd really appreciate any help on this. Thanks!
extensions [graphics]
breed [animals animal]
breed [homeranges homerange]
animals-own
[
Name
X
Y
]
patches-own
[
owner
]
homeranges-own
[
Name
]
to setup
clear-all
random-seed 4
ask patches
[
set owner nobody
set pcolor grey
]
let $colors [brown orange violet sky lime]
let $Name ["t6" "t7" "t8" "t9" "t10"]
ask n-of 5 patches with [(pycor < 10 and pycor > -10) and (pxcor < 10 and pxcor > -10)]
[
sprout-animals 1
[
set shape "circle"
set color item who $colors
set pcolor color
set X (list xcor)
set Y (list ycor)
set Name item who $Name
set owner self
]
]
graphics:initialize min-pxcor max-pycor patch-size
reset-ticks
end
to go
repeat 5
[
ask animals
[
rt 45
fd 2
set X lput pxcor X
set Y lput pycor Y
set pcolor [color] of self
]
]
ask animals
[
pen-up
let tempXY (map [list ?1 ?2] X Y)
graphics:fill-polygon tempXY
; create a turtle, which draws the homerange boundary
hatch-homeranges 1
[
hide-turtle
set Name [Name] of myself
set color [color] of myself
]
; draw the homerange boundary
foreach tempXY
[
ask homeranges with [Name = [Name] of myself]
[
move-to patch (item 0 ?) (item 1 ?)
pen-down
]
]
; connect the last point of the homerange with the first one, to close the polygon
ask homeranges with [Name = [Name] of myself]
[
let lastpoint first tempXY
move-to patch (item 0 lastpoint) (item 1 lastpoint)
]
]
end
If you look at http://netlogo-users.18673.x6.nabble.com/Netlogo-Point-in-Polygon-td4980030.html you'll find a past (2012) discussion of solutions to this problem.
At the end of the thread, Jim Lyons posts a link to a model on the Modeling Commons, but the model doesn't seem to exist there anymore. He's here on Stack Overflow if you want to ask him about it.
An answer was provided in this post: NetLogo - misalignment with imported GIS shapefiles. The polygons are exported as a GIS shapefile and imported back in using the GIS extension. Then the gis:intersecting was used to give a variable to those patches that fall within the GIS-imported polygons.