### integer_graticule.makefile --- Make an (integer only) graticule
## Author: Dan Jacobson https://www.jidanni.org/
## Copyright: https://www.gnu.org/licenses/gpl.html
## Created: 2026-03-30T21:18:13+0000
## Last-Updated: 2026-05-07T10:39:20+0000
##     Update #: 73

# Note that as we are making house number grids, and house numbers are
# _usually_ integers and not finer grained, we can get away with just
# using the Linix shells' integer arithmetic.

#Put something like this in your Makefile:
#E.g., a very fine grained grid for just part of a city block:
#interval=1
#_x = x0=3225 xi=$(interval) x1=3244
#_y = y0=7376 yi=$(interval) y1=7377
#Then in your Makefile do: include integer_graticule.makefile .

#We are going to use Unix seq(1), so we want to count up, not down or
#all around, please!
_w = #Hook for a WHERE clause.
counting_upward_check%: _m=Man, you are rather non-intellegent. You can\'t even count upward...
counting_upward_check%:
	$(_x); test $$x1 -gt $$x0
	$(_y); test $$y1 -gt $$y0

#Want intervals that make sense:
interval_non_zero_check%:
	$(_x); test $$xi -gt 0
	$(_y); test $$yi -gt 0

#Be sure there is no remainder after the last lines, else there will
#be ugly (usually uneven too) tic-tac-toe (#)（井） edges sticking out
#beyond the border of our graticule. (Which is formed by the first and
#last perpendicular lines.)
remainder_check%: _m=\
Do you realize that the interval you chose for this side doesn\'t \
coincide with your choice of start and end? Just like if you went to \
the store and bought floor tiles but the last one doesn\'t fit!
remainder_check%:
	set -eu; $(_x); ! expr \( $$x1 - $$x0 \) \* 10 / $$xi % 10 \
	> /dev/null ||{ echo "$(_m)" 1>&2; exit 11;}
	set -eu; $(_y); ! expr \( $$y1 - $$y0 \) \* 10 / $$yi % 10 \
	> /dev/null ||{ echo "$(_m)" 1>&2; exit 11;}
#GPX/KML etc. renderers like Viking will place labels (if the user has
#turned them on) e.g., right at the middle of a line. That's great
#except when there is a perpendicular line that just happens to cross
#at the same point as one of those labels. Then the person reading the
#map cannot tell which line the label belongs to!:

thickness_check%: _m=\
Gosh you will need some thickness to your grid, else, well, you need to fix \
these algorithms to handle just making a line.
thickness_check%:
	set -eu; $(_x); expr $$x1 - $$x0 \
	> /dev/null ||{ echo X: "$(_m)" 1>&2; exit 11;}
	set -eu; $(_y); expr $$y1 - $$y0 \
	> /dev/null ||{ echo Y: "$(_m)" 1>&2; exit 11;}

##lots of segments to ensure e.g., Viking makes labels on each segment
_ii=\
for $(1) in `seq $$$(1)0 $$$(1)i $$$(1)1`; do \
  for $(2) in `seq $$$(2)0 $$$(2)i $$$(2)1`; do \
    echo $$x,$$y,$$$(1); done; done
graticule_i%.csv: remainder_check% thickness_check%
	{ set -eu; $(_x) $(_y); echo x,y,name; \
	$(call _ii,x,y); $(call _ii,y,x);} > $@
graticule_i%.gpkg:graticule_i%.csv
	ogr2ogr $@ $< -nln $(basename $@) \
	-nlt LINESTRING -oo KEEP_GEOM_COLUMNS=NO \
	-dialect SQLite -sql \
	"SELECT MakeLine(MakePoint(x+0,y+0)) "\
	"AS geom, name + 0 AS name FROM $N $(_w) "\
	"GROUP BY name + 0 ORDER BY name + 0"
#And here's the final product, with labels on all sides of every
#rectangle! Also no checks needed:
graticule_k%.gpkg:graticule_i%.gpkg #Beautiful!:
	ogr2ogr $@ $< -nln $(basename $@) \
	-nlt LINESTRING -explodecollections \
	-dialect SQLite -sql \
	"SELECT ST_DissolveSegments(geom) AS geom,"\
	"name FROM $N $(_w) ORDER BY name + 0"
#ToDo: What about offsets? What if we want lines at 150, 250, 350?
#Current workaround: OK, we could make them every 50, and then cancel
#out the ones where mod 100 = 0. But the labels remain...
#Also what if we want 100 133 167 200...? But we only are using integers...

#Yes, we are using only early sh(1) features, for maximum portability!

one_line%.gpkg: #could one day also split into segments for more labels.
	set -xeu; $(params); ogr2ogr $@ :memory: -nln $(basename $@) $S \
	"SELECT $$name AS name,"\
	"ST_Segmentize(MakeLine(ST_Point($$x0,$$y0),ST_Point($$x1,$$y1)),$$i) AS geom"
#Example:
#one_line_y.%: params= x0=0 x1=0 y0=-5000 y1=5000 i=500 name=0
#one_line_y.kml:
