Skip to content

Commit

Permalink
Create the package and add document (#1)
Browse files Browse the repository at this point in the history
* added datatype, widget and function

* Provided a completed Readme document.
  • Loading branch information
aj-he authored Dec 4, 2019
1 parent cab7ac7 commit d01a002
Show file tree
Hide file tree
Showing 31 changed files with 1,080 additions and 0 deletions.
86 changes: 86 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,88 @@
# arches-bngpoint
Arches package containing the BNGPoint datatype, supporting widget and functions to sync with a geojson-feature-collection node node.

This was written and tested against Arches v4.4.1. However, It will likely support all v4.4.x versions.

Arches v5.0.0 compatible version has been developed and will be released in the same timeframe as v5.0.0.

# Installation

To install into your Arches project run the following command:

```bat
python manage.py packages -o load_package -s /path/to/arches-bngpoint/pkg
```


# Information

## BNG Datatype

The BNG Datatype was written to contain a 12 figure alphanumeric grid reference representing the centre point location of a resource e.g. ***SU1234512345***. Details of this coordinate system can be found [here](https://en.wikipedia.org/wiki/Ordnance_Survey_National_Grid).

### Validation

The value must be 12 figures and zero padded if necessary e.g. ***TA123123*** must be padded to ***TA1230012300***. This is validated during a tile card.

When using the widget to enter the value it will automatically be padded before saving. It you are importing the data then it must have been padded to 12 figures before hand.


## BNG Widget

The BNG Widget is the default widget for the BNG datatype. They are linked in the BNG Widgets python config, which states the datatype that it can be used with: `"datatype": "bngcentrepoint" `

The widget accepts a text value as the input in the following formats:

* Alphanumeric BNG (deafult)
* Absolute BNG
* Long/Lat

The format is selected from the drop down to ensure it is converted to a 12 figure alphanumeric grid reference correctly.

The widget triggers the process of transforming data into a 12 character Alphanumeric BNG grid reference once focus is removed from the input textbox (i.e. when a user clicks outside the input textbox).

Error messages are displayed, in bold red text, above the Preview element to guide users when they have entered an incorrect value.

### Alphanumeric BNG
The widget checks that there is a 100km Grid Square reference at the start of the value entered and then handles the number element of the value to that the length of the number element is 10 (making a total length of 12 for the complete value). It does this by padding the easting and northing number values with 0s.

*Example input alphanumeric BNG: SP0123401234*

### Absolute BNG
The widget splits the value in half to create easting and northing. It uses the first number of the eastings and the first number of the northings to identify the correct 100km Grid Square value and then pads out the remaining numbers as necessary to achieve an Alphanumeric BNG grid reference with a length of 12.

*Example input absolute BNG: 401234,201234*

### Long/Lat

We state long/lat in that order because they represent the x/y order of coordinates to match the other two. Lat/long would reverse the order to y/x.

Using the Proj4JS module, the long/lat values (split on a comma and turned into integers) are reprojected to return an OSGB absolute grid reference. The resulting value is handled as described in the Absolute BNG section.

*Example input Long/Lat: -1.54,55.5*


---
## BNG to GeoJSON and GeoJSON to BNG functions


### What the functions do

The BNG to GeoJSON and GeoJSON to BNG functions work together to ensure the record's Geometry and BNG centre point values remain synchronised.

The BNG to GeoJSON function takes a 12 figure alphanumeric grid reference saved as the NGR value and populates the geometry node with a point at the grid reference. If there are other geometries present then they are kept but a point is added at the BNG position. This point is updated when the BNG value is.

The GeoJSON to BNG function takes whatever geometry/ies has been added to the geometry node, calculates the centre point of the geometry/ies and populates the NGR value with the centre point value as an alphanumeric grid reference.


### Bulk loading data

When carrying out a bulk load of data, these functions need to be unattached to the resource model so that the data being added is not overwritten. There may be cases where the bulk load should use these functions but you must be aware of the performance hit on loading times.

# Limitations

The datatype and functions should work for everything in the OS National Grid except for off the north coast of mainland Scotland as it does not account for 7 figure northings.

The BNG and the GEOJSON nodes ***must*** be in the same tile OR in tiles that share the same parent tile. It is very difficult to find a way of determining the correct parent tile outside this configuration. The models at Historic England using this function were designed to meet these limitations.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
57 changes: 57 additions & 0 deletions pkg/extensions/datatypes/bngcentrepoint.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
from arches.app.datatypes.base import BaseDataType
from arches.app.models.models import Widget
from arches.app.models.system_settings import settings

bngpoint = Widget.objects.get(name="bngpoint")

details = {
'datatype': 'bngcentrepoint',
'iconclass': 'fa fa-location-arrow',
'modulename': 'bngcentrepoint.py',
'classname': 'BNGCentreDataType',
'defaultwidget': bngpoint,
'defaultconfig': None,
'configcomponent': None,
'configname': None,
'isgeometric': False,
'issearchable': False
}

class BNGCentreDataType(BaseDataType):


def validate(self, value, row_number=None, source=None):

errors = []
gridSquareArray = ["NA","NB","NC","ND","NE","NF","NG","NH","NJ","NK","NL", "NM","NN","NO","NP","NR","NS","NT","NU","NV","NW","NX","NY","NZ","OA","OB","OF","OG","OL","OM","OQ","OR","OV","OW","SA","SB","SC","SD","SE","SF","SG","SH","SJ","SK","SL","SM","SN","SO","SP","SQ","SR","SS","ST","SU","SV","SW","SX","SY","SZ","TA","TB","TF","TG","TL","TM","TQ","TR","TV","TW"]
try:
# CS - Validation for datatype. Replicates functionality in widget which will be removed once datatype validation is fixed.
firstTwoCharacters = value[0:2]
numberElement = value[2:]

firstTwoCharacters in gridSquareArray
isinstance(int(numberElement),int)
len(value) == 12
except Exception:
errors.append({
'type':'ERROR',
'message': 'Issue with input data'
})

return errors



def append_to_document(self, document, nodevalue, nodeid, tile):

document['strings'].append({
'string': nodevalue,
'nodegroup_id': tile.nodegroup_id
})



def get_search_terms(self, nodevalue, nodeid=None):
return [
nodevalue
]
Empty file.
28 changes: 28 additions & 0 deletions pkg/extensions/functions/bngpoint-to-geojson-function.htm
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{% load i18n %}

<div style="height:0px">
<div class="row widget-container">
<div class="form-group">
<div class="relative">
<label class="col-xs-12 control-label widget-input-label"> {% trans "BNG Node" %}</label>
</div>

<div class="col-xs-12">
<select data-placeholder="{% trans "Choose a card." %}"
data-bind="chosen: {width: '100%', disable_search_threshold: 15}, value: bng_node, options: nodesBNG, optionsText: 'name', optionsValue: 'nodeid', valueAllowUnset: true"></select>
</div>
</div>

<div class="form-group">
<div class="relative">
<label class="col-xs-12 control-label widget-input-label"> {% trans "GeoJSON Node" %}</label>
</div>

<div class="col-xs-12">
<select data-placeholder="{% trans "Choose a card." %}"
data-bind="chosen: {width: '100%', disable_search_threshold: 15}, value: geojson_node, options: nodesGeoJSON, optionsText: 'name', optionsValue: 'nodeid', valueAllowUnset: true"></select>
</div>
</div>

</div>
</div>
77 changes: 77 additions & 0 deletions pkg/extensions/functions/bngpoint-to-geojson-function.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
define(['knockout',
'knockout-mapping',
'views/list',
'viewmodels/function',
'bindings/chosen'],
function (ko, koMapping, ListView, FunctionViewModel, chosen) {
return ko.components.register('views/components/functions/bngpoint-to-geojson-function', {
viewModel: function(params) {
FunctionViewModel.apply(this, arguments);
console.log("Running a sample function")
var self = this;
this.nodesBNG = ko.observableArray();
this.nodesGeoJSON = ko.observableArray();
this.bng_node = params.config.bng_node;
this.geojson_node = params.config.geojson_node;
this.triggering_nodegroups = params.config.triggering_nodegroups;
this.bng_node.subscribe(function(ng){
_.each(self.nodesBNG(),function(node){
if (node.datatype !== "semantic"){

if (ng === node.nodeid){
self.triggering_nodegroups.push(node.nodegroup_id);
params.config.bng_nodegroup = node.nodegroup_id;
console.log("bng_nodegroup",self.bng_nodegroup);
}

}
})
});

this.geojson_node.subscribe(function(o_n){
console.log('GeoJSON node id:', o_n);
_.each(self.nodesGeoJSON(),function(node){
if (node.datatype !== "semantic"){

if (o_n === node.nodeid){
params.config.geojson_nodegroup = node.nodegroup_id;
console.log("geojson_nodegroup",self.geojson_nodegroup);
}
}

})


})




this.graph.nodes.forEach(function(node){
if (node.datatype != 'semantic'){
if (node.datatype === "geojson-feature-collection"){
this.nodesGeoJSON.push(node);
}
else if (node.datatype === "bngcentrepoint"){
this.nodesBNG.push(node);
}

}
}, this);










window.setTimeout(function(){$("select[data-bind^=chosen]").trigger("chosen:updated")}, 300);
},
template: {
require: 'text!templates/views/components/functions/bngpoint-to-geojson-function.htm'
}
});
})
Loading

0 comments on commit d01a002

Please sign in to comment.