changeset 2563:dc4fae4bdb8f

Expose axis snapping tolerance to users
author Tom Gottfried <tom@intevation.de>
date Fri, 08 Mar 2019 19:15:47 +0100
parents ce39e9954e85
children 27501719e79b
files client/src/components/ImportStretches.vue client/src/components/importschedule/Importscheduledetail.vue client/src/components/importschedule/importtypes/Bottleneck.vue client/src/store/importschedule.js pkg/common/attributes.go pkg/controllers/uploadedimports.go pkg/imports/bn.go pkg/imports/modelconvert.go pkg/imports/st.go pkg/imports/ubn.go pkg/models/imports.go schema/isrs_functions.sql schema/isrs_tests.sql
diffstat 13 files changed, 195 insertions(+), 49 deletions(-) [+]
line wrap: on
line diff
--- a/client/src/components/ImportStretches.vue	Fri Mar 08 18:57:58 2019 +0100
+++ b/client/src/components/ImportStretches.vue	Fri Mar 08 19:15:47 2019 +0100
@@ -154,6 +154,27 @@
         <div class="d-flex flex-row justify-content-between">
           <div class="mt-2  mr-2 w-50  text-left">
             <small class="text-muted">
+              <translate>Tolerance for snapping of waterway axis</translate>
+            </small>
+            <input
+              class="form-control"
+              v-model.number="tolerance"
+              placeholder=""
+              type="number"
+              step="any"
+              aria-label="tolerance"
+              id="tolerance"
+            />
+            <span class="text-left text-danger">
+              <small v-if="toleranceError && !tolerance">
+                <translate>Please enter a tolerance value</translate>
+              </small>
+            </span>
+          </div>
+        </div>
+        <div class="d-flex flex-row justify-content-between">
+          <div class="mt-2  mr-2 w-50  text-left">
+            <small class="text-muted">
               <translate>Object name</translate>
             </small>
             <input
@@ -245,12 +266,13 @@
  * SPDX-License-Identifier: AGPL-3.0-or-later
  * License-Filename: LICENSES/AGPL-3.0.txt
  *
- * Copyright (C) 2018 by via donau
+ * Copyright (C) 2018, 2019 by via donau
  *   – Österreichische Wasserstraßen-Gesellschaft mbH
  * Software engineering by Intevation GmbH
  *
  * Author(s):
  * Thomas Junk <thomas.junk@intevation.de>
+ * Tom Gottfried <tom.gottfried@intevation.de>
  */
 import { mapState, mapGetters } from "vuex";
 import { displayError, displayInfo } from "@/lib/errors.js";
@@ -266,6 +288,7 @@
       funktion: "",
       startrhm: "",
       endrhm: "",
+      tolerance: "",
       objbn: "",
       nobjbn: "",
       countryCode: "",
@@ -277,6 +300,7 @@
       funktionError: false,
       startrhmError: false,
       endrhmError: false,
+      toleranceError: false,
       objbnError: false,
       nobjbnError: false,
       date_infoError: false,
@@ -339,6 +363,7 @@
       this.edit = true;
       this.startrhm = properties.lower;
       this.endrhm = properties.upper;
+      this.tolerance = properties.tolerance;
       this.idEditable = false;
     },
     deleteStretch(stretch) {
@@ -393,6 +418,7 @@
       this.idEditable = true;
       this.funktion = "";
       this.startrhm = "";
+      this.tolerance = "";
       this.endrhm = "";
       this.objbn = "";
       this.nobjbn = "";
@@ -405,6 +431,7 @@
       this.funktionError = false;
       this.startrhmError = false;
       this.endrhmError = false;
+      this.toleranceError = false;
       this.objbnError = false;
       this.nobjbnError = false;
       this.date_infoError = false;
@@ -430,6 +457,7 @@
         "id",
         "funktion",
         "startrhm",
+        "tolerance",
         "endrhm",
         "objbn",
         "nobjbn",
@@ -452,6 +480,7 @@
         !this.id ||
         !this.startrhm ||
         !this.endrhm ||
+        !this.tolerance ||
         !this.source ||
         !this.date_info ||
         !this.objbn ||
@@ -462,6 +491,7 @@
         name: this.id,
         from: this.startrhm,
         to: this.endrhm,
+        tolerance: this.tolerance,
         "source-organization": this.source,
         "date-info": this.date_info,
         objnam: this.objbn,
--- a/client/src/components/importschedule/Importscheduledetail.vue	Fri Mar 08 18:57:58 2019 +0100
+++ b/client/src/components/importschedule/Importscheduledetail.vue	Fri Mar 08 19:15:47 2019 +0100
@@ -96,7 +96,9 @@
           <Bottleneck
             v-if="import_ == $options.IMPORTTYPES.BOTTLENECK && !directImport"
             @urlChanged="setUrl"
+            @toleranceChanged="setTolerance"
             :url="url"
+            :tolerance="tolerance"
           ></Bottleneck>
           <Distancemarksvirtual
             v-if="import_ == $options.IMPORTTYPES.DISTANCEMARKSVIRTUAL"
@@ -422,12 +424,13 @@
  * SPDX-License-Identifier: AGPL-3.0-or-later
  * License-Filename: LICENSES/AGPL-3.0.txt
  *
- * Copyright (C) 2018 by via donau
+ * Copyright (C) 2018, 2019 by via donau
  *   – Österreichische Wasserstraßen-Gesellschaft mbH
  * Software engineering by Intevation GmbH
  *
  * Author(s):
  * Thomas Junk <thomas.junk@intevation.de>
+ * Tom Gottfried <tom.gottfried@intevation.de>
  */
 import {
   IMPORTTYPES,
@@ -570,6 +573,14 @@
           return false;
       }
     },
+    isToleranceRequired() {
+      switch (this.import_) {
+        case this.$options.IMPORTTYPES.BOTTLENECK:
+          return true;
+        default:
+          return false;
+      }
+    },
     isValid() {
       if (!this.import_) return false;
       if (this.directImport && !this.uploadFile) return false;
@@ -577,6 +588,7 @@
         if (this.isURLRequired && !this.url) return false;
         if (this.isSortbyRequired && !this.sortBy) return false;
         if (this.isFeatureTypeRequired && !this.featureType) return false;
+        if (this.isToleranceRequired && !this.tolerance) return false;
         if (this.isCredentialsRequired && (!this.username || !this.password))
           return false;
         if (this.import_ == this.$options.IMPORTTYPES.FAIRWAYDIMENSION) {
@@ -609,6 +621,9 @@
     setSortBy(value) {
       this.sortBy = value;
     },
+    setTolerance(value) {
+      this.tolerance = value;
+    },
     setUsername(value) {
       this.username = value;
     },
@@ -673,6 +688,7 @@
       this.cronString = this.currentSchedule.cronString;
       this.featureType = this.currentSchedule.featureType;
       this.sortBy = this.currentSchedule.sortBy;
+      this.tolerance = this.currentSchedule.tolerance;
       this.username = this.currentSchedule.username;
       this.password = this.currentSchedule.password;
       this.LOS = this.currentSchedule.LOS;
@@ -765,6 +781,10 @@
         if (!this.sortBy) return;
         data["sort-by"] = this.sortBy;
       }
+      if (this.isToleranceRequired) {
+        if (!this.tolerance) return;
+        data["tolerance"] = parseFloat(this.tolerance);
+      }
       if (this.isCredentialsRequired) {
         if (!this.username || !this.password) return;
         data["user"] = this.username;
@@ -836,6 +856,10 @@
         if (!this.featureType) return;
         config["feature-type"] = this.featureType;
       }
+      if (this.isToleranceRequired) {
+        if (!this.tolerance) return;
+        config["tolerance"] = parseFloat(this.tolerance);
+      }
       if (this.isCredentialsRequired) {
         if (!this.username || !this.password) return;
         config = {
--- a/client/src/components/importschedule/importtypes/Bottleneck.vue	Fri Mar 08 18:57:58 2019 +0100
+++ b/client/src/components/importschedule/importtypes/Bottleneck.vue	Fri Mar 08 19:15:47 2019 +0100
@@ -45,6 +45,30 @@
         ><translate class="text-danger">Please enter a URL</translate></small
       >
     </div>
+    <div class="d-flex flex-row">
+      <div class="flex-column mt-3 mr-3 w-50">
+        <div class="flex-row text-left">
+          <small class="text-muted">
+            <translate>Tolerance for snapping of waterway axis</translate>
+          </small>
+        </div>
+        <div class="w-100">
+          <input
+            @input="toleranceChanged"
+            class="tolerance form-control"
+            type="number"
+            :value="tolerance"
+          />
+        </div>
+        <div v-if="!tolerance" class="d-flex flex-row">
+          <small
+            ><translate class="text-danger"
+              >Please enter a tolerance value</translate
+            ></small
+          >
+        </div>
+      </div>
+    </div>
   </div>
 </template>
 
@@ -55,19 +79,23 @@
  * SPDX-License-Identifier: AGPL-3.0-or-later
  * License-Filename: LICENSES/AGPL-3.0.txt
  *
- * Copyright (C) 2018 by via donau
+ * Copyright (C) 2018, 2019 by via donau
  *   – Österreichische Wasserstraßen-Gesellschaft mbH
  * Software engineering by Intevation GmbH
  *
  * Author(s):
  * Thomas Junk <thomas.junk@intevation.de>
+ * Tom Gottfried <tom.gottfried@intevation.de>
  */
 export default {
   name: "bottleneckimport",
-  props: ["url"],
+  props: ["url", "tolerance"],
   methods: {
     urlChanged(e) {
       this.$emit("urlChanged", e.target.value);
+    },
+    toleranceChanged(e) {
+      this.$emit("toleranceChanged", e.target.value);
     }
   }
 };
--- a/client/src/store/importschedule.js	Fri Mar 08 18:57:58 2019 +0100
+++ b/client/src/store/importschedule.js	Fri Mar 08 19:15:47 2019 +0100
@@ -77,6 +77,7 @@
     triggerActive: true,
     featureType: null,
     sortBy: "hydro_scamin",
+    tolerance: 5,
     username: "",
     password: "",
     LOS: 3,
@@ -181,6 +182,7 @@
       let maxWidth = config["max-width"];
       let sourceOrganization = config["source-organization"];
       const featureType = config["feature-type"];
+      const tolerance = config["tolerance"];
       insecure = insecure == "true";
       if (insecure) {
         Vue.set(state.currentSchedule, "insecure", insecure);
@@ -191,6 +193,9 @@
       if (sortBy) {
         Vue.set(state.currentSchedule, "sortBy", sortBy);
       }
+      if (tolerance) {
+        Vue.set(state.currentSchedule, "tolerance", tolerance);
+      }
       if (user) {
         Vue.set(state.currentSchedule, "username", user);
       }
--- a/pkg/common/attributes.go	Fri Mar 08 18:57:58 2019 +0100
+++ b/pkg/common/attributes.go	Fri Mar 08 19:15:47 2019 +0100
@@ -4,12 +4,13 @@
 // SPDX-License-Identifier: AGPL-3.0-or-later
 // License-Filename: LICENSES/AGPL-3.0.txt
 //
-// Copyright (C) 2018 by via donau
+// Copyright (C) 2018, 2019 by via donau
 //   – Österreichische Wasserstraßen-Gesellschaft mbH
 // Software engineering by Intevation GmbH
 //
 // Author(s):
 //  * Sascha L. Teichmann <sascha.teichmann@intevation.de>
+//  * Tom Gottfried <tom.gottfried@intevation.de>
 
 package common
 
@@ -158,6 +159,24 @@
 	return ca.Set(key, v)
 }
 
+func (ca Attributes) Float(key string) (float64, bool) {
+	s, found := ca.Get(key)
+	if !found {
+		return 0, false
+	}
+	f, err := strconv.ParseFloat(s, 64)
+	if err != nil {
+		log.Printf("error: %v\n", err)
+		return 0, false
+	}
+	return f, true
+}
+
+func (ca Attributes) SetFloat(key string, value float64) bool {
+	v := strconv.FormatFloat(value, 'e', -1, 64)
+	return ca.Set(key, v)
+}
+
 func (ca Attributes) Duration(key string) (time.Duration, bool) {
 	s, found := ca.Get(key)
 	if !found {
--- a/pkg/controllers/uploadedimports.go	Fri Mar 08 18:57:58 2019 +0100
+++ b/pkg/controllers/uploadedimports.go	Fri Mar 08 19:15:47 2019 +0100
@@ -92,7 +92,8 @@
 		imports.UBNJobKind,
 		"data.xml",
 		func(_ *http.Request, dir string) (imports.Job, error) {
-			return &imports.UploadedBottleneck{Dir: dir}, nil
+			// TODO expose tolerance to endpoint
+			return &imports.UploadedBottleneck{Dir: dir, Tolerance: 5}, nil
 		},
 	)
 }
--- a/pkg/imports/bn.go	Fri Mar 08 18:57:58 2019 +0100
+++ b/pkg/imports/bn.go	Fri Mar 08 19:15:47 2019 +0100
@@ -30,6 +30,8 @@
 type Bottleneck struct {
 	// URL is the URL of the SOAP service.
 	URL string `json:"url"`
+	// Tolerance used for axis snapping
+	Tolerance float64 `json:"tolerance"`
 	// Insecure indicates if HTTPS traffic
 	// should validate certificates or not.
 	Insecure bool `json:"insecure"`
@@ -64,7 +66,7 @@
   $4,
   isrsrange(isrs_fromText($5), isrs_fromText($6)),
   ISRSrange_area(
-    isrsrange(isrs_fromText($5), isrs_fromText($6)),
+    ISRSrange_axis(isrsrange(isrs_fromText($5), isrs_fromText($6)), $14),
     (SELECT ST_Collect(CAST(area AS geometry))
         FROM waterway.waterway_area)),
   $7,
@@ -162,7 +164,7 @@
 		return resp.Export_bn_by_isrsResult.BottleNeckType, nil
 	}
 
-	return storeBottlenecks(ctx, fetch, importID, conn, feedback)
+	return storeBottlenecks(ctx, fetch, importID, conn, feedback, bn.Tolerance)
 }
 
 func storeBottlenecks(
@@ -171,6 +173,7 @@
 	importID int64,
 	conn *sql.Conn,
 	feedback Feedback,
+	tolerance float64,
 ) (interface{}, error) {
 	start := time.Now()
 
@@ -202,7 +205,7 @@
 
 	for _, bn := range bns {
 		if err := storeBottleneck(
-			ctx, importID, conn, feedback, bn, &nids,
+			ctx, importID, conn, feedback, bn, &nids, tolerance,
 			hasStmt, insertStmt, trackStmt); err != nil {
 			return nil, err
 		}
@@ -228,6 +231,7 @@
 	feedback Feedback,
 	bn *ifbn.BottleNeckType,
 	nids *[]string,
+	tolerance float64,
 	hasStmt, insertStmt, trackStmt *sql.Stmt,
 ) error {
 
@@ -278,6 +282,7 @@
 		limiting,
 		bn.Date_Info,
 		bn.Source,
+		tolerance,
 	).Scan(&nid)
 	if err != nil {
 		feedback.Warn("Failed to insert '%s' into database", bn.OBJNAM)
--- a/pkg/imports/modelconvert.go	Fri Mar 08 18:57:58 2019 +0100
+++ b/pkg/imports/modelconvert.go	Fri Mar 08 19:15:47 2019 +0100
@@ -39,8 +39,9 @@
 	BNJobKind: func(input interface{}) interface{} {
 		bi := input.(*models.BottleneckImport)
 		return &Bottleneck{
-			URL:      bi.URL,
-			Insecure: bi.Insecure,
+			URL:       bi.URL,
+			Tolerance: bi.Tolerance,
+			Insecure:  bi.Insecure,
 		}
 	},
 
@@ -127,6 +128,7 @@
 			Name:      sti.Name,
 			From:      sti.From,
 			To:        sti.To,
+			Tolerance: sti.Tolerance,
 			ObjNam:    sti.ObjNam,
 			NObjNam:   sti.NObjNam,
 			Source:    sti.Source,
--- a/pkg/imports/st.go	Fri Mar 08 18:57:58 2019 +0100
+++ b/pkg/imports/st.go	Fri Mar 08 19:15:47 2019 +0100
@@ -26,6 +26,7 @@
 	Name      string                 `json:"name"`
 	From      models.Isrs            `json:"from"`
 	To        models.Isrs            `json:"to"`
+	Tolerance float32                `json:"tolerance"`
 	ObjNam    string                 `json:"objnam"`
 	NObjNam   *string                `json:"nobjnam"`
 	Source    string                 `json:"source-organization"`
@@ -99,7 +100,7 @@
   $11,
   (SELECT r FROM r),
   ISRSrange_area(
-    (SELECT r FROM r),
+    ISRSrange_axis((SELECT r FROM r), $16::double precision),
     (SELECT ST_Collect(CAST(area AS geometry))
       FROM waterway.waterway_area)),
   $12,
@@ -191,6 +192,7 @@
 		nobjnm,
 		st.Date.Time,
 		st.Source,
+		st.Tolerance,
 	).Scan(&id); err != nil {
 		return nil, handleError(err)
 	}
--- a/pkg/imports/ubn.go	Fri Mar 08 18:57:58 2019 +0100
+++ b/pkg/imports/ubn.go	Fri Mar 08 19:15:47 2019 +0100
@@ -26,6 +26,8 @@
 
 type UploadedBottleneck struct {
 	Dir string `json:"dir"`
+	// Tolerance used for axis snapping
+	Tolerance float64 `json:"tolerance"`
 }
 
 // UBNJobKind is the import queue type identifier.
@@ -84,5 +86,6 @@
 		return dst.Export_bn_by_isrsResult.BottleNeckType, nil
 	}
 
-	return storeBottlenecks(ctx, fetch, importID, conn, feedback)
+	return storeBottlenecks(
+		ctx, fetch, importID, conn, feedback, ubn.Tolerance)
 }
--- a/pkg/models/imports.go	Fri Mar 08 18:57:58 2019 +0100
+++ b/pkg/models/imports.go	Fri Mar 08 19:15:47 2019 +0100
@@ -4,12 +4,14 @@
 // SPDX-License-Identifier: AGPL-3.0-or-later
 // License-Filename: LICENSES/AGPL-3.0.txt
 //
-// Copyright (C) 2018 by via donau
+// Copyright (C) 2018, 2019 by via donau
 //   – Österreichische Wasserstraßen-Gesellschaft mbH
 // Software engineering by Intevation GmbH
 //
 // Author(s):
 //  * Sascha L. Teichmann <sascha.teichmann@intevation.de>
+//  * Tom Gottfried <tom.gottfried@intevation.de>
+
 package models
 
 import (
@@ -27,6 +29,9 @@
 
 	BottleneckImport struct {
 		ConfigurableURLImport
+
+		// Tolerance used for axis snapping
+		Tolerance float64 `json:"tolerance"`
 	}
 
 	// GaugeMeasurementImport contains data used to define the endpoint
@@ -95,6 +100,7 @@
 		Name      string          `json:"name"`
 		From      Isrs            `json:"from"`
 		To        Isrs            `json:"to"`
+		Tolerance float32         `json:"tolerance"`
 		ObjNam    string          `json:"objnam"`
 		NObjNam   *string         `json:"nobjnam"`
 		Source    string          `json:"source-organization"`
@@ -143,6 +149,26 @@
 	return nil
 }
 
+func (bn *BottleneckImport) MarshalAttributes(attrs common.Attributes) error {
+	if err := bn.ConfigurableURLImport.MarshalAttributes(attrs); err != nil {
+		return err
+	}
+	attrs.SetFloat("tolerance", bn.Tolerance)
+	return nil
+}
+
+func (bn *BottleneckImport) UnmarshalAttributes(attrs common.Attributes) error {
+	if err := bn.ConfigurableURLImport.UnmarshalAttributes(attrs); err != nil {
+		return err
+	}
+	tol, found := attrs.Float("tolerance")
+	if !found {
+		return errors.New("missing 'tolerance' attribute")
+	}
+	bn.Tolerance = tol
+	return nil
+}
+
 func (fdi *FairwayDimensionImport) MarshalAttributes(attrs common.Attributes) error {
 	if err := fdi.WFSImport.MarshalAttributes(attrs); err != nil {
 		return err
--- a/schema/isrs_functions.sql	Fri Mar 08 18:57:58 2019 +0100
+++ b/schema/isrs_functions.sql	Fri Mar 08 19:15:47 2019 +0100
@@ -47,6 +47,7 @@
 -- Uses the table waterway.distance_marks_virtual to map ISRS location codes
 -- to their geo-location.
 -- Distance marks are assumed to be near the axis.
+-- Returns the axis geometry transformed to the best matching UTM zone.
 CREATE OR REPLACE FUNCTION ISRSrange_axis(
     stretch isrsrange,
     tolerance float
@@ -135,32 +136,28 @@
     LANGUAGE plpgsql
     STABLE PARALLEL SAFE;
 
--- Clip an area to a stretch given by a pair of ISRS location codes.
--- Uses ISRSrange_axis() to retrieve the respective clipped axis used to find
--- perpendicular direction at geo-locations of ISRS codes.
+-- Clip an area to a stretch given by a geometry representing an axis (e.g.
+-- the output of ISRSrange_axis()).
+-- Clipping is done by cutting the area in perpendicular direction at
+-- the ends of the given axis.
 -- The area passed as argument is assumed to intersect with the axis
 -- (use e.g. waterway area or fairway dimensions).
 -- If a multipolygon is passed, the union of the polygons intersecting with the
--- relevant part of the axis is used for clipping.
+-- axis is used for clipping.
 CREATE OR REPLACE FUNCTION ISRSrange_area(
-    stretch isrsrange,
+    axis geometry,
     area geometry
 ) RETURNS geometry
 AS $$
     WITH
-        axis_substring AS (
-            SELECT ISRSrange_axis(stretch, 5) AS line),
-        utm_zone AS (
-            SELECT best_utm(stretch) AS z),
         area_subset AS (
             -- In case area is a multipolygon, process the union of those
             -- polygons, which intersect with the axis. The union is to avoid
             -- problems with invalid/self-intersecting multipolygons
             SELECT ST_Union(a_dmp.geom) AS area
-                FROM axis_substring, utm_zone, LATERAL (
-                    SELECT ST_MakeValid(ST_Transform(geom, z)) AS geom
-                        FROM ST_Dump(area)) AS a_dmp
-                WHERE ST_Intersects(a_dmp.geom, axis_substring.line)
+                FROM (SELECT ST_MakeValid(ST_Transform(geom, ST_SRID(axis)))
+                        FROM ST_Dump(area)) AS a_dmp (geom)
+                WHERE ST_Intersects(a_dmp.geom, axis)
             ),
         rotated_ends AS (
             SELECT ST_Collect(ST_Scale(
@@ -168,11 +165,11 @@
                         (ST_X(p1) - ST_X(p2)) / 2,
                         (ST_Y(p1) - ST_Y(p2)) / 2),
                     ST_Point(d, d), p1)) AS blade
-                FROM axis_substring, area_subset,
-                    LATERAL (SELECT i, ST_PointN(line, i) AS p1
+                FROM (SELECT i, ST_PointN(axis, i) AS p1
                         FROM (VALUES (1), (-1)) AS idx (i)) AS ep,
-                    ST_Rotate(ST_PointN(line, i*2), pi()/2, p1) AS ep2 (p2),
+                    ST_Rotate(ST_PointN(axis, i*2), pi()/2, p1) AS ep2 (p2),
                     ST_Makeline(p1, p2) AS e (e),
+                    area_subset,
                     LATERAL (SELECT (ST_MaxDistance(p1, area) / ST_Length(e))
                             * 2) AS d (d)),
         range_area AS (
@@ -183,8 +180,7 @@
         -- From the polygons returned by the last CTE, select only those
         -- around the clipped axis
         SELECT ST_Multi(ST_Transform(ST_Union(range_area.geom), ST_SRID(area)))
-            FROM axis_substring, range_area
-            WHERE ST_Intersects(ST_Buffer(range_area.geom, -0.0001),
-                axis_substring.line)
+            FROM range_area
+            WHERE ST_Intersects(ST_Buffer(range_area.geom, -0.0001), axis)
     $$
     LANGUAGE sql;
--- a/schema/isrs_tests.sql	Fri Mar 08 18:57:58 2019 +0100
+++ b/schema/isrs_tests.sql	Fri Mar 08 19:15:47 2019 +0100
@@ -4,7 +4,7 @@
 -- SPDX-License-Identifier: AGPL-3.0-or-later
 -- License-Filename: LICENSES/AGPL-3.0.txt
 
--- Copyright (C) 2018 by via donau
+-- Copyright (C) 2018, 2019 by via donau
 --   – Österreichische Wasserstraßen-Gesellschaft mbH
 -- Software engineering by Intevation GmbH
 
@@ -52,9 +52,10 @@
     'ISRSrange_axis fails if no contiguous axis can be constructed');
 
 SELECT ok(
-    ISRSrange_area(isrsrange(
-            ('AT', 'XXX', '00001', '00000', 0)::isrs,
-            ('AT', 'XXX', '00001', '00000', 1)::isrs),
+    ISRSrange_area(ISRSrange_axis(isrsrange(
+                ('AT', 'XXX', '00001', '00000', 0)::isrs,
+                ('AT', 'XXX', '00001', '00000', 1)::isrs),
+            5),
         ST_SetSRID('POLYGON((0 1, 0 2, 1 2, 1 1, 0 1))'::geometry, 4326)
     ) IS NULL,
     'ISRSrange_area returns NULL, if given area does not intersect with axis');
@@ -62,9 +63,10 @@
 SELECT results_eq($$
     SELECT every(ST_DWithin(
             ST_Boundary(ISRSrange_area(
-                isrsrange(
-                    ('AT', 'XXX', '00001', '00000', 0)::isrs,
-                    ('AT', 'XXX', '00001', '00000', 1)::isrs),
+                ISRSrange_axis(isrsrange(
+                        ('AT', 'XXX', '00001', '00000', 0)::isrs,
+                        ('AT', 'XXX', '00001', '00000', 1)::isrs),
+                    5),
                 (SELECT ST_Collect(CAST(area AS geometry))
                     FROM waterway.waterway_area))),
             geom,
@@ -83,9 +85,10 @@
 SELECT ok(
     2 = ST_NumGeometries(
         ISRSrange_area(
-            isrsrange(
-                ('AT', 'XXX', '00001', '00000', 0)::isrs,
-                ('AT', 'XXX', '00001', '00000', 1)::isrs),
+            ISRSrange_axis(isrsrange(
+                    ('AT', 'XXX', '00001', '00000', 0)::isrs,
+                    ('AT', 'XXX', '00001', '00000', 1)::isrs),
+                5),
             ST_SetSRID(ST_Collect(
                     ST_Translate(:'test_area',
                         (ST_XMax(:'test_area'::geometry)
@@ -101,9 +104,10 @@
 SELECT ok(
     1 = ST_NumGeometries(
         ISRSrange_area(
-            isrsrange(
-                ('AT', 'XXX', '00001', '00000', 0)::isrs,
-                ('AT', 'XXX', '00001', '00000', 1)::isrs),
+            ISRSrange_axis(isrsrange(
+                    ('AT', 'XXX', '00001', '00000', 0)::isrs,
+                    ('AT', 'XXX', '00001', '00000', 1)::isrs),
+                5),
             ST_SetSRID(ST_Collect(
                     ST_Translate(:'test_area',
                         (ST_XMax(:'test_area'::geometry)
@@ -119,9 +123,10 @@
 SELECT results_eq($$
     SELECT every(ST_DWithin(
             ST_Boundary(ISRSrange_area(
-                isrsrange(
-                    ('AT', 'XXX', '00001', '00000', 0)::isrs,
-                    ('AT', 'XXX', '00001', '00000', 2)::isrs),
+            ISRSrange_axis(isrsrange(
+                        ('AT', 'XXX', '00001', '00000', 0)::isrs,
+                        ('AT', 'XXX', '00001', '00000', 2)::isrs),
+                    5),
                 (SELECT ST_Collect(CAST(area AS geometry))
                     FROM waterway.waterway_area))),
             geom,