Scenario:
I am currently working with d3.js Hive Plots, and for an experimental scenario, I need control of the visual directionality of the links.
Problem Source:
I am using d3.hive.v0.js "add-on", and due to the fact that Hive Plots charts do not inherently carry any visual directionality information on the links, the add-on does not adhere to source and target nodes with regards to directionality of the drawn path, and always draws the paths clockwise, and hence always pointing in the direction of the node to the left when snapping on a marker-end.
Problem Effect
Pointers are unreliable because the path "end" that the marker adheres to, is not nescessarily at the target, but may be at the source, depending on the source and targets relative position to each other.
What it boils down to
I know that I could draw my own links with my own Arcs and gain more control, instead of using the d3 Hive Plot library links, and I have tried it, but it's not easy to get nice, and the Hive Plot algorithm is pretty and I would like to use it.
Let's say I intercept d, when it comes back from the Hive Plot link path algo.
I find d = "M 8.327598234202001e-15,-136 C 101.06769626492562,-91.00176246480473 135.0052608777338,14.189624701397365 79.7912059004442,109.82317321396422";
That gives me a nice path, starting in the top, and drawing down (CW) as demostrated in
http://jsfiddle.net/hwehqhtm/1/
svg.selectAll(".test")
.data(d3.range(1))
.enter().append("path")
.attr("class", "link")
.style("stroke", "green")
.attr("stroke-width", 3)
.attr("marker-end", "url(#arrow)")
.attr("d", d)
My question is, now that I have d, is it possible to "reverse the draw direction" of the line by doing something on d ? , - making "path end" be the top end of the line, and make the marker-end go here, effectivly making the link point the other direction.
The line should be visually identical, only logically "beginning" in the other end.
The parent fiddle http://jsfiddle.net/hwehqhtm uses two different markers for start and end, but then I would have to include new logic in some marker-end and marker-start callbacks to switch them on off, and I would really prefer to just mathemagically make it draw "the other way" by "reversing d" if possible. I'm not good enough at trig to know if this even makes sense. Any comments and solutions on path directionality and markers are very welcome !
Thx
Seems that it can be done by switching around the parameters. The d above, created by the hive plot algorithm turns out to be a moveto and a curveto (bezier) in the format M x y C x1 y1 x2 y2 x y.
To reverse the curve, switching endpoint x,y in C with startpoint x,y in M and then switching the bezier control points x1,y1 with x2,y2 seems to do it.
Related
I'm working on a project where I need to parse svg path data.
Right now we're loading an svg, looking for the path tag, and pulling out it's d attribute.
For some of the artwork we'll get path data that is made up of coordinates which we can translate into the data types we need. E.g.
But other times the d value is in a more g-code-esq format.
Like in this case I drew a rectangle, converted it to a compound path:
And when I export it and look at the svg I get a d value like this:
Which we can't easily parse for the project.
My questions are:
How do I read this second format? It doesn't seem to fit what I'm reading on MDN so I suspect there's some other documentation I need to refer to: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/d
For illustrator users, is there a way of changing the format when exporting?
I know that this seems like more of an art question than a programming question, but I'm trying to understand the underlying reasoning behind the svg data structure so I can better parse it.
Oh! Oh ok, I was 100% misunderstanding the path data that I was reading. I didn't realize that the delimiting information was based on the letter. My brain wanted some specific character as a delimiter like a comma or pipe.
So reading (and in some cases re-reading :| ) the documentation, when I see:
M753,315H435.27V165H753Z
I can read that as:
M753,315 Move to x,y coordinates x: 753 y:315
H435.27 Starting at the current location, draw a horizontal line to the absolute x coordinate of 435.27
V165 Starting at the current location, draw a vertical line to the absolute y coordinate of 165
H753 Starting at the current location, draw a horizontal line to the absolute x coordinate of 753
ZDraw a straight line to the initial point of this path to close the path. This doesn't necessarily mean a horizontal or vertical line, but the coincidence that we're at the same x coordinate that we started at means that if we draw a straight line we will get a vertical line to complete the rectangle
That seems right. Anything I missed or misunderstood?
Also, thank for all of the links. I appreciate the points :clap: :bows:
I'm using pixi.js to create some editable polygons. So, what I want to achieve is this:
I have one polygon
Then, when I hit the edge a small circle should appear
And next I can drag and drop that part of the edge to creating a new point for the polygon
For now, what I know is the polygon vertices and I'm thinking to use the line function (y=mx+b) to check if the point where the mouse is belongs to the edge. My problem here, is that I have no idea how to obtain that edges. Any Suggestion? Of course, if you have any other idea to do this feel free to share =).
For now, what I know is the polygon vertices
You probably draw your polygon using https://pixijs.download/dev/docs/PIXI.Graphics.html#drawPolygon method by passing to it a list of points - similar as last shape in this example: https://pixijs.io/examples/#/graphics/simple.js
// draw polygon
const path = [600, 370, 700, 460, 780, 420, 730, 570, 590, 520];
graphics.lineStyle(0);
graphics.beginFill(0x3500FA, 1);
graphics.drawPolygon(path);
graphics.endFill();
^ In that example we have 5 points: P (600, 370), Q (700, 460), R (780, 420), S (730, 570), T (590, 520).
It also means that we have 5 edges: PQ, QR, RS, ST, TP
Now, we should have some way to tell if mouse pointer "is hovered over some some edge". By "is hovered" i mean: it lies in some distance from edge - lets say said distance is 10 pixels. So we want to know if mouse pointer is 10 pixels away from some edge.
To know that we can use formula explained in Line defined by two points part in: https://en.wikipedia.org/wiki/Distance_from_a_point_to_a_line#Line_defined_by_two_points
P1=(x1,y1) and P2=(x2,y2) - are the beginning and end vertices of some edge (for example PQ)
(x0,y0) is our "mouse point"
You can iterate over all edges and perform above calculation - if the distance is less that 10 pixel for some edge then you have the answer. If there is more than one edge which meets this requirement then you should pick one with smallest distance (it can happen if for example mouse is placed near some vertice).
Now you have the selected edge. Now lets do following point from your question:
2. Then, when I hit the edge a small circle should appear
To calculate position of this circle we can use equation from same Wikipedia page: https://en.wikipedia.org/wiki/Distance_from_a_point_to_a_line#Line_defined_by_an_equation - the part The point on this line which is closest to (x0,y0) has coordinates:.
Here you need to convert coordinates of vertices from your selected edge to line function.
Then we can proceed to last point from your question:
3. And next I can drag and drop that part of the edge to creating a new point for the polygon
You can do it by adding new vertice to your polygon.
Lets assume that selected edge is PQ - then this new vertice should be added between vertices P and Q in the vertices list which you pass to drawPolygon method. Lets name this new vertice X. Coordinates of vertice X should be equal to current mouse coordinates.
Then you will have following edges: PX, XQ, QR, RS, ST, TP.
You probably want to activate this "mode" after mouse is clicked and when mouse button is down etc - but that is separate issue related to interactivity / GUI etc - not graphics :) .
Note: is good to separate your presentation part of application (graphics / pixi.js related things) from mechanics and interactivity / GUI etc. So for example: do your calculations in separate place (other class, method etc) from where you do your actual drawing (calling pixi.js methods, update canvas etc). Store results of calculations in some place (from above example it would be: list of vertices, position of circle, colors etc), and then when time comes to draw you take those results and just draw polygons using them. Dont mix everything in one place ;)
Following Quote from this source:
http://www.cambridgeincolour.com/tutorials/image-projections.htm
Equirectangular image projections map the latitude and longitude
coordinates of a spherical globe directly onto horizontal and vertical
coordinates of a grid, where this grid is roughly twice as wide as it
is tall.
I have a 13312 px width and 6656 pixel height Panorama picture. It's a equirectangular projection of a room and have a 2:1 ratio.
I use following formular to calculate the xPosition:
var xPosition = ( panorama.width / 360 ) * azimuth
Azimuth = Phi = Heading = Angle to the left or right
How do I project this now on a 1366x768px browser screen?
I think my results are wrong, because it's not on the point where it should be.. it could be because the sphere has a distortion on the left and right:
Is there any formular to calculate the position with attention to the distortion and scale it to fit on the browser screen? I looked many (MANY) sources to find a solution for this, but they always just say that equirectangular are just lat and long.. they don't consider the distortion.
Last question: To find a special solution, I tryed to put a plane on the circle and expanded the line which shows the alpha angle. I though with Phytagoras I could find the position.. but this didn't worked either.. maybe I did something wrong? Is this the way even possible or am I doing it wrong?
edit
THIS is what I'm actually looking for: http://othree.github.io/360-panorama/three-2d/
The black grid in the background. What is the name of this? For what do I have to google or look for? When you start the 2D Panorama, if you want to get the coordinations of the top right corner of the window, what do you have to do?
The whole calculation problem was about to create a Google Streetview similiar view from a 2:1 equirectangular image. We already found a solution for this with a great help from Martin Matysiak (https://github.com/marmat | Google).
It's been a while so I can't give a direct answer to what the main solution is, but I can provide a URL to an AddOn Martin wrote for adding the custom Markers that we actually were trying to make.
You can follow https://github.com/marmat/google-maps-api-addons and look for yourself. In the end it helped a lot to solve the main problem and let us continue with our main Framework for Google Business Tours.
If you follow the link in the threejs demo you included, it would take you to the source code.
particularly look at:
https://github.com/mrdoob/three.js/blob/dev/examples/webgl_panorama_equirectangular.html
and
https://github.com/mrdoob/three.js/blob/dev/src/geometries/SphereBufferGeometry.js
not sure if there is distortion though. The distortion comes from the fact that the texture is mapped to the sphere, and the sphere is rendered in 3D (openGL).
JavaFX does not provide a CENTER value for Side so I am trying to center the X and Y Axis by translation:
scanXAxis.setTranslateY(0.5*scanYAxis.getBoundsInParent().getHeight()); // xAxis initially on TOP
scanYAxis.setTranslateX(0.5*scanXAxis.getBoundsInParent().getWidth()); // yAxis initially on LEFT
The result I am getting however are axes crossing at a point that depends on the scene's size instead of (0,0) i.e I can get them crossed at the origin by manually resizing the scene. This is exaclty the reverse of what I am striving for.
Any help would be greatly appreciated!
Cheers
I am using the Axis and I think the design is not friendly. I can't set the axis upside down or right to the left. I used axis.rotate but I have to hack the code for the layout of the contentPlot. Also, the axis can only be set to the left, right, top or bottom. But I want some flexibility, e.g. when I implement parallel coordinates, I can't put it to the place I really want to put it. So I am thinking I have to write my own axis class instead.
I draw SVG path like this:
Start:
M x, y
Add Curve
Q x1, y1, x, y
etc etc.... and when I want to close path I just add Z
But that last line segment now doesn't have any control points.
How can I close path and also have control points on that last segment?
Something like : Z Q x1, y1 where Z closes path (current point to first point) but it uses x1 and y1 as control points, not just straight line.
I understand your desire. Every time I draw a freehand blob in Illustrator I always set the final point on the original point and then drag to create a tangent for the control points on either side.
SVG has no such feature like this. There is no path command that does this. The closest are the shorthand path commands S and T, but these derive the first control point from the last control point on the previous command, whereas what you want is something that derives the second control point from the first control point on the next command (wrap-around style).
You could do this with JavaScript, e.g. markup like
<path d="… Z" class="smooth-close" />
…and a small script that finds all the smooth-close paths, determines the appropriate control point from the first commands and generates a S or T command and appends it to the path data. But since you did not tag your question with javascript I assume such a solution would not interest you.