javascript and svg contour plots - javascript

I want to make like this with javascript and svg ( they use pyhthon ):
I got the image from this site : 100-500hPa
From this site :"
MSLP and 1000-500 hPa Thickness with High and Low Symbols
Plot MSLP, calculate and plot 1000-500 hPa thickness, and plot H and L markers. Beyond just plotting a few variables, in the example we use functionality from the scipy module to find local maximum and minimimum values within the MSLP field in order to plot symbols at those locations.
"
Here, equal pressure values ​​are drawn and low and high pressure centers are determined. They are written in Python language. I want to do this using javascript and svg.
I tried some codes ; didn't work.

Related

d3js v5 + Topojson v3 Map with border rendering

I come back for a problem. I'm still learning d3js for 5 days and I have a problem about the border rendering.
Why I have that ?
The problem occurs when I add region borders.
svgMap.append("path")
.attr("class", "reg_contour")
.datum(topojson.mesh(fr[0], fr[0].objects.reg_GEN_WGS84_UTF8, function(a, b) { return a !== b; }))
.attr("d", path);
Here is my code : https://plnkr.co/edit/mD1PzxtedWGrZd5ave28?p=preview
Just for the record, the json file combines two layers (departments and regions) created with the same shp and compiled by QGIS for geojson output. After I convert this to topojson by mapshapper.
The error lies in your topojson - the two different feature types, departments and regions do not share the same coordinates along their common boundaries.
First, in this sort of situation it is desirable to check to make sure there is no layering issue (often other features are drawn ontop of others, hiding them or portions of them), we can do this by just showing the regional boundaries:
(plunkr)
So the problem can't be layering, if we look at a particular feature in the topojson, say the department of Creuse:
{"arcs":[[-29,-28,-27,-26,202,-297,-296,205,-295,-410,419]],"type":"Polygon","properties":{"codgeo":"23","pop":120581,"libgeo":"Creuse","libgeo_m":"CREUSE","codreg":"75","libreg":"Nouvelle Aquitaine"}}
We see that the department is drawn using 11 arcs representing each portion of the boundary based on shared boundaries between multiple features so that shared boundaries are only represented once in the data.
If we zoom in on Creuse we can see those 11 arc segments shared between either other departments, regions, or with nothing at all:
The thick portions of the boundary correspond to the thick white boundaries in the image in the question, I've only changed the styling and zoom from the original plunkr
This looks problematic, the department should only have 6 arcs:
Why are there additional arcs? Because the boundaries of the departments are not aligned properly - the shared boundaries between departments do not always share the same arcs in your topojson. Chances are the departments might use a different scale than the regions, a different precision or projection, or were made somehow differently. This has resulted in minute nearly imperceptible differences that have resulted in boundaries that share coordinates in reality not sharing the same coordinates in the data, and thus the shared arcs are going unrecognized.
Since you are generating the mesh like this:
topojson.mesh(fr[0], fr[0].objects.reg_GEN_WGS84_UTF8, function(a, b) { return a !== b; })
Only shared boundaries are drawn, which explains the gaps.
We can rectify this a few ways, the easiest way would be to remove the regions altogether. The departments record which region they are in, we can check to see if a boundary should be drawn if the departments on each side of that boundary are in different regions:
.datum(topojson.mesh(fr[0], fr[0].objects.dep_GEN_WGS84_UTF8, function(a, b) { return a.properties.libreg !== b.properties.libreg; }))
Which gives us:
(plunkr)
Alternatively, we can re-habilitate the regional boundaries by importing them into a GIS platform such as ArcGIS and repairing the geometry. We could also import the departments and make a new layer based on region properties in a dissolve. Using the repair geometry tool in Arc, I get a nice boundary (when shown with the same code as the first image here):
There are other methods, such as including a tolerance in aligning arcs, but these might be more difficult than the above.

Warp an SVG in JavaScript into an arc

I saw a d3 helper function which can create an svg arc: making an arc in d3.js
Is there a way to bend an existing svg into an arc in d3.js? If not, how can it be done in JavaScript? The initial image could be a square with negative space inside that makes a silhouette of something like a cat.
I included a drawing of what I want. I eventually want to make more and create a ring, and then concentric rings of smaller transformations.
I think conformal mapping is the way to go. As an example, I have started with the original square source and the circularly arranged (and appropriately warped) squares using conformal mapping. See the Circular Image and the Corresponding Square Image. Note, however, that I first converted the SVG source into a png image, and then applied conformal mapping transformation to each pixel in the png image. If anyone has a method of mapping entirely in the SVG domain [where the source uses only straight lines and bezier curves], pl. let us know!
I am not able to provide the code -- it is too complex and uses proprietary libraries). Here is a way to do it.
In order to compute the conformal mapping, I used a complex algebra library. JEP is one example. For each pixel in the OUTPUT image, you set Z = (x, y) where (x, y) are the coordinates of the pixel and Z is a complex variable with real part x and imaginary part y. Then you compute NEWZ = f(Z) where f is any function you want. for circle, I used an expression such as "(ln(Z*1)/pi)*6-9" where the log (ln) provides circularity, the 6 implies 6 bent squares in a circle and the -9 is a scaling factor to center and place the image. From the (X, Y) values of the NEWZ, you look up the old image to find the pixel to place in the new image. When the (X, Y) values are outside the size of the old image, I just use tiling of the old image to determine the pixel. When X and Y are fractional (non-integer) you average the neighbors in a weighted way.

Draw Polygons on a map using WebGL's drawArrays

I am trying to draw polygons on a map, using OSM data downloaded. I have written a query that returns a list of polygons from the planet_osm_polygon table. It resturns the list as JSON objects. I am using gl.drawArrays(gl.LINESTRIP, 0, json_data_length) to draw the polygons. I have done the same for points- I have a list of points returned and I have been able to plot them using gl.POINTS.
The problem is, I want each of the polygons to be drawn separately, but I guess using LINE_STRIP is connecting one ending point of one polygon to the starting point of another polygon.
For example, I want civic center plaza and buchanan street in SFO to be separate polygons. But the polygons, after being drawn, are still connected to each other through one point. I want these two to be drawn as separate polygons. How do I do it?
I do not want to use any libraries. Just basic WebGL. My JavaScript code takes the lat-long coordinates from my osm database and converts into pixel coordinates to help plotting- see link: WebGL shader code (http://psousa.net/demos/webgl/) I am using this example and extending it.
If i understood correctly you want to draw 'borders' of multiple polygons not the filled polygon itself.
In order to draw seperate lines in a single draw call you should use gl.LINES mode instead of gl.LINESTRIP.
Lets say you have a quad which has points A,B,C,D and a triangle which has points X Y Z. If you want to use glDrawArrays command with GL_LINES mode , your vertex data should be submitted as
{A,B, B,C, C,D, D,A, X,Y, Y,Z, Z,X}
Following lines are drawn with this vertex data
Line from A to B
Line from B to C
Line from C to D
Line from D to A
Line from X to Y
Line from Y to Z
Line from Z to X
In order to eliminate duplicate vertex data you can also use glDrawElements with a proper index .

D3: What does the scale do when passed an axis?

In d3, if you want to create an axis you might do something like this:
var xAxis = d3.svg.axis()
.scale(x)
where x is a scale function. I understand that the domain of x defines the start and ending values for the ticks. I'm having trouble understanding how the range of x changes the resulting axis. What does the domain map to in the context of an axis.
Think about what one must do to create a visual representation of any data set. You must convert each data point (e.g. 1 million dollars) into a point on the screen. If your data has a minimum value of $0 and maximum value of $1000000, you have a domain of 0 to 1000000. Now to represent your data on a computer screen you must convert each data point (e.g. $25) into a number of pixels. You could try a simple 1 to 1 linear conversion ($25 converts to 25 pixels on the screen), in which case your range would be the same as your domain = 0 to 1000000. But this would require a bloody big screen. More likely we have an idea of how large we want the graphic to appear on the screen, so we set our range accordingly (e.g. 0 to 600).
The d3 scale function converts each data point in your dataset into a corresponding value within your range. That enables it to be presented on the screen. The previous example is a simple conversion so the d3.scale() function is not doing much for you, but spend some time converting data points into a visual representation and you will quickly discover some situations where the scale function is doing a lot of work for you.
In the particular case of an axis, the scale function is doing exactly the same thing. It is doing the conversion (to pixels) for each 'tick' and placing them on the screen.

How to subdivide a shape into sections of a given size

I'm currently trying to build a kind of pie chart / voronoi diagram hybrid (in canvas/javascript) .I don't know if it's even possible. I'm very new to this, and I haven't tried any approaches yet.
Assume I have a circle, and a set of numbers 2, 3, 5, 7, 11.
I want to subdivide the circle into sections equivalent to the numbers (much like a pie chart) but forming a lattice / honeycomb like shape.
Is this even possible? Is it ridiculously difficult, especially for someone who's only done some basic pie chart rendering?
This is my view on this after a quick look.
A general solution, assuming there are to be n polygons with k vertices/edges, will depend on the solution to n equations, where each equation has no more than 2nk, (but exactly 2k non-zero) variables. The variables in each polygon's equation are the same x_1, x_2, x_3... x_nk and y_1, y_2, y_3... y_nk variables. Exactly four of x_1, x_2, x_3... x_nk have non-zero coefficients and exactly four of y_1, y_2, y_3... y_nk have non-zero coefficients for each polygon's equation. x_i and y_i are bounded differently depending on the parent shape.. For the sake of simplicity, we'll assume the shape is a circle. The boundary condition is: (x_i)^2 + (y_i)^2 <= r^2
Note: I say no more than 2nk, because I am unsure of the lowerbound, but know that it can not be more than 2nk. This is a result of polygons, as a requirement, sharing vertices.
The equations are the collection of definite, but variable-bounded, integrals representing the area of each polygon, with the area equal for the ith polygon:
A_i = pi*r^2/S_i
where r is the radius of the parent circle and S_i is the number assigned to the polygon, as in your diagram.
The four separate pairs of (x_j,y_j), both with non-zero coefficients in a polygon's equation will yield the vertices for the polygon.
This may prove to be considerably difficult.
Is the boundary fixed from the beginning, or can you deform it a bit?
If I had to solve this, I would sort the areas from large to small. Then, starting with the largest area, I would first generate a random convex polygon (vertices along a circle) with the required size. The next area would share an edge with the first area, but would be otherwise also random and convex. Each polygon after that would choose an existing edge from already-present polygons, and would also share any 'convex' edges that start from there (where 'convex edge' is one that, if used for the new polygon, would result in the new polygon still being convex).
By evaluating different prospective polygon positions for 'total boundary approaches desired boundary', you can probably generate a cheap approximation to your initial goal. This is quite similar to what word-clouds do: place things incrementally from largest to smallest while trying to fill in a more-or-less enclosed space.
Given a set of voronio centres (i.e. a list of the coordinates of the centre for each one), we can calculate the area closest to each centre:
area[i] = areaClosestTo(i,positions)
Assume these are a bit wrong, because we haven't got the centres in the right place. So we can calculate the error in our current set by comparing the areas to the ideal areas:
var areaIndexSq = 0;
var desiredAreasMagSq = 0;
for(var i = 0; i < areas.length; ++i) {
var contrib = (areas[i] - desiredAreas[i]);
areaIndexSq += contrib*contrib;
desiredAreasMagSq += desiredAreas[i]*desiredAreas[i];
}
var areaIndex = Math.sqrt(areaIndexSq/desiredAreasMagSq);
This is the vector norm of the difference vector between the areas and the desiredAreas. Think of it like a measure of how good a least squares fit line is.
We also want some kind of honeycomb pattern, so we can call that honeycombness(positions), and get an overall measure of the quality of the thing (this is just a starter, the weighting or form of this can be whatever floats your boat):
var overallMeasure = areaIndex + honeycombnessIndex;
Then we have a mechanism to know how bad a guess is, and we can combine this with a mechanism for modifying the positions; the simplest is just to add a random amount to the x and y coords of each centre. Alternatively you can try moving each point towards neighbour areas which have an area too high, and away from those with an area too low.
This is not a straight solve, but it requires minimal maths apart from calculating the area closest to each point, and it's approachable. The difficult part may be recognising local minima and dealing with them.
Incidentally, it should be fairly easy to get the start points for the process; the centroids of the pie slices shouldn't be too far from the truth.
A definite plus is that you could use the intermediate calculations to animate a transition from pie to voronoi.

Categories