SVG to HTML map and area - javascript

I have been trying to convert map in SVG to HTML area map for three days. I`am trying to do that with this SVG.
I've tried to convert this SVG with several methods and programs, but all of them failed.
e.g.: inkscape, inkscapeMap, Adobe Illustrator, Polygonator, SVGtoHTML and more.
So I wrote my own PHP script to do the job. Its works fine, but it converts only polygons. But there are two paths in SVG which need to be convert to polygon as well. I've tried to convert these paths into polygons in Illustrator and Inkscape, but apparently there is no way how to force these programs to convert path into polygons. (SVG editors probably decide alone, if they do the conversion or not). I find this topic on SO. But I'am not able to get the JS work - I dont know what the param sample is, and more - browser said that function createElementNS is unknown.
The best result I'am able to reach is this HTML, but there is still two region missing (because they are in SVG in paths)
I would be pleased for any clue.
QUESTIONS
1) How to transform SVG paths into polygons? Is that possible?
2) Is there any software which converts SVG into HTML area maps?
3) Could you show my example parametrs, in this JS function (function written Phrogz):
function polygonSampledFromPath(path,samples){
var doc = path.ownerDocument;
var poly = doc.createElementNS('http://www.w3.org/2000/svg','polygon');
var points = [];
var len = path.getTotalLength();
var step = step=len/samples;
for (var i=0;i<=len;i+=step){
var p = path.getPointAtLength(i);
points.push( p.x+','+p.y );
}
poly.setAttribute('points',points.join(' '));
return poly;
}
3ad) Why is function createElementNS unknown?
PS: I hope you understand my English :)

Related

Equivalent of canvas quadraticCurveTo in SVG

I am working on a plugin to allow "natural looking" signatures to be drawn using mouse or touch. When confirmed by the user, the result will be a stored SVG that can then be displayed in place of the "Click to sign" button.
The attached JSFiddle http://jsfiddle.net/TrueBlueAussie/67haj4nt/3/ shows a testbed for what I am trying to do. The SVG generated image should look close to the original canvas paths.
The first div contains a canvas, in which I draw some multiple-segment lines (e.g. paths). Using quadraticCurveTo, and a midpoint for the control point, I draw the lines with smooth curves. This works just fine.
The key part of the curved line drawing is:
$.each(lines, function () {
if (this.length > 0) {
var lastPoint = this[0];
ctx.moveTo(lastPoint[0], lastPoint[1]);
for (var i = 1; i < this.length; i++) {
var point = this[i];
var midPoint = [(lastPoint[0] + point[0]) / 2, (lastPoint[1] + point[1]) / 2];
ctx.quadraticCurveTo(lastPoint[0], lastPoint[1], midPoint[0], midPoint[1]);
lastPoint = point;
}
// Draw the last line straight
ctx.lineTo(lastPoint[0], lastPoint[1]);
}
});
I have tried multiple options for SVG generation of the same output, but I am stumped on how to convert the same sets of points to equivalent curved lines. Quadratic Beziers require "proper" control points, but I would prefer to use the far simpler mid-points if possible.
Any ideas? Is this possible or will I have to convert both to use Beziers with calculated control point(s). Is there a simple way to calculate control points that will do the same job?
jQuery or raw JavaScript solutions are fine, but you need to demonstrate in the JSFiddle provided :)
It's just a bug in your code. You are not updating lastPoint in your SVG version.
http://jsfiddle.net/67haj4nt/4/
And if you update the SVG version to match the canvas version, you get identical curves.
http://jsfiddle.net/67haj4nt/5/

Visualising a custom map with QGIS and D3.js is harmed by the projection

These are 4 polygons I have: http://imgur.com/vsVjxE1 in QGIS. I now wanted to use them with D3.js. I already tried out the things in QGIS generated shapefile malformed when converted to topojson by mapshaper. That was working well on the old json file. But when I was creating a new one, it was bugging in the vertical middle. That's the example http://jsfiddle.net/kwoxer/kpL1uyy2/5/:
var projection = d3.geo.projection(function(x, y) { return [x, y];})
.precision(0).scale(1).translate([0, 0]);
var path = d3.geo.path().projection(projection);
I also tried:
var path = d3.geo.path().projection(null);
but then the whole map was mirrored in the middle.
I think I don't use that system correctly I must assume. The json is fine on mapshaper, too. So do you have some tips, so that I just draw anything I want however big it is and then d3.js is able to draw it as it is. =)
Maybe by
normalizing lan/lng
disabling KBS
I really don't know why creating an own map is not straithforward.
Edit1: found nearly my issue here https://gis.stackexchange.com/questions/54373/either-geojson-to-topojson-conversion-problem-or-projection-issue-with-d3-js but I got:
C:\Program Files\GDAL>ogr2ogr.exe -f "GeoJSON" -s_srs region.prj -t_srs EPSG:432
6 asdas.json region.shp
ERROR 4: Failed to create GeoJSON datasource: asdas.json.
GeoJSON driver failed to create asdas.json
Edit2: already found this interesting answer: https://gis.stackexchange.com/questions/14731/how-do-i-specify-a-crs-for-a-fictional-game-map-in-qgis
But I used such a projection like he used, but still failing with d3.js.
I'm just using an own projection now:
+proj=eqc +a=1790493.11 +lat_ts=0 +lon_0=0 +rf=800 +units=m +no_defs
With that projection all is fine.

Why does D3.js not display my geoJSON file ?

I want to draw the outline of Berlin (germany) with D3.js.
The geoJSON file for Berlin i use is this (there Berlin-"bundesländer"):
http://opendatalab.de/projects/geojson-utilities/
But it just doesn't work with my .json file. I cant spot the difference to this .json file for us-states that works just fine with exactly the same code:
http://examples.oreilly.com/0636920026938/chapter_12/us-states.json
I also tried to completely copy the us-states file, delete all "features" entries except one and then only replace the coordinates-array of the one left with the coordinates-array of my file. But firebug tells me that the path's element has no "d" attribute at all.
I really appreciate any hint. Thank you in advance!
/*
I use the default albersUsa projection.
If I define path as : d3.geo.path().projection(null) some path-element is added.
But if that's the solution how can i translate that path ?
*/
var path = d3.geo.path();
d3.json("data/berlinBundeslaender_simplify2000.json",function(geoJson){
var color1 = d3.scale.category20();
mainSVG.selectAll("path")
.data(geoJson.features)
.enter()
.append("path")
.attr("d",path)
.attr("fill",function(d,i){return color1(i);});
});
The albersUSA projection will clip anything that's not within the lower 48 US states, Hawaii or Alaska. That is, anything else simply won't be displayed. Use a different projection for different parts of the world.

Draw Polygon with GPolygon without GMap

Anyone know how I can draw Polygons with GPolygon from Google Map without having a map, inside other elements? Or anyone know any framework to do it with the same features like GPolygon?
I would like to have this "draw polygon" on a custom element, like div:
<div id="MyArea"></div>
Check out Raphael, a javascript library that wraps around VML in IE and SVG in standards compliant browsers. It's fairly easy to use and quite well documented.
Granted, the path element (used to draw polygon and polylines) uses the SVG path string syntax which is a bit cryptic but quite easy to understand. You can of course extend Raphael to use a more simple syntax:
Raphael.fn.polygon = function () { // supply x,y coordinates as arguments
var self = this.path();
self.coords = [];
for (var i=0;i<arguments.length;i++) self.coords.push(arguments[i]);
self.update = function () {
var pathlist = [];
// the M command moves the cursor:
pathlist.push('M'+self.coords[0]+' '+self.coords[1]);
// the L command draws a line:
pathlist.push('L');
// Now push the remaining coordinates:
for (var i=2;i<self.coords.length;i++) {
pathlist.push(self.coords[i]);
}
// the Z command closes the path:
pathlist.push('Z');
self.attr('path',pathlist.join(' '));
}
self.update();
return self;
}
Which should allow you to do:
<div id="MyArea"></div>
<script>
var paper = Raphael("MyArea",640,480);
var mypolygon = paper.polygon(
10, 10,
20, 20,
10, 30
);
// you can even modify it after creation:
mypolygon.coords.push(15,20);
mypolygon.update();
</script>
Or create your own polygon API to taste if you don't like mine.
EDIT: fixed some small bugs.
I agree with slebetman that Raphael is totally great. Note, however, that neither SVG nor VML is currently supported in the Android browser. Canvas with excanvas.js may be a better bet for cross-browser work, if you are also targeting Android.
Also, if you really want to use the Google Map API, you can simply hide the map. But you would still be stuck with the Google logo due to the Terms of Use.
You can do this by using a tile with a single color in v2, but I believe there are other ways do this in v3.
Example of the v2 method: http://fisherwebdev.com/california
Example of hiding some of the map features in v3: http://fisherwebdev.com/mapcolors -- You can use this same technique to hide all features.
Play around with this to see what is possible to hide/show or restyle in v3: http://gmaps-samples-v3.googlecode.com/svn/trunk/styledmaps/wizard/index.html

How can I stop elements overlapping using JavaScript and the Raphael JavaScript library

I’m generating multiple, random sized, circular elements using the Raphael JavaScript library but because it’s random a lot of the circular elements being generate overlap or cover each other. What I wanted to know, is there any way with JavaScript to tell if one element is in already in particular position so to avoid the overlapping? Essentially, I want to create random elements on a canvas, of a random size that don’t overlap or cover each other.
There's a couple of test files I created here to give you an idea of what I'm doing. The first one generates random objects and the second link sets them to a grid to stop the overlapping.
http://files.nicklowman.co.uk/movies/raphael_test_01/
http://files.nicklowman.co.uk/movies/raphael_test_03/
The easiest way is to create an object and give it a repulsive force that degrades towards zero at it's edge. As you drop these objects onto the canvas the objects will push away from each other until they reach a point of equilibrium.
Your examples aren't working for me, so I cannot visualize your exact scenario.
Before you "drop" an element on the canvas, you could query the positions of your other elements and do some calculations to check if the new element will overlap.
A very simple example of this concept using circle elements might look like this:
function overlap(circ1, circ2) {
var attrs = ["cx", "cy", "r"];
var c1 = circ1.attr(attrs);
var c2 = circ2.attr(attrs);
var dist = Math.sqrt(Math.pow(c1.cx - c2.cx ,2) + Math.pow(c1.cy - c2.cy, 2));
return (dist < (c1.r + c2.r));
}
var next_drop = paper.circle(x, y, r);
for (var i in circles) {
if (overlap(next_drop, circles[i])) {
// do something
}
}
Of course calculating just where you're going to place a circle after you've determined it overlaps with others is a little more complicated.

Categories

Resources