diff --git a/.gitignore b/.gitignore
index c2658d7..3e21bcc 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,3 @@
node_modules/
+regions/
+region-raw-image/
diff --git a/exps.json b/exps.json
deleted file mode 100644
index 61bfc2b..0000000
--- a/exps.json
+++ /dev/null
@@ -1 +0,0 @@
-{"region-pin0-exp0":{"exp_id":"region-pin0-exp0","label":"region-pin0-exp0","state":"expired","start":"2016/11/08 14:30:00","end":"2016/11/08 15:00:00","hero_photo":3,"content":"this is the text description","pin_id":null},"region-pin0-exp1":{"exp_id":"region-pin0-exp1","label":"region-pin0-exp1","state":"current","start":"2016/11/14 21:47:46","end":"2016/11/14 22:24:21","hero_photo":4,"content":"this is the text description","pin_id":null},"region-pin0-exp2":{"exp_id":"region-pin0-exp2","label":"region-pin0-exp2","state":"current","start":"2016/11/14 21:31:18","end":"2016/11/14 22:42:19","hero_photo":1,"content":"this is the text description","pin_id":null},"region-pin1-exp0":{"exp_id":"region-pin1-exp0","label":"region-pin1-exp0","state":"current","start":"2016/11/14 20:09:56","end":"2016/11/15 00:16:08","hero_photo":1,"content":"this is the text description","pin_id":null},"region-pin2-exp0":{"exp_id":"region-pin2-exp0","label":"region-pin2-exp0","state":"expired","start":"2016/11/08 14:30:00","end":"2016/11/08 15:00:00","hero_photo":4,"content":"this is the text description","pin_id":null},"region-pin2-exp1":{"exp_id":"region-pin2-exp1","label":"Label only","content":"this is the text description","pin_id":null},"region-pin2-exp2":{"exp_id":"region-pin2-exp2","label":"Label only","content":"this is the text description","pin_id":null},"region-pin2-exp3":{"exp_id":"region-pin2-exp3","label":"region-pin2-exp3","state":"current","start":"2016/11/14 21:31:05","end":"2016/11/14 22:32:09","hero_photo":2,"content":"this is the text description","pin_id":null},"region-pin3-exp0":{"exp_id":"region-pin3-exp0","label":"Label only","content":"this is the text description","pin_id":null},"region-pin3-exp1":{"exp_id":"region-pin3-exp1","label":"region-pin3-exp1","state":"current","start":"2016/11/14 21:06:17","end":"2016/11/15 02:49:31","hero_photo":4,"content":"this is the text description","pin_id":null},"region-pin3-exp2":{"exp_id":"region-pin3-exp2","label":"region-pin3-exp2","state":"current","start":"2016/11/14 21:01:52","end":"2016/11/14 23:55:07","hero_photo":2,"content":"this is the text description","pin_id":null},"region-pin4-exp0":{"exp_id":"region-pin4-exp0","label":"region-pin4-exp0","state":"current","start":"2016/11/14 21:08:31","end":"2016/11/15 01:06:10","hero_photo":4,"content":"this is the text description","pin_id":null},"region-pin4-exp1":{"exp_id":"region-pin4-exp1","label":"region-pin4-exp1","state":"current","start":"2016/11/14 21:29:12","end":"2016/11/14 23:38:55","hero_photo":1,"content":"this is the text description","pin_id":null},"region-pin5-exp0":{"exp_id":"region-pin5-exp0","label":"region-pin5-exp0","state":"expired","start":"2016/11/08 14:30:00","end":"2016/11/08 15:00:00","hero_photo":4,"content":"this is the text description","pin_id":null},"region-pin5-exp1":{"exp_id":"region-pin5-exp1","label":"Label only","content":"this is the text description","pin_id":null},"region-pin5-exp2":{"exp_id":"region-pin5-exp2","label":"region-pin5-exp2","state":"current","start":"2016/11/14 20:17:16","end":"2016/11/15 01:34:25","hero_photo":4,"content":"this is the text description","pin_id":null},"region-pin5-exp3":{"exp_id":"region-pin5-exp3","label":"region-pin5-exp3","state":"current","start":"2016/11/14 20:00:28","end":"2016/11/15 02:08:07","hero_photo":3,"content":"this is the text description","pin_id":null},"region-pin6-exp0":{"exp_id":"region-pin6-exp0","label":"Label only","content":"this is the text description","pin_id":null},"region-pin6-exp1":{"exp_id":"region-pin6-exp1","label":"region-pin6-exp1","state":"current","start":"2016/11/14 21:51:46","end":"2016/11/14 22:50:20","hero_photo":4,"content":"this is the text description","pin_id":null},"region-pin7-exp0":{"exp_id":"region-pin7-exp0","label":"region-pin7-exp0","state":"expired","start":"2016/11/08 14:30:00","end":"2016/11/08 15:00:00","hero_photo":3,"content":"this is the text description","pin_id":null},"region-pin7-exp1":{"exp_id":"region-pin7-exp1","label":"region-pin7-exp1","state":"current","start":"2016/11/14 21:19:05","end":"2016/11/15 00:01:13","hero_photo":3,"content":"this is the text description","pin_id":null},"region-pin7-exp2":{"exp_id":"region-pin7-exp2","label":"region-pin7-exp2","state":"current","start":"2016/11/14 21:16:55","end":"2016/11/14 22:52:13","hero_photo":3,"content":"this is the text description","pin_id":null},"region-pin7-exp3":{"exp_id":"region-pin7-exp3","label":"region-pin7-exp3","state":"current","start":"2016/11/14 21:43:03","end":"2016/11/14 22:57:12","hero_photo":2,"content":"this is the text description","pin_id":null},"region-pin8-exp0":{"exp_id":"region-pin8-exp0","label":"region-pin8-exp0","state":"current","start":"2016/11/14 20:56:08","end":"2016/11/15 00:15:54","hero_photo":4,"content":"this is the text description","pin_id":null},"region-pin8-exp1":{"exp_id":"region-pin8-exp1","label":"region-pin8-exp1","state":"current","start":"2016/11/14 20:25:28","end":"2016/11/15 02:26:26","hero_photo":3,"content":"this is the text description","pin_id":null},"region-pin8-exp2":{"exp_id":"region-pin8-exp2","label":"region-pin8-exp2","state":"current","start":"2016/11/14 21:54:40","end":"2016/11/15 01:07:44","hero_photo":3,"content":"this is the text description","pin_id":null},"region-pin9-exp0":{"exp_id":"region-pin9-exp0","label":"region-pin9-exp0","state":"current","start":"2016/11/14 21:58:09","end":"2016/11/14 22:24:23","hero_photo":3,"content":"this is the text description","pin_id":null},"region-pin9-exp1":{"exp_id":"region-pin9-exp1","label":"region-pin9-exp1","state":"expired","start":"2016/11/08 14:30:00","end":"2016/11/08 15:00:00","hero_photo":1,"content":"this is the text description","pin_id":null},"region-pin9-exp2":{"exp_id":"region-pin9-exp2","label":"region-pin9-exp2","state":"current","start":"2016/11/14 20:59:44","end":"2016/11/14 23:39:29","hero_photo":2,"content":"this is the text description","pin_id":null},"region-pin9-exp3":{"exp_id":"region-pin9-exp3","label":"region-pin9-exp3","state":"expired","start":"2016/11/08 14:30:00","end":"2016/11/08 15:00:00","hero_photo":2,"content":"this is the text description","pin_id":null},"region-pin10-exp0":{"exp_id":"region-pin10-exp0","label":"Label only","content":"this is the text description","pin_id":null},"region-pin11-exp0":{"exp_id":"region-pin11-exp0","label":"region-pin11-exp0","state":"current","start":"2016/11/14 20:36:44","end":"2016/11/14 22:54:32","hero_photo":3,"content":"this is the text description","pin_id":null},"region-pin11-exp1":{"exp_id":"region-pin11-exp1","label":"region-pin11-exp1","state":"expired","start":"2016/11/08 14:30:00","end":"2016/11/08 15:00:00","hero_photo":3,"content":"this is the text description","pin_id":null},"region-pin12-exp0":{"exp_id":"region-pin12-exp0","label":"region-pin12-exp0","state":"current","start":"2016/11/14 20:08:26","end":"2016/11/15 00:46:02","hero_photo":2,"content":"this is the text description","pin_id":null},"region-pin12-exp1":{"exp_id":"region-pin12-exp1","label":"region-pin12-exp1","state":"current","start":"2016/11/14 20:02:39","end":"2016/11/15 02:25:00","hero_photo":1,"content":"this is the text description","pin_id":null},"region-pin12-exp2":{"exp_id":"region-pin12-exp2","label":"region-pin12-exp2","state":"expired","start":"2016/11/08 14:30:00","end":"2016/11/08 15:00:00","hero_photo":4,"content":"this is the text description","pin_id":null},"region-pin13-exp0":{"exp_id":"region-pin13-exp0","label":"region-pin13-exp0","state":"current","start":"2016/11/14 21:32:46","end":"2016/11/15 01:10:37","hero_photo":1,"content":"this is the text description","pin_id":null},"region-pin13-exp1":{"exp_id":"region-pin13-exp1","label":"region-pin13-exp1","state":"expired","start":"2016/11/08 14:30:00","end":"2016/11/08 15:00:00","hero_photo":3,"content":"this is the text description","pin_id":null},"region-pin13-exp2":{"exp_id":"region-pin13-exp2","label":"Label only","content":"this is the text description","pin_id":null},"region-pin13-exp3":{"exp_id":"region-pin13-exp3","label":"Label only","content":"this is the text description","pin_id":null},"region-pin14-exp0":{"exp_id":"region-pin14-exp0","label":"region-pin14-exp0","state":"expired","start":"2016/11/08 14:30:00","end":"2016/11/08 15:00:00","hero_photo":3,"content":"this is the text description","pin_id":null},"region-pin14-exp1":{"exp_id":"region-pin14-exp1","label":"region-pin14-exp1","state":"expired","start":"2016/11/08 14:30:00","end":"2016/11/08 15:00:00","hero_photo":2,"content":"this is the text description","pin_id":null},"region-pin14-exp2":{"exp_id":"region-pin14-exp2","label":"region-pin14-exp2","state":"expired","start":"2016/11/08 14:30:00","end":"2016/11/08 15:00:00","hero_photo":2,"content":"this is the text description","pin_id":null},"region-pin14-exp3":{"exp_id":"region-pin14-exp3","label":"region-pin14-exp3","state":"expired","start":"2016/11/08 14:30:00","end":"2016/11/08 15:00:00","hero_photo":2,"content":"this is the text description","pin_id":null},"region-pin15-exp0":{"exp_id":"region-pin15-exp0","label":"region-pin15-exp0","state":"current","start":"2016/11/14 20:50:33","end":"2016/11/14 22:48:02","hero_photo":4,"content":"this is the text description","pin_id":null},"region-pin15-exp1":{"exp_id":"region-pin15-exp1","label":"region-pin15-exp1","state":"expired","start":"2016/11/08 14:30:00","end":"2016/11/08 15:00:00","hero_photo":3,"content":"this is the text description","pin_id":null},"region-pin15-exp2":{"exp_id":"region-pin15-exp2","label":"region-pin15-exp2","state":"expired","start":"2016/11/08 14:30:00","end":"2016/11/08 15:00:00","hero_photo":2,"content":"this is the text description","pin_id":null},"region-pin15-exp3":{"exp_id":"region-pin15-exp3","label":"region-pin15-exp3","state":"current","start":"2016/11/14 21:51:51","end":"2016/11/15 02:20:27","hero_photo":3,"content":"this is the text description","pin_id":null},"region-pin16-exp0":{"exp_id":"region-pin16-exp0","label":"region-pin16-exp0","state":"expired","start":"2016/11/08 14:30:00","end":"2016/11/08 15:00:00","hero_photo":1,"content":"this is the text description","pin_id":null},"region-pin16-exp1":{"exp_id":"region-pin16-exp1","label":"region-pin16-exp1","state":"current","start":"2016/11/14 20:53:18","end":"2016/11/15 02:15:00","hero_photo":1,"content":"this is the text description","pin_id":null},"region-pin17-exp0":{"exp_id":"region-pin17-exp0","label":"region-pin17-exp0","state":"current","start":"2016/11/14 20:40:21","end":"2016/11/15 01:07:01","hero_photo":3,"content":"this is the text description","pin_id":null},"region-pin18-exp0":{"exp_id":"region-pin18-exp0","label":"region-pin18-exp0","state":"current","start":"2016/11/14 21:51:58","end":"2016/11/15 02:14:43","hero_photo":3,"content":"this is the text description","pin_id":null},"region-pin18-exp1":{"exp_id":"region-pin18-exp1","label":"Label only","content":"this is the text description","pin_id":null},"region-pin19-exp0":{"exp_id":"region-pin19-exp0","label":"region-pin19-exp0","state":"expired","start":"2016/11/08 14:30:00","end":"2016/11/08 15:00:00","hero_photo":1,"content":"this is the text description","pin_id":null},"region-pin19-exp1":{"exp_id":"region-pin19-exp1","label":"Label only","content":"this is the text description","pin_id":null},"region-pin19-exp2":{"exp_id":"region-pin19-exp2","label":"region-pin19-exp2","state":"current","start":"2016/11/14 20:50:36","end":"2016/11/14 22:15:05","hero_photo":4,"content":"this is the text description","pin_id":null},"region-pin20-exp0":{"exp_id":"region-pin20-exp0","label":"region-pin20-exp0","state":"current","start":"2016/11/14 21:11:30","end":"2016/11/15 02:56:23","hero_photo":4,"content":"this is the text description","pin_id":null},"region-pin20-exp1":{"exp_id":"region-pin20-exp1","label":"region-pin20-exp1","state":"current","start":"2016/11/14 21:06:08","end":"2016/11/15 00:15:56","hero_photo":1,"content":"this is the text description","pin_id":null},"region-pin21-exp0":{"exp_id":"region-pin21-exp0","label":"region-pin21-exp0","state":"expired","start":"2016/11/08 14:30:00","end":"2016/11/08 15:00:00","hero_photo":3,"content":"this is the text description","pin_id":null},"region-pin21-exp1":{"exp_id":"region-pin21-exp1","label":"region-pin21-exp1","state":"current","start":"2016/11/14 21:22:36","end":"2016/11/15 00:07:44","hero_photo":3,"content":"this is the text description","pin_id":null},"region-pin21-exp2":{"exp_id":"region-pin21-exp2","label":"region-pin21-exp2","state":"expired","start":"2016/11/08 14:30:00","end":"2016/11/08 15:00:00","hero_photo":1,"content":"this is the text description","pin_id":null},"region-pin22-exp0":{"exp_id":"region-pin22-exp0","label":"Label only","content":"this is the text description","pin_id":null},"region-pin23-exp0":{"exp_id":"region-pin23-exp0","label":"region-pin23-exp0","state":"expired","start":"2016/11/08 14:30:00","end":"2016/11/08 15:00:00","hero_photo":4,"content":"this is the text description","pin_id":null},"region-pin23-exp1":{"exp_id":"region-pin23-exp1","label":"region-pin23-exp1","state":"current","start":"2016/11/14 21:34:01","end":"2016/11/15 02:09:53","hero_photo":1,"content":"this is the text description","pin_id":null},"region-pin24-exp0":{"exp_id":"region-pin24-exp0","label":"region-pin24-exp0","state":"expired","start":"2016/11/08 14:30:00","end":"2016/11/08 15:00:00","hero_photo":3,"content":"this is the text description","pin_id":null},"region-pin25-exp0":{"exp_id":"region-pin25-exp0","label":"region-pin25-exp0","state":"current","start":"2016/11/14 21:06:06","end":"2016/11/14 22:51:22","hero_photo":4,"content":"this is the text description","pin_id":null},"region-pin25-exp1":{"exp_id":"region-pin25-exp1","label":"region-pin25-exp1","state":"current","start":"2016/11/14 20:42:20","end":"2016/11/15 00:34:14","hero_photo":3,"content":"this is the text description","pin_id":null},"region-pin25-exp2":{"exp_id":"region-pin25-exp2","label":"region-pin25-exp2","state":"expired","start":"2016/11/08 14:30:00","end":"2016/11/08 15:00:00","hero_photo":3,"content":"this is the text description","pin_id":null},"region-pin26-exp0":{"exp_id":"region-pin26-exp0","label":"Label only","content":"this is the text description","pin_id":null},"region-pin26-exp1":{"exp_id":"region-pin26-exp1","label":"Label only","content":"this is the text description","pin_id":null},"region-pin26-exp2":{"exp_id":"region-pin26-exp2","label":"region-pin26-exp2","state":"current","start":"2016/11/14 21:58:58","end":"2016/11/14 23:12:18","hero_photo":3,"content":"this is the text description","pin_id":null},"region-pin26-exp3":{"exp_id":"region-pin26-exp3","label":"Label only","content":"this is the text description","pin_id":null},"region-pin27-exp0":{"exp_id":"region-pin27-exp0","label":"region-pin27-exp0","state":"current","start":"2016/11/14 20:50:23","end":"2016/11/15 01:44:05","hero_photo":3,"content":"this is the text description","pin_id":null},"region-pin28-exp0":{"exp_id":"region-pin28-exp0","label":"region-pin28-exp0","state":"current","start":"2016/11/14 21:13:57","end":"2016/11/14 22:52:47","hero_photo":1,"content":"this is the text description","pin_id":null},"region-pin28-exp1":{"exp_id":"region-pin28-exp1","label":"region-pin28-exp1","state":"expired","start":"2016/11/08 14:30:00","end":"2016/11/08 15:00:00","hero_photo":4,"content":"this is the text description","pin_id":null},"region-pin29-exp0":{"exp_id":"region-pin29-exp0","label":"region-pin29-exp0","state":"current","start":"2016/11/14 20:27:42","end":"2016/11/14 23:25:44","hero_photo":1,"content":"this is the text description","pin_id":null},"region-pin29-exp1":{"exp_id":"region-pin29-exp1","label":"region-pin29-exp1","state":"current","start":"2016/11/14 20:04:24","end":"2016/11/15 02:35:45","hero_photo":2,"content":"this is the text description","pin_id":null},"region-pin29-exp2":{"exp_id":"region-pin29-exp2","label":"region-pin29-exp2","state":"expired","start":"2016/11/08 14:30:00","end":"2016/11/08 15:00:00","hero_photo":2,"content":"this is the text description","pin_id":null},"region-pin29-exp3":{"exp_id":"region-pin29-exp3","label":"region-pin29-exp3","state":"expired","start":"2016/11/08 14:30:00","end":"2016/11/08 15:00:00","hero_photo":3,"content":"this is the text description","pin_id":null},"region-pin30-exp0":{"exp_id":"region-pin30-exp0","label":"region-pin30-exp0","state":"current","start":"2016/11/14 21:31:10","end":"2016/11/14 22:36:08","hero_photo":1,"content":"this is the text description","pin_id":null},"region-pin30-exp1":{"exp_id":"region-pin30-exp1","label":"Label only","content":"this is the text description","pin_id":null},"region-pin30-exp2":{"exp_id":"region-pin30-exp2","label":"region-pin30-exp2","state":"current","start":"2016/11/14 21:16:52","end":"2016/11/14 22:08:05","hero_photo":2,"content":"this is the text description","pin_id":null},"region-pin31-exp0":{"exp_id":"region-pin31-exp0","label":"region-pin31-exp0","state":"current","start":"2016/11/14 21:50:19","end":"2016/11/15 01:23:52","hero_photo":2,"content":"this is the text description","pin_id":null},"region-pin31-exp1":{"exp_id":"region-pin31-exp1","label":"region-pin31-exp1","state":"current","start":"2016/11/14 21:56:14","end":"2016/11/14 23:24:35","hero_photo":3,"content":"this is the text description","pin_id":null},"region-pin31-exp2":{"exp_id":"region-pin31-exp2","label":"region-pin31-exp2","state":"expired","start":"2016/11/08 14:30:00","end":"2016/11/08 15:00:00","hero_photo":2,"content":"this is the text description","pin_id":null},"region-pin31-exp3":{"exp_id":"region-pin31-exp3","label":"region-pin31-exp3","state":"expired","start":"2016/11/08 14:30:00","end":"2016/11/08 15:00:00","hero_photo":2,"content":"this is the text description","pin_id":null},"region-pin32-exp0":{"exp_id":"region-pin32-exp0","label":"Label only","content":"this is the text description","pin_id":null},"region-pin32-exp1":{"exp_id":"region-pin32-exp1","label":"region-pin32-exp1","state":"current","start":"2016/11/14 20:40:30","end":"2016/11/14 23:08:37","hero_photo":3,"content":"this is the text description","pin_id":null},"region-pin32-exp2":{"exp_id":"region-pin32-exp2","label":"region-pin32-exp2","state":"current","start":"2016/11/14 21:27:30","end":"2016/11/15 01:00:46","hero_photo":4,"content":"this is the text description","pin_id":null},"region-pin33-exp0":{"exp_id":"region-pin33-exp0","label":"region-pin33-exp0","state":"current","start":"2016/11/14 20:12:22","end":"2016/11/14 22:50:35","hero_photo":4,"content":"this is the text description","pin_id":null},"region-pin33-exp1":{"exp_id":"region-pin33-exp1","label":"region-pin33-exp1","state":"current","start":"2016/11/14 20:14:14","end":"2016/11/14 22:47:33","hero_photo":4,"content":"this is the text description","pin_id":null},"region-pin34-exp0":{"exp_id":"region-pin34-exp0","label":"region-pin34-exp0","state":"expired","start":"2016/11/08 14:30:00","end":"2016/11/08 15:00:00","hero_photo":2,"content":"this is the text description","pin_id":null},"region-pin34-exp1":{"exp_id":"region-pin34-exp1","label":"region-pin34-exp1","state":"current","start":"2016/11/14 21:38:46","end":"2016/11/15 02:40:12","hero_photo":3,"content":"this is the text description","pin_id":null},"region-pin35-exp0":{"exp_id":"region-pin35-exp0","label":"region-pin35-exp0","state":"current","start":"2016/11/14 20:03:44","end":"2016/11/14 23:54:21","hero_photo":2,"content":"this is the text description","pin_id":null},"region-pin35-exp1":{"exp_id":"region-pin35-exp1","label":"region-pin35-exp1","state":"expired","start":"2016/11/08 14:30:00","end":"2016/11/08 15:00:00","hero_photo":4,"content":"this is the text description","pin_id":null},"region-pin35-exp2":{"exp_id":"region-pin35-exp2","label":"region-pin35-exp2","state":"current","start":"2016/11/14 21:54:39","end":"2016/11/15 02:20:50","hero_photo":4,"content":"this is the text description","pin_id":null},"region-pin35-exp3":{"exp_id":"region-pin35-exp3","label":"Label only","content":"this is the text description","pin_id":null},"region-pin36-exp0":{"exp_id":"region-pin36-exp0","label":"region-pin36-exp0","state":"current","start":"2016/11/14 20:27:23","end":"2016/11/14 23:40:59","hero_photo":2,"content":"this is the text description","pin_id":null},"region-pin36-exp1":{"exp_id":"region-pin36-exp1","label":"Label only","content":"this is the text description","pin_id":null},"region-pin37-exp0":{"exp_id":"region-pin37-exp0","label":"region-pin37-exp0","state":"expired","start":"2016/11/08 14:30:00","end":"2016/11/08 15:00:00","hero_photo":1,"content":"this is the text description","pin_id":null},"region-pin37-exp1":{"exp_id":"region-pin37-exp1","label":"region-pin37-exp1","state":"expired","start":"2016/11/08 14:30:00","end":"2016/11/08 15:00:00","hero_photo":3,"content":"this is the text description","pin_id":null},"region-pin37-exp2":{"exp_id":"region-pin37-exp2","label":"region-pin37-exp2","state":"expired","start":"2016/11/08 14:30:00","end":"2016/11/08 15:00:00","hero_photo":3,"content":"this is the text description","pin_id":null},"region-pin37-exp3":{"exp_id":"region-pin37-exp3","label":"region-pin37-exp3","state":"expired","start":"2016/11/08 14:30:00","end":"2016/11/08 15:00:00","hero_photo":1,"content":"this is the text description","pin_id":null},"region-pin38-exp0":{"exp_id":"region-pin38-exp0","label":"region-pin38-exp0","state":"current","start":"2016/11/14 21:30:05","end":"2016/11/15 00:53:39","hero_photo":2,"content":"this is the text description","pin_id":null},"region-pin39-exp0":{"exp_id":"region-pin39-exp0","label":"Label only","content":"this is the text description","pin_id":null},"region-pin40-exp0":{"exp_id":"region-pin40-exp0","label":"region-pin40-exp0","state":"current","start":"2016/11/14 21:02:30","end":"2016/11/14 23:25:37","hero_photo":2,"content":"this is the text description","pin_id":null},"region-pin40-exp1":{"exp_id":"region-pin40-exp1","label":"region-pin40-exp1","state":"current","start":"2016/11/14 20:49:58","end":"2016/11/14 22:33:35","hero_photo":2,"content":"this is the text description","pin_id":null},"region-pin41-exp0":{"exp_id":"region-pin41-exp0","label":"region-pin41-exp0","state":"current","start":"2016/11/14 21:27:15","end":"2016/11/14 23:37:17","hero_photo":1,"content":"this is the text description","pin_id":null},"region-pin41-exp1":{"exp_id":"region-pin41-exp1","label":"Label only","content":"this is the text description","pin_id":null},"region-pin41-exp2":{"exp_id":"region-pin41-exp2","label":"Label only","content":"this is the text description","pin_id":null},"region-pin42-exp0":{"exp_id":"region-pin42-exp0","label":"region-pin42-exp0","state":"current","start":"2016/11/14 21:15:15","end":"2016/11/15 02:53:47","hero_photo":3,"content":"this is the text description","pin_id":null},"region-pin42-exp1":{"exp_id":"region-pin42-exp1","label":"region-pin42-exp1","state":"current","start":"2016/11/14 21:55:56","end":"2016/11/15 00:57:01","hero_photo":2,"content":"this is the text description","pin_id":null},"region-pin42-exp2":{"exp_id":"region-pin42-exp2","label":"region-pin42-exp2","state":"expired","start":"2016/11/08 14:30:00","end":"2016/11/08 15:00:00","hero_photo":3,"content":"this is the text description","pin_id":null},"region-pin43-exp0":{"exp_id":"region-pin43-exp0","label":"region-pin43-exp0","state":"expired","start":"2016/11/08 14:30:00","end":"2016/11/08 15:00:00","hero_photo":3,"content":"this is the text description","pin_id":null},"region-pin43-exp1":{"exp_id":"region-pin43-exp1","label":"region-pin43-exp1","state":"current","start":"2016/11/14 21:05:55","end":"2016/11/15 02:00:49","hero_photo":4,"content":"this is the text description","pin_id":null},"region-pin44-exp0":{"exp_id":"region-pin44-exp0","label":"region-pin44-exp0","state":"expired","start":"2016/11/08 14:30:00","end":"2016/11/08 15:00:00","hero_photo":4,"content":"this is the text description","pin_id":null},"region-pin45-exp0":{"exp_id":"region-pin45-exp0","label":"Label only","content":"this is the text description","pin_id":null},"region-pin45-exp1":{"exp_id":"region-pin45-exp1","label":"Label only","content":"this is the text description","pin_id":null},"region-pin46-exp0":{"exp_id":"region-pin46-exp0","label":"Label only","content":"this is the text description","pin_id":null},"region-pin46-exp1":{"exp_id":"region-pin46-exp1","label":"region-pin46-exp1","state":"current","start":"2016/11/14 21:45:39","end":"2016/11/15 00:31:45","hero_photo":4,"content":"this is the text description","pin_id":null},"region-pin46-exp2":{"exp_id":"region-pin46-exp2","label":"region-pin46-exp2","state":"expired","start":"2016/11/08 14:30:00","end":"2016/11/08 15:00:00","hero_photo":4,"content":"this is the text description","pin_id":null},"region-pin47-exp0":{"exp_id":"region-pin47-exp0","label":"region-pin47-exp0","state":"expired","start":"2016/11/08 14:30:00","end":"2016/11/08 15:00:00","hero_photo":4,"content":"this is the text description","pin_id":null},"region-pin47-exp1":{"exp_id":"region-pin47-exp1","label":"Label only","content":"this is the text description","pin_id":null},"region-pin48-exp0":{"exp_id":"region-pin48-exp0","label":"region-pin48-exp0","state":"current","start":"2016/11/14 21:14:32","end":"2016/11/14 23:13:11","hero_photo":1,"content":"this is the text description","pin_id":null},"region-pin48-exp1":{"exp_id":"region-pin48-exp1","label":"region-pin48-exp1","state":"expired","start":"2016/11/08 14:30:00","end":"2016/11/08 15:00:00","hero_photo":2,"content":"this is the text description","pin_id":null},"region-pin49-exp0":{"exp_id":"region-pin49-exp0","label":"region-pin49-exp0","state":"current","start":"2016/11/14 21:19:30","end":"2016/11/14 23:30:07","hero_photo":3,"content":"this is the text description","pin_id":null},"region-pin49-exp1":{"exp_id":"region-pin49-exp1","label":"Label only","content":"this is the text description","pin_id":null},"region-pin50-exp0":{"exp_id":"region-pin50-exp0","label":"region-pin50-exp0","state":"current","start":"2016/11/14 21:28:20","end":"2016/11/14 23:00:41","hero_photo":4,"content":"this is the text description","pin_id":null},"region-pin50-exp1":{"exp_id":"region-pin50-exp1","label":"region-pin50-exp1","state":"current","start":"2016/11/14 20:32:24","end":"2016/11/15 02:33:36","hero_photo":2,"content":"this is the text description","pin_id":null},"region-pin50-exp2":{"exp_id":"region-pin50-exp2","label":"region-pin50-exp2","state":"current","start":"2016/11/14 20:12:11","end":"2016/11/14 23:46:23","hero_photo":1,"content":"this is the text description","pin_id":null},"region-pin50-exp3":{"exp_id":"region-pin50-exp3","label":"region-pin50-exp3","state":"current","start":"2016/11/14 21:53:28","end":"2016/11/14 23:53:45","hero_photo":1,"content":"this is the text description","pin_id":null},"region-pin51-exp0":{"exp_id":"region-pin51-exp0","label":"region-pin51-exp0","state":"current","start":"2016/11/14 20:34:20","end":"2016/11/15 00:14:40","hero_photo":2,"content":"this is the text description","pin_id":null},"region-pin51-exp1":{"exp_id":"region-pin51-exp1","label":"region-pin51-exp1","state":"expired","start":"2016/11/08 14:30:00","end":"2016/11/08 15:00:00","hero_photo":4,"content":"this is the text description","pin_id":null},"region-pin52-exp0":{"exp_id":"region-pin52-exp0","label":"region-pin52-exp0","state":"current","start":"2016/11/14 21:48:10","end":"2016/11/15 00:51:12","hero_photo":3,"content":"this is the text description","pin_id":null},"region-pin52-exp1":{"exp_id":"region-pin52-exp1","label":"region-pin52-exp1","state":"current","start":"2016/11/14 20:37:20","end":"2016/11/14 23:04:45","hero_photo":1,"content":"this is the text description","pin_id":null},"region-pin52-exp2":{"exp_id":"region-pin52-exp2","label":"region-pin52-exp2","state":"current","start":"2016/11/14 21:31:11","end":"2016/11/15 01:51:52","hero_photo":2,"content":"this is the text description","pin_id":null},"region-pin52-exp3":{"exp_id":"region-pin52-exp3","label":"Label only","content":"this is the text description","pin_id":null},"region-pin53-exp0":{"exp_id":"region-pin53-exp0","label":"region-pin53-exp0","state":"current","start":"2016/11/14 20:16:06","end":"2016/11/14 23:40:13","hero_photo":1,"content":"this is the text description","pin_id":null},"region-pin53-exp1":{"exp_id":"region-pin53-exp1","label":"region-pin53-exp1","state":"current","start":"2016/11/14 21:54:31","end":"2016/11/15 02:53:59","hero_photo":4,"content":"this is the text description","pin_id":null},"region-pin53-exp2":{"exp_id":"region-pin53-exp2","label":"region-pin53-exp2","state":"expired","start":"2016/11/08 14:30:00","end":"2016/11/08 15:00:00","hero_photo":3,"content":"this is the text description","pin_id":null},"region-pin54-exp0":{"exp_id":"region-pin54-exp0","label":"region-pin54-exp0","state":"current","start":"2016/11/14 21:06:55","end":"2016/11/15 02:44:29","hero_photo":2,"content":"this is the text description","pin_id":null},"region-pin54-exp1":{"exp_id":"region-pin54-exp1","label":"region-pin54-exp1","state":"expired","start":"2016/11/08 14:30:00","end":"2016/11/08 15:00:00","hero_photo":4,"content":"this is the text description","pin_id":null},"region-pin55-exp0":{"exp_id":"region-pin55-exp0","label":"Label only","content":"this is the text description","pin_id":null},"region-pin56-exp0":{"exp_id":"region-pin56-exp0","label":"region-pin56-exp0","state":"expired","start":"2016/11/08 14:30:00","end":"2016/11/08 15:00:00","hero_photo":2,"content":"this is the text description","pin_id":null},"region-pin57-exp0":{"exp_id":"region-pin57-exp0","label":"region-pin57-exp0","state":"expired","start":"2016/11/08 14:30:00","end":"2016/11/08 15:00:00","hero_photo":4,"content":"this is the text description","pin_id":null},"region-pin57-exp1":{"exp_id":"region-pin57-exp1","label":"region-pin57-exp1","state":"current","start":"2016/11/14 21:50:12","end":"2016/11/15 01:28:38","hero_photo":3,"content":"this is the text description","pin_id":null},"region-pin57-exp2":{"exp_id":"region-pin57-exp2","label":"region-pin57-exp2","state":"expired","start":"2016/11/08 14:30:00","end":"2016/11/08 15:00:00","hero_photo":3,"content":"this is the text description","pin_id":null},"region-pin58-exp0":{"exp_id":"region-pin58-exp0","label":"region-pin58-exp0","state":"expired","start":"2016/11/08 14:30:00","end":"2016/11/08 15:00:00","hero_photo":3,"content":"this is the text description","pin_id":null},"region-pin58-exp1":{"exp_id":"region-pin58-exp1","label":"region-pin58-exp1","state":"current","start":"2016/11/14 20:45:09","end":"2016/11/14 22:13:32","hero_photo":4,"content":"this is the text description","pin_id":null},"region-pin58-exp2":{"exp_id":"region-pin58-exp2","label":"Label only","content":"this is the text description","pin_id":null},"region-pin59-exp0":{"exp_id":"region-pin59-exp0","label":"region-pin59-exp0","state":"current","start":"2016/11/14 21:38:43","end":"2016/11/14 23:22:04","hero_photo":4,"content":"this is the text description","pin_id":null},"region-pin59-exp1":{"exp_id":"region-pin59-exp1","label":"region-pin59-exp1","state":"current","start":"2016/11/14 21:57:39","end":"2016/11/15 01:25:59","hero_photo":1,"content":"this is the text description","pin_id":null},"region-pin1-exp1":{"exp_id":"region-pin1-exp1","label":"Label only","content":"this is the text description","pin_id":null},"region-pin6-exp2":{"exp_id":"region-pin6-exp2","label":"region-pin6-exp2","state":"expired","start":"2016/11/08 14:30:00","end":"2016/11/08 15:00:00","hero_photo":4,"content":"this is the text description","pin_id":null},"region-pin10-exp1":{"exp_id":"region-pin10-exp1","label":"region-pin10-exp1","state":"expired","start":"2016/11/08 14:30:00","end":"2016/11/08 15:00:00","hero_photo":4,"content":"this is the text description","pin_id":null},"region-pin11-exp2":{"exp_id":"region-pin11-exp2","label":"region-pin11-exp2","state":"expired","start":"2016/11/08 14:30:00","end":"2016/11/08 15:00:00","hero_photo":4,"content":"this is the text description","pin_id":null},"region-pin16-exp2":{"exp_id":"region-pin16-exp2","label":"region-pin16-exp2","state":"current","start":"2016/11/14 21:03:34","end":"2016/11/15 00:06:59","hero_photo":2,"content":"this is the text description","pin_id":null},"region-pin17-exp1":{"exp_id":"region-pin17-exp1","label":"region-pin17-exp1","state":"current","start":"2016/11/14 21:17:59","end":"2016/11/14 22:08:03","hero_photo":3,"content":"this is the text description","pin_id":null},"region-pin19-exp3":{"exp_id":"region-pin19-exp3","label":"region-pin19-exp3","state":"current","start":"2016/11/14 21:38:44","end":"2016/11/15 01:27:49","hero_photo":1,"content":"this is the text description","pin_id":null},"region-pin20-exp2":{"exp_id":"region-pin20-exp2","label":"region-pin20-exp2","state":"expired","start":"2016/11/08 14:30:00","end":"2016/11/08 15:00:00","hero_photo":4,"content":"this is the text description","pin_id":null},"region-pin20-exp3":{"exp_id":"region-pin20-exp3","label":"Label only","content":"this is the text description","pin_id":null},"region-pin21-exp3":{"exp_id":"region-pin21-exp3","label":"region-pin21-exp3","state":"current","start":"2016/11/14 21:15:08","end":"2016/11/15 01:42:19","hero_photo":3,"content":"this is the text description","pin_id":null},"region-pin22-exp1":{"exp_id":"region-pin22-exp1","label":"region-pin22-exp1","state":"current","start":"2016/11/14 20:35:02","end":"2016/11/14 22:10:34","hero_photo":2,"content":"this is the text description","pin_id":null},"region-pin22-exp2":{"exp_id":"region-pin22-exp2","label":"region-pin22-exp2","state":"expired","start":"2016/11/08 14:30:00","end":"2016/11/08 15:00:00","hero_photo":3,"content":"this is the text description","pin_id":null},"region-pin22-exp3":{"exp_id":"region-pin22-exp3","label":"region-pin22-exp3","state":"expired","start":"2016/11/08 14:30:00","end":"2016/11/08 15:00:00","hero_photo":1,"content":"this is the text description","pin_id":null},"region-pin23-exp2":{"exp_id":"region-pin23-exp2","label":"Label only","content":"this is the text description","pin_id":null},"region-pin23-exp3":{"exp_id":"region-pin23-exp3","label":"region-pin23-exp3","state":"current","start":"2016/11/14 20:48:48","end":"2016/11/14 23:33:31","hero_photo":4,"content":"this is the text description","pin_id":null},"region-pin24-exp1":{"exp_id":"region-pin24-exp1","label":"region-pin24-exp1","state":"expired","start":"2016/11/08 14:30:00","end":"2016/11/08 15:00:00","hero_photo":1,"content":"this is the text description","pin_id":null},"region-pin27-exp1":{"exp_id":"region-pin27-exp1","label":"region-pin27-exp1","state":"expired","start":"2016/11/08 14:30:00","end":"2016/11/08 15:00:00","hero_photo":4,"content":"this is the text description","pin_id":null},"region-pin27-exp2":{"exp_id":"region-pin27-exp2","label":"region-pin27-exp2","state":"expired","start":"2016/11/08 14:30:00","end":"2016/11/08 15:00:00","hero_photo":1,"content":"this is the text description","pin_id":null},"region-pin27-exp3":{"exp_id":"region-pin27-exp3","label":"region-pin27-exp3","state":"expired","start":"2016/11/08 14:30:00","end":"2016/11/08 15:00:00","hero_photo":3,"content":"this is the text description","pin_id":null},"region-pin32-exp3":{"exp_id":"region-pin32-exp3","label":"region-pin32-exp3","state":"current","start":"2016/11/14 21:27:33","end":"2016/11/15 00:54:36","hero_photo":1,"content":"this is the text description","pin_id":null},"region-pin33-exp2":{"exp_id":"region-pin33-exp2","label":"region-pin33-exp2","state":"expired","start":"2016/11/08 14:30:00","end":"2016/11/08 15:00:00","hero_photo":2,"content":"this is the text description","pin_id":null},"region-pin33-exp3":{"exp_id":"region-pin33-exp3","label":"region-pin33-exp3","state":"expired","start":"2016/11/08 14:30:00","end":"2016/11/08 15:00:00","hero_photo":2,"content":"this is the text description","pin_id":null},"region-pin34-exp2":{"exp_id":"region-pin34-exp2","label":"region-pin34-exp2","state":"current","start":"2016/11/14 20:33:00","end":"2016/11/14 23:54:15","hero_photo":1,"content":"this is the text description","pin_id":null},"region-pin34-exp3":{"exp_id":"region-pin34-exp3","label":"region-pin34-exp3","state":"current","start":"2016/11/14 21:06:47","end":"2016/11/14 23:11:00","hero_photo":1,"content":"this is the text description","pin_id":null},"region-pin38-exp1":{"exp_id":"region-pin38-exp1","label":"region-pin38-exp1","state":"current","start":"2016/11/14 21:41:23","end":"2016/11/15 02:39:30","hero_photo":2,"content":"this is the text description","pin_id":null},"region-pin38-exp2":{"exp_id":"region-pin38-exp2","label":"region-pin38-exp2","state":"current","start":"2016/11/14 21:04:25","end":"2016/11/15 02:52:48","hero_photo":1,"content":"this is the text description","pin_id":null},"region-pin38-exp3":{"exp_id":"region-pin38-exp3","label":"region-pin38-exp3","state":"current","start":"2016/11/14 20:58:55","end":"2016/11/14 23:23:07","hero_photo":1,"content":"this is the text description","pin_id":null},"region-pin39-exp1":{"exp_id":"region-pin39-exp1","label":"region-pin39-exp1","state":"current","start":"2016/11/14 20:02:44","end":"2016/11/15 00:21:32","hero_photo":3,"content":"this is the text description","pin_id":null},"region-pin41-exp3":{"exp_id":"region-pin41-exp3","label":"region-pin41-exp3","state":"expired","start":"2016/11/08 14:30:00","end":"2016/11/08 15:00:00","hero_photo":4,"content":"this is the text description","pin_id":null},"region-pin44-exp1":{"exp_id":"region-pin44-exp1","label":"region-pin44-exp1","state":"current","start":"2016/11/14 20:24:43","end":"2016/11/15 00:49:05","hero_photo":4,"content":"this is the text description","pin_id":null},"region-pin44-exp2":{"exp_id":"region-pin44-exp2","label":"region-pin44-exp2","state":"current","start":"2016/11/14 21:59:24","end":"2016/11/14 22:53:37","hero_photo":3,"content":"this is the text description","pin_id":null},"region-pin44-exp3":{"exp_id":"region-pin44-exp3","label":"region-pin44-exp3","state":"expired","start":"2016/11/08 14:30:00","end":"2016/11/08 15:00:00","hero_photo":3,"content":"this is the text description","pin_id":null},"region-pin46-exp3":{"exp_id":"region-pin46-exp3","label":"region-pin46-exp3","state":"current","start":"2016/11/14 20:56:04","end":"2016/11/14 23:53:43","hero_photo":4,"content":"this is the text description","pin_id":null},"region-pin48-exp2":{"exp_id":"region-pin48-exp2","label":"region-pin48-exp2","state":"current","start":"2016/11/14 21:38:16","end":"2016/11/14 22:06:12","hero_photo":1,"content":"this is the text description","pin_id":null},"region-pin48-exp3":{"exp_id":"region-pin48-exp3","label":"Label only","content":"this is the text description","pin_id":null},"region-pin49-exp2":{"exp_id":"region-pin49-exp2","label":"region-pin49-exp2","state":"current","start":"2016/11/14 21:27:36","end":"2016/11/14 23:00:09","hero_photo":4,"content":"this is the text description","pin_id":null},"region-pin49-exp3":{"exp_id":"region-pin49-exp3","label":"region-pin49-exp3","state":"current","start":"2016/11/14 20:57:08","end":"2016/11/15 01:01:06","hero_photo":3,"content":"this is the text description","pin_id":null},"region-pin51-exp2":{"exp_id":"region-pin51-exp2","label":"region-pin51-exp2","state":"current","start":"2016/11/14 21:26:24","end":"2016/11/15 00:36:57","hero_photo":4,"content":"this is the text description","pin_id":null},"region-pin56-exp1":{"exp_id":"region-pin56-exp1","label":"Label only","content":"this is the text description","pin_id":null}}
diff --git a/index.js b/index.js
index c4a54b2..00f559c 100644
--- a/index.js
+++ b/index.js
@@ -7,13 +7,11 @@ var fs = require('fs');
var util = require('util');
var mkdirp = require('mkdirp');
var getDirName = require('path').dirname;
-var enableCache = true;
+var enableCache = false;
var cp = require('child_process').exec;
var bodyParser = require('body-parser');
var imgCache = {};
-var regions = JSON.parse(require('fs').readFileSync('./regions.json'));
-
app.set('port', (process.env.PORT || 5000));
app.use('/public', express.static('public'));
@@ -25,6 +23,31 @@ app.listen(app.get('port'), function() {
console.log('Node app is running on port', app.get('port'));
});
+app.get('/regions', function(req, res) {
+
+ try {
+ var regions = fs.readdir('./regions/', function(err, files) {
+ console.log(files)
+ var results = [];
+ for(var i in files) {
+ if(/\.json$/i.test(files[i])) {
+ var meta = './regions/'+files[i];
+ console.log('read region meta :', meta);
+ var region = JSON.parse(fs.readFileSync(meta));
+ region.name = String(files[i]).replace(/\.json$/i,'');
+ results.push(region);
+ }
+ }
+ res.send(results);
+ })
+
+ // res.send(files)
+ }catch(err) {
+ console.log(err.stack);
+ }
+
+})
+
app.post('/bounds/:region', function(req, res) {
var region = req.params.region;
console.log(region,req.body)
@@ -234,7 +257,7 @@ function createTileFromRawImage(region, x, y, z, debug, cb) {
ctx.rect(0, 0, 256, 256);
ctx.fillStyle = '#F0F0F0';
ctx.fill();
- ctx.fillStyle = '#777';
+ ctx.fillStyle = '#222';
ctx.font = '16px Arial';
ctx.fillText('OUT OF BOUND', 128, 128);
var bytes = tileImg.toBuffer(undefined, 3, ctx.PNG_FILTER_NONE);
@@ -285,7 +308,7 @@ function drawText(ctx,param, ox,oy, dx, dy, z) {
var coords = 'from (' + [Math.round(ox), Math.floor(oy)].join(', ') + ')';
var coords2 = 'to (' + [Math.round(ox+dx), Math.floor(oy + dy)].join(', ') + ')';
ctx.font = '16px Arial';
- ctx.fillStyle = '#DDD';
+ ctx.fillStyle = '#333';
ctx.fillText(info, 8, 24);
ctx.fillText(coords, 8, 48);
ctx.fillText(coords2, 8, 64);
@@ -302,7 +325,7 @@ function generateTile(x,y,z) {
ctx.rect(0, 0, 256, 256);
ctx.fillStyle = '#F0F0F0';
ctx.fill();
- ctx.fillStyle = '#777';
+ ctx.fillStyle = '#333';
ctx.font = '16px Arial';
ctx.fillText(coords, 24, 64);
ctx.strokeStyle = 'white';
diff --git a/make-tiles.js b/make-tiles.js
new file mode 100644
index 0000000..09c87e8
--- /dev/null
+++ b/make-tiles.js
@@ -0,0 +1,164 @@
+var Canvas = require('canvas');
+var Image = Canvas.Image;
+var moment = require('moment');
+var fs = require('fs');
+var util = require('util');
+var mkdirp = require('mkdirp');
+var getDirName = require('path').dirname;
+var cp = require('child_process').exec;
+let img = new Image;
+let imageCache = {};
+
+console.log(process.argv);
+
+var regionName = process.argv[2];
+var min = +process.argv[3];
+var max = +process.argv[4];
+var val = JSON.parse(fs.readFileSync('./regions/'+regionName+'.json')).bounds;
+console.log(val)
+console.log('generate tiles:', regionName, min+'x', '~', max+'x');
+// get tms bounds for each zoom level
+var total = 0;
+var ranges = [];
+for(var i = min; i <= max ; i++) {
+ var lt = getTileAtLatLng(val[0], i);
+ var rb = getTileAtLatLng(val[2], i);
+ var w = Math.abs(rb.x-lt.x);
+ var h = Math.abs(rb.y-lt.y);
+ ranges.push({
+ zoom : i,
+ lt : lt,
+ rb : rb,
+ width : w,
+ height : h,
+ number : w*h
+ });
+ total += w*h;
+}
+console.log('tiles needs to be generated :', total);
+var now = 0;
+for(var i=min;i<=max;i++) {
+ var lt = getTileAtLatLng(val[0], i);
+ var rb = getTileAtLatLng(val[2], i);
+ for(var j = lt.x; j < rb.x;j++){
+ for(var k=lt.y; k < rb.y;k++) {
+ createTileFromRawImage(regionName, j,k,i, function() {
+ });
+ }
+ }
+
+}
+
+function tileToLatLng(x,y,z) {
+ var result = { lat : tileToLat(y,z), lng : tileToLong(x,z) };;
+ return result;
+}
+
+function tileToLong(x,z) { return (x/Math.pow(2,z)*360-180); }
+
+function tileToLat(y,z) {
+ var n = Math.PI-2*Math.PI*y/Math.pow(2,z);
+ return (180/Math.PI*Math.atan(0.5*(Math.exp(n)-Math.exp(-n))));
+}
+
+function createTileFromRawImage(region, x, y, z, cb) {
+ x = Math.floor(x);
+ y = Math.floor(y);
+ z = Math.floor(z);
+ let bounds = fs.readFile(`./regions/${region}.json`, (err, data) => {
+
+ let {bounds} = JSON.parse(data);
+ let tileBounds = [
+ tileToLatLng(x,y,z),
+ tileToLatLng(x+1,y,z),
+ tileToLatLng(x+1,y+1,z),
+ tileToLatLng(x,y+1,z)
+ ];
+ if(imageCache[region]) {
+ render(null, imageCache[region]);
+ }
+ else {
+ fs.readFile(`./region-raw-img/${region}.png`, render);
+ }
+
+ function render(err, data) {
+ if(!imageCache[region] )
+ imageCache[region] = data;
+ if(err)
+ throw err;
+ let img = new Image;
+ img.src = data;
+
+ let regionWidth = Math.abs(Math.abs(bounds[0].lng) - Math.abs(bounds[1].lng)),
+ regionHeight = Math.abs(Math.abs(bounds[1].lat) - Math.abs(bounds[2].lat));
+
+ let tileWidth = Math.abs(tileBounds[0].lng - tileBounds[1].lng) * img.width /regionWidth,
+ tileHeight = Math.abs(tileBounds[1].lat - tileBounds[2].lat) * img.height /regionHeight;
+
+ let tileImg = new Canvas(256, 256);
+ let originX = (Math.abs(tileBounds[0].lng) - Math.abs(bounds[0].lng))/regionWidth * img.width;
+ let originY = (Math.abs(tileBounds[0].lat) - Math.abs(bounds[0].lat))/regionHeight * img.height;
+ let ctx = tileImg.getContext('2d');
+
+ if( originX > img.width + tileWidth ||
+ originY > img.height + tileHeight ||
+ originY < -tileHeight -1 || originX < -tileWidth -1 ) {
+ return
+ }
+ else {
+ ctx.drawImage(img, originX, originY, tileWidth, tileHeight, 0, 0, 256, 256);
+ ctx.strokeStyle = 'transparent';
+ ctx.strokeRect(0, 0, 256, 256);
+ }
+
+ var bytes = tileImg.toBuffer(undefined, 3, ctx.PNG_FILTER_NONE);
+
+ var dir = `./regions/${region}/${z}/${x}${y}.png`;
+ mkdirp(getDirName(dir), function (err) {
+ if (err)
+ console.log(err);
+
+ fs.writeFile(dir, bytes, function(err) {
+ if(err)
+ console.log(err)
+ console.log('remaining tiles', --total);
+ cb();
+ });
+
+ });
+
+ }
+
+ });
+
+}
+
+var deleteFolderRecursive = function(path, cb) {
+ if( fs.existsSync(path) ) {
+ fs.readdirSync(path).forEach(function(file,index){
+ var curPath = path + "/" + file;
+ if(fs.lstatSync(curPath).isDirectory()) { // recurse
+ deleteFolderRecursive(curPath);
+ } else { // delete file
+ fs.unlinkSync(curPath);
+ }
+ });
+ fs.rmdirSync(path);
+ }
+ cb()
+};
+
+function fromLatLngToPoint (latLng){
+ var siny = Math.min(Math.max(Math.sin(latLng.lat* (Math.PI / 180)), -.9999),.9999);
+ return {
+ x: 128 + latLng.lng * (256/360),
+ y: 128 + 0.5 * Math.log((1 + siny) / (1 - siny)) * -(256 / (2 * Math.PI))
+ };
+}
+
+function getTileAtLatLng(latLng,zoom){
+ var t=Math.pow(2,zoom),
+ s=256/t,
+ p=fromLatLngToPoint(latLng);
+ return {x:Math.floor(p.x/s),y:Math.floor(p.y/s),z:zoom};
+}
diff --git a/public/app.js b/public/app.js
index 866e6a5..533cb3f 100644
--- a/public/app.js
+++ b/public/app.js
@@ -1,170 +1,309 @@
-var regions = [[
- // north west
- {lat: -33.3686095, lng: 149.7558751},
- // north east
- {lat: -33.3686095, lng: 149.3558751},
- // south east
- {lat: -33.5286095, lng: 149.3558751},
- // south west
- {lat: -33.5286095, lng: 149.7558751},
-]];
-
-$(function() {
-
- console.log('initialize')
- $('#draw-region').on('click',function() {
-
- drawRegion(regions[0])
- });
+var map = null;
+var markers = [];
+var rect = null;
+var app = new Vue({
+ el: '#app',
-});
+ // data context
-function drawRegion(region) {
+ data: {
+ regions : [],
+ selectedRegion : null,
+ regionZoom : 15,
+ regionCenter : { lat : 0, lng : 0 },
+ viewerTMSCoord : '17,116005,79122',
+ viewerWidth : 3,
+ viewerHeight : 3,
+ tiles : [],
+ json : '',
+ selectedBounds : [{lat:0, lng:0},{lat:0, lng:0},{lat:0, lng:0},{lat:0, lng:0}],
+ config : {
+ zoomMin : 8,
+ zoomMax : 19,
+ ranges : []
+ },
+ },
- // Construct the polygon.
- var bermudaTriangle = new google.maps.Polygon({
- paths: region,
- strokeColor: '#FF0000',
- strokeOpacity: 0.8,
- strokeWeight: 3,
- fillColor: '#00000000',
- fillOpacity: 0.35
- });
- bermudaTriangle.setMap(map);
+ // lifecycle
- // Add a listener for the click event.
- bermudaTriangle.addListener('click', showArrays);
+ created : function() {
+ this.getRegions();
+ },
- infoWindow = new google.maps.InfoWindow;
-}
+ // watch prop changes
-/** @this {google.maps.Polygon} */
-function showArrays(event) {
- // Since this polygon has only one path, we can call getPath() to return the
- // MVCArray of LatLngs.
- var vertices = this.getPath();
+ watch : {
- var contentString = 'region
' +
- 'Clicked location:
' + event.latLng.lat() + ',' + event.latLng.lng() +
- '
';
+ selectedBounds : function(val) {
+ var json = { bounds: val };
+ app.json = JSON.stringify(json);
+ // get tms bounds for each zoom level
+ var min = app.config.zoomMin;
+ var max = app.config.zoomMax;
+ var ranges = [];
+ for(var i = min; i <= max ; i++) {
+ var lt = getTileAtLatLng(val[0], i);
+ var rb = getTileAtLatLng(val[2], i);
+ console.log(lt,rb,i)
+ ranges.push({
+ zoom : i,
+ lt : lt,
+ rb : rb,
+ width : Math.abs(rb.x-lt.x),
+ height : Math.abs(rb.y-lt.y),
+ number : Math.abs((rb.x-lt.x) * (rb.y-lt.y))
+ })
+ }
+ console.log(ranges);
+ app.config.ranges = ranges;
+ },
- // Iterate over the vertices.
- for (var i =0; i < vertices.getLength(); i++) {
- var xy = vertices.getAt(i);
- contentString += '
' + 'Coordinate ' + i + ':
' + xy.lat() + ',' +
- xy.lng();
- }
+ regionZoom : function(val) {
+ map.setZoom(val);
+ },
- // Replace the info window's content and position.
- infoWindow.setContent(contentString);
- infoWindow.setPosition(event.latLng);
+ selectedRegion : function(key) {
+ console.log(key)
+ var region = null;
+ for(var i in app.regions) {
+ if(app.regions[i].name === key) {
+ region = app.regions[i];
+ break
+ }
+ }
+ console.log(region);
+ if(!region)
+ return;
+ var center = {
+ lat : ((+region.bounds[0].lat) + (+region.bounds[2].lat))/2,
+ lng : ((+region.bounds[0].lng) + (+region.bounds[2].lng))/2
+ };
+ map.setZoom(app.regionZoom);
+ map.setCenter(center);
+ $.get('/bounds/' + key, function(data) {
+ var bounds = JSON.parse(data);
+ console.log('bounds', bounds);
+ // clear rect and redraw
+ app.selectedBounds = bounds.bounds;
+ for(var i in markers) {
+ markers[i].setMap(null);
+ }
+ rect && rect.setMap(null);
+ var marker1 = new google.maps.Marker({
+ position: region.bounds[0],
+ label : 'LT',
+ map: map
+ });
+ var marker2 = new google.maps.Marker({
+ position: region.bounds[2],
+ label : 'RB',
+ map: map
+ });
+ markers = [marker1, marker2];
+ var rectBounds = {
+ north: Math.max(markers[0].position.lat(), markers[1].position.lat()),
+ south: Math.min(markers[0].position.lat(), markers[1].position.lat()),
+ east: Math.max(markers[0].position.lng(), markers[1].position.lng()),
+ west: Math.min(markers[0].position.lng(), markers[1].position.lng())
+ };
+ rect = new google.maps.Rectangle({
+ strokeOpacity: 0.8,
+ strokeWeight: 0,
+ fillColor: '#007dff',
+ fillOpacity: 0.35,
+ map: map,
+ bounds: rectBounds
+ });
+ });
+ app.regionCenter = center;
+ },
- infoWindow.open(map);
-}
+ },
-function handleMap(map){
- var getBounds = getFnDefineBounds();
- var drawRect = getFnDrawRect();
- map.addListener('click', function(event) {
- bounds = getBounds({ lat: event.latLng.lat(), lng: event.latLng.lng() }, map);
- drawRect(bounds);
- });
-}
+ // methods
-function getFnDrawRect(){
- var rect;
- return function(bounds){
- clearIfNeed();
- if(bounds){
- rect = new google.maps.Rectangle({
- strokeColor: '#FF0000',
- strokeOpacity: 0.8,
- strokeWeight: 2,
- fillOpacity: 0,
- map: map,
- bounds: bounds
- });
- }
- }
- function clearIfNeed(){
- if(rect){
- rect.setMap(null);
- rect = null;
+ methods : {
+
+ stat : function() {
+ var json = { bounds: app.selectedBounds };
+ app.json = JSON.stringify(json);
+ // get tms bounds for each zoom level
+ var min = app.config.zoomMin;
+ var max = app.config.zoomMax;
+ var ranges = [];
+ for(var i = min; i <= max ; i++) {
+ var lt = getTileAtLatLng(app.selectedBounds[0], i);
+ var rb = getTileAtLatLng(app.selectedBounds[2], i);
+ console.log(lt,rb,i)
+ ranges.push({
+ zoom : i,
+ lt : lt,
+ rb : rb,
+ width : Math.abs(rb.x-lt.x),
+ height : Math.abs(rb.y-lt.y),
+ number : Math.abs((rb.x-lt.x) * (rb.y-lt.y))
+ })
+ }
+ console.log(ranges);
+ app.config.ranges = ranges;
+ },
+
+ getRegions : function() {
+ $.get('/regions', function(data) {
+ console.log(app.regions)
+ console.log('regions', data);
+ regions = data;
+ for(var i in data) {
+ var meta = data[i];
+ app.regions.push(meta)
+ }
+ console.log(app.regions);
+
+ });
+ },
+
+ renderViewer() {
+ var z = Math.floor(String(app.viewerTMSCoord).split(',')[0]);
+ var x = Math.floor(String(app.viewerTMSCoord).split(',')[1]);
+ var y = Math.floor(String(app.viewerTMSCoord).split(',')[2]);
+ var tiles = [];
+
+ for(var j = 0; j < app.viewerHeight; j++) {
+ var row = [];
+ for(var i = 0; i < app.viewerWidth; i++) {
+ row.push({
+ src : '/tiles/debug/' + app.selectedRegion + '/' + [z, x+i, y+j].join('/') + '?v='+Date.now(),
+ base : '/base/' + [z, x+i, y+j].join('/')
+ });
}
+ tiles.push(row);
+ }
+ app.tiles = tiles;
+ console.log('render tiles', tiles)
+ },
+
+ viewerMove (dx, dy, dz) {
+ var coords = String(app.viewerTMSCoord).split(',');
+ var x = Math.floor((+coords[1] + dx) * Math.pow(2, dz));
+ var z = (+coords[0]) + dz;
+ var y = Math.floor((+coords[2] + dy) * Math.pow(2, dz));
+ app.viewerTMSCoord = [z,x,y].join(',');
+ console.log('viewer move', dx, dy, dz,app.viewerTMSCoord)
+ app.renderViewer();
+ },
+
+ updateRegionBounds() {
+ var body = {};
+ body.bounds = app.selectedBounds;
+ var xhr = new XMLHttpRequest();
+ xhr.open('POST', '/bounds/'+ app.selectedRegion);
+ xhr.setRequestHeader('Content-Type', 'application/json');
+ xhr.send(JSON.stringify(body));
+ console.log(app.selectedBounds);
}
-}
-function getFnDefineBounds(){
- var count = 0;
- var markerAry = [];
- return function(location, map){
- var oldMarker;
- var newMarker = new google.maps.Marker({
- position: location,
- animation: google.maps.Animation.DROP,
- map: map
- });
- if(count%2==0){
- oldMarker = markerAry[0];
- markerAry[0] = newMarker;
- }
- else{
- oldMarker = markerAry[1];
- markerAry[1] = newMarker;
- }
+ },
- clearIfNeed(oldMarker, infowindow);
- var infowindow = new google.maps.InfoWindow();
- infowindow.setContent('lat: ' + location.lat + '
' + 'lng: ' + location.lng);
- infowindow.open(map, newMarker);
+});
- count++;
- return getBounds(markerAry);
+function initMap() {
+ map = new google.maps.Map(document.getElementById('map'), {
+ zoom: 16,
+ center: {lat: -34.9270088, lng: 138.6089918},
+ mapTypeId: google.maps.MapTypeId.TERRAIN
+ });
+ map.addListener('click', function(event) {
+ if(markers.length > 1) {
+ for(var i in markers) {
+ markers[i].setMap(null);
+ }
+ markers = [];
+ }
+ var ll = {
+ lat: event.latLng.lat(),
+ lng: event.latLng.lng()
+ };
+ bounds = getBounds(ll, map);
+ var marker = new google.maps.Marker({
+ position: ll,
+ label : markers.length === 0 ? 'LT' : 'RB',
+ map: map
+ });
+ var info = new google.maps.InfoWindow();
+ info.setContent('lat: ' + ll.lat + '
' + 'lng: ' + ll.lng);
+ info.open(map, marker);
+ markers.push(marker);
+ // draw rect
+ if(markers.length === 2) {
+ var bounds = {
+ north: Math.max(markers[0].position.lat(), markers[1].position.lat()),
+ south: Math.min(markers[0].position.lat(), markers[1].position.lat()),
+ east: Math.max(markers[0].position.lng(), markers[1].position.lng()),
+ west: Math.min(markers[0].position.lng(), markers[1].position.lng())
+ };
+ rect && rect.setMap(null);
+ rect = new google.maps.Rectangle({
+ strokeOpacity: 0.8,
+ strokeWeight: 0,
+ fillColor: '#007dff',
+ fillOpacity: 0.35,
+ map: map,
+ bounds: bounds
+ });
+ app.selectedBounds = [
+ { lat : bounds.west, lng : bounds.north },
+ { lat : bounds.east, lng : bounds.north },
+ { lat : bounds.east, lng : bounds.south },
+ { lat : bounds.west, lng : bounds.south },
+ ];
+ console.log('rectBounds', bounds)
}
- function clearIfNeed(oldMarker, infowindow){
- if(infowindow){
- infowindow.close();
+ });
+}
+
+function fromLatLngToPoint (latLng){
+ var siny = Math.min(Math.max(Math.sin(latLng.lat* (Math.PI / 180)), -.9999),.9999);
+ return {
+ x: 128 + latLng.lng * (256/360),
+ y: 128 + 0.5 * Math.log((1 + siny) / (1 - siny)) * -(256 / (2 * Math.PI))
+ };
+}
+
+function getTileAtLatLng(latLng,zoom){
+ var t=Math.pow(2,zoom),
+ s=256/t,
+ p=this.fromLatLngToPoint(latLng);
+ return {x:Math.floor(p.x/s),y:Math.floor(p.y/s),z:zoom};
+}
+
+function getBounds(markerAry){
+ if(markerAry && markerAry.length >1){
+ var n, s, w, e;
+ var lat = [];
+ lat[0] = markerAry[0].position.lat();
+ lat[1] = markerAry[1].position.lat();
+ if(Math.abs(lat[0]) < Math.abs(lat[1])){
+ n = lat[0];
+ s = lat[1];
}
- if(oldMarker){
- oldMarker.setMap(null);
- oldMarker = null;
+ else{
+ s = lat[0];
+ n = lat[1];
}
- }
- function getBounds(markerAry){
- if(markerAry && markerAry.length >1){
- var n, s, w, e;
- var lat = [];
- lat[0] = markerAry[0].position.lat();
- lat[1] = markerAry[1].position.lat();
- if(Math.abs(lat[0]) < Math.abs(lat[1])){
- n = lat[0];
- s = lat[1];
- }
- else{
- s = lat[0];
- n = lat[1];
- }
- var lng = [];
- lng[0] = markerAry[0].position.lng();
- lng[1] = markerAry[1].position.lng();
- if(Math.abs(lng[0]) < Math.abs(lng[1])){
- w = lng[0];
- e = lng[1];
- }
- else{
- e = lng[0];
- w = lng[1];
- }
- return {north: n, south: s, west: w, east: e};
+ var lng = [];
+ lng[0] = markerAry[0].position.lng();
+ lng[1] = markerAry[1].position.lng();
+ if(Math.abs(lng[0]) < Math.abs(lng[1])){
+ w = lng[0];
+ e = lng[1];
+ }
+ else{
+ e = lng[0];
+ w = lng[1];
}
+ return {north: n, south: s, west: w, east: e};
}
}
-
-function extendBound(map, latLngLiteral){
- var bounds = map.getBounds();
- bounds.extend(latLngLiteral);
- map.fitBounds(bounds);
-}
diff --git a/public/demo-map.jpg b/public/demo-map.jpg
deleted file mode 100644
index 1f4ae59..0000000
Binary files a/public/demo-map.jpg and /dev/null differ
diff --git a/public/demo.html b/public/demo.html
deleted file mode 100644
index bf014bb..0000000
--- a/public/demo.html
+++ /dev/null
@@ -1,39 +0,0 @@
-
-
-
-
Origin
- - - x - - -Top left
- - - -Bottom right
- - - -Regions
+ +Zoom x {{ regionZoom }}
+ +Latitude
+ +Longitude
+ +Origin
+Top left
+ + + +Bottom right
+ + + +Tiles Generation Configs
+Zoom
+ ~ + + +This is a sample Node application deployed to Heroku. It's a reasonably simple app - but a good foundation for understanding how to get the most out of the Heroku platform.
- Getting Started with Node - Source on GitHub -git clone https://github.com/heroku/node-js-getting-started.git
- this will create a local copy of the source code for the appcd node-js-getting-started
- change directory into the local source code repositoryheroku git:remote -a <your-app-name>
- associate the Heroku app with the repository