mirror of
https://github.com/FoggedLens/iD.git
synced 2026-05-16 13:59:27 +02:00
Merge branch 'master' into layers
This commit is contained in:
@@ -2,7 +2,10 @@ var fs = require('fs'),
|
||||
path = require('path'),
|
||||
glob = require('glob'),
|
||||
YAML = require('js-yaml'),
|
||||
_ = require('./js/lib/lodash');
|
||||
_ = require('./js/lib/lodash'),
|
||||
jsonschema = require('jsonschema'),
|
||||
fieldSchema = require('./data/presets/schema/field.json'),
|
||||
presetSchema = require('./data/presets/schema/preset.json');
|
||||
|
||||
function read(f) {
|
||||
return JSON.parse(fs.readFileSync(f));
|
||||
@@ -16,6 +19,21 @@ function rp(f) {
|
||||
return r('presets/' + f);
|
||||
}
|
||||
|
||||
function validate(file, instance, schema) {
|
||||
var result = jsonschema.validate(instance, schema);
|
||||
if (result.length) {
|
||||
console.error(file + ": ");
|
||||
result.forEach(function(error) {
|
||||
if (error.property) {
|
||||
console.error(error.property + ' ' + error.message);
|
||||
} else {
|
||||
console.error(error);
|
||||
}
|
||||
});
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
var translations = {
|
||||
fields: {},
|
||||
presets: {}
|
||||
@@ -25,12 +43,16 @@ var fields = {};
|
||||
glob.sync(__dirname + '/data/presets/fields/*.json').forEach(function(file) {
|
||||
var field = read(file),
|
||||
id = path.basename(file, '.json');
|
||||
|
||||
validate(file, field, fieldSchema);
|
||||
|
||||
translations.fields[id] = {label: field.label};
|
||||
if (field.strings) {
|
||||
for (var i in field.strings) {
|
||||
translations.fields[id][i] = field.strings[i];
|
||||
}
|
||||
}
|
||||
|
||||
fields[id] = field;
|
||||
});
|
||||
fs.writeFileSync('data/presets/fields.json', JSON.stringify(fields, null, 4));
|
||||
@@ -39,10 +61,14 @@ var presets = {};
|
||||
glob.sync(__dirname + '/data/presets/presets/**/*.json').forEach(function(file) {
|
||||
var preset = read(file),
|
||||
id = file.match(/presets\/presets\/([^.]*)\.json/)[1];
|
||||
|
||||
validate(file, preset, presetSchema);
|
||||
|
||||
translations.presets[id] = {
|
||||
name: preset.name,
|
||||
terms: (preset.terms || []).join(',')
|
||||
};
|
||||
|
||||
presets[id] = preset;
|
||||
});
|
||||
fs.writeFileSync('data/presets/presets.json', JSON.stringify(presets, null, 4));
|
||||
|
||||
+2
-3
@@ -283,7 +283,7 @@ ul.link-list li:last-child {
|
||||
|
||||
div.hide,
|
||||
form.hide {
|
||||
display:none;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.deemphasize {
|
||||
@@ -1147,12 +1147,11 @@ div.combobox {
|
||||
/* tag editor */
|
||||
|
||||
.inspector-inner.additional-tags {
|
||||
border-bottom: 1px solid #ccc;
|
||||
border-top: 1px solid #ccc;
|
||||
}
|
||||
|
||||
.tag-list {
|
||||
margin-top: 10px;
|
||||
padding-top: 20px;
|
||||
}
|
||||
|
||||
.tag-row {
|
||||
|
||||
@@ -588,6 +588,10 @@ locale.en = {
|
||||
"name": "Building",
|
||||
"terms": ""
|
||||
},
|
||||
"building/entrance": {
|
||||
"name": "Entrance",
|
||||
"terms": ""
|
||||
},
|
||||
"entrance": {
|
||||
"name": "Entrance",
|
||||
"terms": ""
|
||||
@@ -1047,6 +1051,7 @@ locale.en = {
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
locale.zh = {
|
||||
"modes": {
|
||||
"add_area": {
|
||||
|
||||
@@ -256,6 +256,9 @@ en:
|
||||
building:
|
||||
name: Building
|
||||
terms: ""
|
||||
building/entrance:
|
||||
name: Entrance
|
||||
terms: ""
|
||||
entrance:
|
||||
name: Entrance
|
||||
terms: ""
|
||||
|
||||
@@ -3,15 +3,14 @@
|
||||
"icon": "highway",
|
||||
"id": "Road",
|
||||
"members": [
|
||||
"highway/residential",
|
||||
"highway/motorway",
|
||||
"highway/trunk",
|
||||
"highway/primary",
|
||||
"highway/secondary",
|
||||
"highway/tertiary",
|
||||
"highway/unclassified",
|
||||
"highway/residential",
|
||||
"highway/service",
|
||||
"highway/track",
|
||||
"highway"
|
||||
"highway/track"
|
||||
]
|
||||
}]
|
||||
|
||||
@@ -368,7 +368,7 @@
|
||||
"no"
|
||||
],
|
||||
"icon": "wheelchair",
|
||||
"universal": "true",
|
||||
"universal": true,
|
||||
"label": "Wheelchair Access"
|
||||
},
|
||||
"wikipedia": {
|
||||
|
||||
@@ -7,6 +7,6 @@
|
||||
"no"
|
||||
],
|
||||
"icon": "wheelchair",
|
||||
"universal": "true",
|
||||
"universal": true,
|
||||
"label": "Wheelchair Access"
|
||||
}
|
||||
|
||||
@@ -828,14 +828,6 @@
|
||||
"building_yes",
|
||||
"levels"
|
||||
],
|
||||
"additional": [
|
||||
"address",
|
||||
"phone",
|
||||
"website",
|
||||
"wikipedia",
|
||||
"elevation",
|
||||
"source"
|
||||
],
|
||||
"geometry": [
|
||||
"area"
|
||||
],
|
||||
@@ -845,6 +837,16 @@
|
||||
"terms": [],
|
||||
"name": "Building"
|
||||
},
|
||||
"building/entrance": {
|
||||
"geometry": [
|
||||
"vertex"
|
||||
],
|
||||
"tags": {
|
||||
"building": "entrance"
|
||||
},
|
||||
"name": "Entrance",
|
||||
"searchable": false
|
||||
},
|
||||
"entrance": {
|
||||
"geometry": [
|
||||
"vertex"
|
||||
|
||||
@@ -4,14 +4,6 @@
|
||||
"building_yes",
|
||||
"levels"
|
||||
],
|
||||
"additional": [
|
||||
"address",
|
||||
"phone",
|
||||
"website",
|
||||
"wikipedia",
|
||||
"elevation",
|
||||
"source"
|
||||
],
|
||||
"geometry": [
|
||||
"area"
|
||||
],
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"geometry": [
|
||||
"vertex"
|
||||
],
|
||||
"tags": {
|
||||
"building": "entrance"
|
||||
},
|
||||
"name": "Entrance",
|
||||
"searchable": false
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
{
|
||||
"title": "Field",
|
||||
"description": "A reusable form element for presets",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"key": {
|
||||
"description": "Tag key whose value is to be displayed",
|
||||
"type": "string"
|
||||
},
|
||||
"keys": {
|
||||
"description": "Tag keys whose value is to be displayed",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"type": {
|
||||
"description": "Type of field",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"address",
|
||||
"check",
|
||||
"combo",
|
||||
"defaultcheck",
|
||||
"text",
|
||||
"number",
|
||||
"tel",
|
||||
"email",
|
||||
"url",
|
||||
"radio",
|
||||
"textarea"
|
||||
],
|
||||
"required": true
|
||||
},
|
||||
"label": {
|
||||
"description": "English label for the form",
|
||||
"type": "string",
|
||||
"required": true
|
||||
},
|
||||
"geometry": {
|
||||
"type": "string"
|
||||
},
|
||||
"default": {
|
||||
"type": "string"
|
||||
},
|
||||
"indexed": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"options": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"universal": {
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"icon": {
|
||||
"type": "string"
|
||||
},
|
||||
"strings": {
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
{
|
||||
"title": "Preset",
|
||||
"description": "Associates an icon, form fields, and other UI with a set of OSM tags",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {
|
||||
"description": "The English name for the feature",
|
||||
"type": "string",
|
||||
"required": true
|
||||
},
|
||||
"geometry": {
|
||||
"description": "Valid geometry types for the feature",
|
||||
"type": "array",
|
||||
"minItems": 1,
|
||||
"uniqueItems": true,
|
||||
"items": {
|
||||
"type": "string",
|
||||
"enum": ["point", "vertex", "line", "area"]
|
||||
},
|
||||
"required": true
|
||||
},
|
||||
"tags": {
|
||||
"description": "Tags that must be present for the preset to match",
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "string"
|
||||
},
|
||||
"required": true
|
||||
},
|
||||
"fields": {
|
||||
"description": "Form fields that are displayed for the preset",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"icon": {
|
||||
"description": "Name of preset icon which represents this preset",
|
||||
"type": "string"
|
||||
},
|
||||
"terms": {
|
||||
"description": "English synonyms or related terms",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"searchable": {
|
||||
"description": "Whether or not the preset will be suggested via search",
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
@@ -13,7 +13,7 @@
|
||||
height="220"
|
||||
id="svg12393"
|
||||
version="1.1"
|
||||
inkscape:version="0.48.1 r9760"
|
||||
inkscape:version="0.48.2 r9819"
|
||||
sodipodi:docname="sprite.svg"
|
||||
inkscape:export-filename="/Users/saman/work_repos/iD/img/sprite.png"
|
||||
inkscape:export-xdpi="90"
|
||||
@@ -38,12 +38,12 @@
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="1"
|
||||
inkscape:cx="-49.735643"
|
||||
inkscape:cy="134.55123"
|
||||
inkscape:zoom="1.4142136"
|
||||
inkscape:cx="2.3449562"
|
||||
inkscape:cy="33.776287"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer12"
|
||||
showgrid="true"
|
||||
showgrid="false"
|
||||
inkscape:window-width="1280"
|
||||
inkscape:window-height="700"
|
||||
inkscape:window-x="361"
|
||||
@@ -53,7 +53,7 @@
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0"
|
||||
showguides="true"
|
||||
showguides="false"
|
||||
inkscape:guide-bbox="true"
|
||||
inkscape:snap-bbox="true"
|
||||
inkscape:snap-nodes="false">
|
||||
@@ -201,7 +201,7 @@
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
|
||||
|
Before Width: | Height: | Size: 123 KiB After Width: | Height: | Size: 123 KiB |
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 510 KiB |
@@ -21,13 +21,14 @@ iD.actions.Circularize = function(wayId, projection, count) {
|
||||
radius = d3.median(points, function(p) {
|
||||
return iD.geo.dist(centroid, p);
|
||||
}),
|
||||
ids = [];
|
||||
ids = [],
|
||||
sign = d3.geom.polygon(points).area() > 0 ? -1 : 1;
|
||||
|
||||
for (var i = 0; i < count; i++) {
|
||||
var node,
|
||||
loc = projection.invert([
|
||||
centroid[0] + Math.cos((i / 12) * Math.PI * 2) * radius,
|
||||
centroid[1] + Math.sin((i / 12) * Math.PI * 2) * radius]);
|
||||
centroid[0] + Math.cos(sign * (i / 12) * Math.PI * 2) * radius,
|
||||
centroid[1] + Math.sin(sign * (i / 12) * Math.PI * 2) * radius]);
|
||||
|
||||
if (nodes.length) {
|
||||
var idx = closestIndex(nodes, loc);
|
||||
|
||||
@@ -3,7 +3,6 @@ iD.presets.Preset = function(id, preset, fields) {
|
||||
|
||||
preset.id = id;
|
||||
preset.fields = (preset.fields || []).map(getFields);
|
||||
preset.additional = (preset.additional || []).map(getFields);
|
||||
|
||||
function getFields(f) {
|
||||
return fields[f];
|
||||
|
||||
@@ -98,7 +98,7 @@ iD.ui.TagEditor = function(context, entity) {
|
||||
}
|
||||
|
||||
editorwrap.append('div')
|
||||
.attr('class','inspector-inner col12 fillL additional-tags')
|
||||
.attr('class','inspector-inner col12 fillL2 additional-tags')
|
||||
.call(tagList, preset.id === 'other');
|
||||
|
||||
// Don't add for created entities
|
||||
|
||||
+2
-1
@@ -24,7 +24,8 @@
|
||||
"mocha-phantomjs": "~1.1.1",
|
||||
"glob": "~3.1.21",
|
||||
"js-yaml": "~2.0.3",
|
||||
"request": "~2.16.2"
|
||||
"request": "~2.16.2",
|
||||
"jsonschema": "~0.3.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": "~0.8.20"
|
||||
|
||||
@@ -26,7 +26,7 @@ describe("iD.actions.Circularize", function () {
|
||||
|
||||
graph = iD.actions.Circularize('-', projection)(graph);
|
||||
|
||||
expect(graph.entity('-').nodes.slice(0, 4)).to.eql(['c', 'b', 'a', 'd']);
|
||||
expect(graph.entity('-').nodes.slice(0, 4).sort()).to.eql(['a', 'b', 'c', 'd']);
|
||||
});
|
||||
|
||||
it("deletes unused nodes that are not members of other ways", function () {
|
||||
@@ -40,7 +40,7 @@ describe("iD.actions.Circularize", function () {
|
||||
|
||||
graph = iD.actions.Circularize('-', projection, 3)(graph);
|
||||
|
||||
expect(graph.entity('d')).to.be.undefined;
|
||||
expect(graph.entity('a')).to.be.undefined;
|
||||
});
|
||||
|
||||
it("reconnects unused nodes that are members of other ways", function () {
|
||||
@@ -51,12 +51,48 @@ describe("iD.actions.Circularize", function () {
|
||||
'd': iD.Node({id: 'd', loc: [0, 2]}),
|
||||
'e': iD.Node({id: 'e', loc: [1, 1]}),
|
||||
'-': iD.Way({id: '-', nodes: ['a', 'b', 'c', 'd', 'e', 'a']}),
|
||||
'=': iD.Way({id: '=', nodes: ['d']})
|
||||
'=': iD.Way({id: '=', nodes: ['a']})
|
||||
});
|
||||
|
||||
graph = iD.actions.Circularize('-', projection, 3)(graph);
|
||||
|
||||
expect(graph.entity('d')).to.be.undefined;
|
||||
expect(graph.entity('a')).to.be.undefined;
|
||||
expect(graph.entity('=').nodes).to.eql(['c']);
|
||||
});
|
||||
|
||||
function area(id, graph) {
|
||||
return d3.geom.polygon(_.pluck(graph.childNodes(graph.entity(id)), 'loc')).area();
|
||||
}
|
||||
|
||||
it("leaves clockwise ways clockwise", function () {
|
||||
var graph = iD.Graph({
|
||||
'a': iD.Node({id: 'a', loc: [0, 0]}),
|
||||
'b': iD.Node({id: 'b', loc: [2, 0]}),
|
||||
'c': iD.Node({id: 'c', loc: [2, 2]}),
|
||||
'd': iD.Node({id: 'd', loc: [0, 2]}),
|
||||
'+': iD.Way({id: '+', nodes: ['a', 'd', 'c', 'b', 'a']})
|
||||
});
|
||||
|
||||
expect(area('+', graph)).to.be.gt(0);
|
||||
|
||||
graph = iD.actions.Circularize('+', projection)(graph);
|
||||
|
||||
expect(area('+', graph)).to.be.gt(0);
|
||||
});
|
||||
|
||||
it("leaves counter-clockwise ways counter-clockwise", function () {
|
||||
var graph = iD.Graph({
|
||||
'a': iD.Node({id: 'a', loc: [0, 0]}),
|
||||
'b': iD.Node({id: 'b', loc: [2, 0]}),
|
||||
'c': iD.Node({id: 'c', loc: [2, 2]}),
|
||||
'd': iD.Node({id: 'd', loc: [0, 2]}),
|
||||
'-': iD.Way({id: '-', nodes: ['a', 'b', 'c', 'd', 'a']})
|
||||
});
|
||||
|
||||
expect(area('-', graph)).to.be.lt(0);
|
||||
|
||||
graph = iD.actions.Circularize('-', projection)(graph);
|
||||
|
||||
expect(area('-', graph)).to.be.lt(0);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user