Opened 5 years ago

Closed 4 years ago

#3926 closed enhancement (fixed)

allow limit viewshed computation by angle

Reported by: annakrat Owned by: grass-dev@…
Priority: normal Milestone: 8.0.0
Component: Raster Version: unspecified
Keywords: r.viewshed, viewshed Cc:
CPU: All Platform: All

Description

r.viewshed should allow to restrict the computation to range of angles, e.g. to simulate human field of view.

Change History (4)

comment:1 by annakrat, 5 years ago

For the record, this is my attempt with hardcoded values, which fails with angle 1 to 270 (the viewshed is written but incorrect). Interestingly, it works with angle 0 to 270.

index 95ecd47..94d0741 100644
--- a/raster/r.viewshed/eventlist.cpp
+++ b/raster/r.viewshed/eventlist.cpp
@@ -605,7 +605,20 @@ int is_point_outside_max_dist(Viewpoint vp, GridHeader hd,
     return 0;
 }
 
+int is_point_inside_angle(Viewpoint vp,
+                         dimensionType row, dimensionType col,
+                         float minAngle, float maxAngle)
+{
+    double ang;
+
+    ang = atan2(vp.row -row, col - vp.col) * 180 / M_PI;
+    if (ang < 0)
+        ang += 360;
+    if (ang < minAngle || ang > maxAngle)
+        return 0;
 
+    return 1;
+}
 
 /* ------------------------------------------------------------ 
    //note: this is expensive because distance is not stored in the event
diff --git a/raster/r.viewshed/eventlist.h b/raster/r.viewshed/eventlist.h
index e071687..234e700 100644
--- a/raster/r.viewshed/eventlist.h
+++ b/raster/r.viewshed/eventlist.h
@@ -74,7 +74,9 @@ is_point_outside_max_dist(Viewpoint vp, GridHeader hd,
                          dimensionType row, dimensionType col,
                          float maxDist);
 
-
+int is_point_inside_angle(Viewpoint vp,
+                         dimensionType row, dimensionType col,
+                         float minAngle, float maxAngle);
 
 /*sort the event list by the angle around the viewpoint) */
 void sort_event_list(AMI_STREAM < AEvent > **eventList);
diff --git a/raster/r.viewshed/grass.cpp b/raster/r.viewshed/grass.cpp
index b9dac21..d5fa240 100644
--- a/raster/r.viewshed/grass.cpp
+++ b/raster/r.viewshed/grass.cpp
@@ -316,6 +316,11 @@ init_event_list_in_memory(AEvent * eventList, char *rastName,
                (*vp, *hd, i, j, viewOptions.maxDist))
                continue;
 
+           if (!is_point_inside_angle(*vp, i, j, 1, 270)) {
+               add_result_to_inmem_visibilitygrid(visgrid, i, j,
+                                                  hd->nodata_value);
+               continue;
+           }
            /* if it got here it is not the viewpoint, not NODATA, and
               within max distance from viewpoint; generate its 3 events
               and insert them */

in reply to:  1 comment:2 by mmetz, 4 years ago

Replying to annakrat:

For the record, this is my attempt with hardcoded values, which fails with angle 1 to 270 (the viewshed is written but incorrect). Interestingly, it works with angle 0 to 270.

Your PR #180 works for me. I tested in the NC dataset with

g.region -p rast=elev_state_500m
r.viewshed in=elev_state_500m out=viewshed coord=637942.9512846764,188095.68718268772 obs=100 direction_range=0,270
r.viewshed in=elev_state_500m out=viewshed coord=637942.9512846764,188095.68718268772 obs=100 direction_range=1,270
r.viewshed in=elev_state_500m out=viewshed coord=637942.9512846764,188095.68718268772 obs=100 direction_range=270,0
r.viewshed in=elev_state_500m out=viewshed coord=637942.9512846764,188095.68718268772 obs=100 direction_range=270,1

and the results seem to be correct.

Can you provide an example where your PR does not work?

comment:4 by annakrat, 4 years ago

Resolution: fixed
Status: newclosed
Note: See TracTickets for help on using tickets.