I've generated a plain svg file using Inkscape containing three paths. Consider one of the paths inside the .svg file given below
<path xmlns="http://www.w3.org/2000/svg"
d="m 128.57143,243.79075
-2.85714,568.57143
474.28571,0
-31.42857,-611.42857 z" id="path2985"
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"/>
I want to parse this svg file to extract the XY coordinates of this closed path (it is closed because of the 'z' at the end of the coordinates list).
I am unsure how to interpret the 8 numbers. From what I understand, the first two numbers indicated by m 128.57143,243.79075 means that the path's origin is in screen-coordinates (not Cartesian!) at 128.57143 right and 243.79075 down from the top-left of the screen.
What about the rest of the 6 numbers? Do they indicate vectors in which to move relative to the previous point? Or just absolute screen coordinates?
As indicated in the SVG documentation here, SVG files usually have those M,L,H,...letters prefixed to each successive number pair which tells the vector-graphics viewer how to interpret that number pair while drawing that path.
In this case however, other than the m prefixed at the beginnnig and the z at the end there are no such letters in between. What then is the default behaviour in this case?
A capital letter M would suggest absolute coördinates. And a small m means relative coördinates. Since positioning is 0,0 by default, the first value of m would be identical to M.
Only the first coördinates are treated as 'm' (=moveto). The next ones are treated as 'l' (=lineto). Since 'm' was not capitalised the next coördinate will be treated as relative.
It would be the same as:
<path xmlns="http://www.w3.org/2000/svg"
d="m 128.57143,243.79075
l-2.85714,568.57143
474.28571,0
-31.42857,-611.42857 z" id="path2985"
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"/>
For the sake of reference: this is what the spec sais about the moveto command. (source: https://www.w3.org/TR/SVG/paths.html#PathDataMovetoCommands)
Start a new sub-path at the given (x,y) coordinate. M (uppercase)
indicates that absolute coordinates will follow; m (lowercase)
indicates that relative coordinates will follow. If a moveto is
followed by multiple pairs of coordinates, the subsequent pairs are
treated as implicit lineto commands. Hence, implicit lineto commands
will be relative if the moveto is relative, and absolute if the moveto
is absolute. If a relative moveto (m) appears as the first element of
the path, then it is treated as a pair of absolute coordinates. In
this case, subsequent pairs of coordinates are treated as relative
even though the initial moveto is interpreted as an absolute moveto.
Related
I have an image and I'm trying to store the pixel colors for a set of points along a line into an array.
The endpoints of the line and the distance between points is given. I know that the command line(x1,y1,x2,y2) draws a line between (x1,y1) and (x2,y2). I also know that .get() applied to an image returns the pixel color at the specified location.
I am unsure how to put it all together.
Essentially the problem is in two parts:
working out which pixel of the image you are over at each point along the line
Reading out that pixel value and storing it in an array
The second is fairly simple: https://processing.org/reference/PImage_get_.html will give you all the info you need about getting the pixel values at a certain coordinate.
The first is a maths problem essentially.
The line you draw will have the equation: Y = m * X + C where C is the intercept of the X axis and M is its gradient.
(One thing to remember is that the origin (0,0) for a processing sketch is at the top left)
https://www.mathsisfun.com/algebra/line-equation-2points.html is a good resource for this. The basic methodology is to calculate the gradient M and then set Y to 0 and equate m * X = -C
I want to create dots/ points in my java-fx application. But there are some conditions:
1)The dots should be random
2)The dots have to be bounded inside a circle ie all the dots must be inside a circle of given dimension
3)The concentration of dots must be far greater near the outer portion ie towards the boundary than anywhere else.
How do i do this ?
I want to align image X against image Y. Each image contains circles and Hough transform is used to detect them.
Lets assume Hough transform detects different number of circles in image X and image Y.
I want to find transformation of image X (rotation, translation) such that most circles in image X match some circle in image Y. Can you tell me how would you proceed?
An approach:
Get some properties from the circles of images X and Y, such as radius or others (color?).
Find putative matches between the circles of X with those of Y. It is to say, two circles with a similar radius are a putative match. You may obtain several matches, correct and incorrect ones.
Use a RANSAC-like algorithm to find the transformation:
Select two random pairs of matching circles and compute the translation and rotation that these define.
Check how many putative matches are ok if you assume the previous transformation (translation + rotation) was ok.
Repeat.
Keep the transformation that maximizes the number of matching circles.
I want to find all grid tiles that touch or contain parts of a given finite line segment. The grid is a 2d regular grid, thus I can deduce any tile's center from a tile position (row,colum) and vice versa I can calculate a tile position from a given floating point coordinate with two fast integer divisions. The tiles are quadratic e.g. 0.25x0.25 with 0.25 defined as the tile width.
Now I need to determine all tiles that are touched by a given line segment
(two 2d points given in floats define a line segment).
My current approach is to split the segment into equidistant points with a distance half the tile-width (greetings to shannon). Than I collect all tiles that contain the given points and remove duplicate tiles.
Since this operation is the most performance critical part of my program I was wondering whether there is a faster approach to calculate the respective tiles.
Edit: As Patricia noted my current approach does not result in a complete tile set since a tile that is only touched to a very small fraction by the line would not be included. This is acceptable for me since in my case speed is more important than accuracy, but should be noted none the less.
To make it clearer: I want all red tiles in the image but I can spare e.g. the rose ones if I gain speed for that.
Your problem basically comes down to drawing a line segment on a raster image.
If you can spare the pink tiles, use the Bresenham's algorithm. Otherwise, use a similar technique as is used to draw antialiased lines:
You start at the tile which contains one end of the segment and put it to the queue. Then follow with a regular BFS algorithm, putting only tiles which intersect with the segment to the queue:
In one iteration take one tile from one end of the queue, this is your next found intersecting tile. Then find all its neighbors, and put those which intersect with the segment (it's enough to test intersection with a line in this case) to the other end of the queue. The neighbors must be chosen according to the direction of the line. If it goes down-right, use the down, right and down-right tiles as neighbors, if it goes up, use only up neighbors, and so on.
You end when you reach the tile which contains the other end of the segment.
Test the gradient of the line, against the tile diagonal with the same gradient sign. If it is steeper than a tile diagonal, exchange x and y coordinates in what follows.
If the gradient is shallower than the tile diagonal, the line touches or crosses a given tile, and the tile does not contain an end point, at least one of its intersections with the edges of the tile must be on an x boundary of the tile.
For each line end, collect the tile containing or tiles touching the end point.
For each x coordinate that is a tile edge between the two end point x coordinates, calculate the line's y coordinate. Collect the tiles touching that point.
I think this can all be done with at most a couple of divisions to do the gradient check. The main process is all multiplication, addition, and comparisons.
Given the line segment's end points, you can easily compute the equation of the line, y = mx + b. And given the length of the segment, you can compute the parametric form:
x = x0 + ft
y = y0 + gt
Given either of those equations, you can calculate the y coordinate for any given x coordinate on the line. So ...
Starting at the first end point of the line, you know that the cell containing that point is in the set. You know the x coordinates for each cell, so you can quickly determine the y coordinate at which your line segment crosses the cell boundary. If that y coordinate is above the cell's top y coordinate, then the line segment intersects the cell above the starting cell. (Substitute "below" if the line's slope is "down.)
If you repeat that test for each cell boundary along the x axis, you will get the list of all cells that the segment crosses.
For a right triangle specified by an equation aX + bY <= c on integers
I want to plot each pixel(*) in the triangle once and only once, in a pseudo-random order, and without storing a list of previously hit points.
I know how to do this with a line segment between 0 and x
pick a random point'o' along the line,
pick 'p' that is relatively prime to x
repeat for up to x times: Onext = (Ocur + P) MOD x
To do this for a triangle, I would
1. Need to count the number of pixels in the triangle sans lists
2. Map an integer 0..points into a x,y pair that is a valid pixel inside the triangle
I hope any solution could be generalized to pyramids and higher dimensional shapes.
(*) I use the CG term pixel for the pair of integer points X,Y such that the equation is satisfied.
Since you want to guarantee visiting each pixel once and only once, it's probably better to think in terms of pixels rather than the real triangles.
You can slice the triangles horizontally and get bunch of horizontal scan lines. Connect the scan lines together and you have converted your "triangle" into a long line. Apply your point visiting algorithm to your long chain of scan lines.
By the way, this mapping only needs to happen on paper, all you need is a function that can return (x, y) given (t) along the virtual scan line.
Edit:
To convert two points to a line segment, you can look for Bresenham's scan conversion. Once you get the 3 line segments converted into series of points, you can put all points into a bucket and group all points by y. Within the same y-value, sort points by x. The smallest x within a y-value is the begin point of the scan line and the largest x within the y-value is the end point of the scan line. This is called "scan converting triangle". You can find more info if you Google.
Here's a solution for Triangle Point Picking.
What you have to do is choose two vectors (sides) of your triangle, multiply each with a random number in [0,1] and add them up. This will provide a uniform distribution in the quadrilateral defined by the vectors. You'll have to check whether the result lies inside the original triangle; if it doesn't either transform it back in or simply discard it and try again.
One method is to put all of the pixels into an array and then shuffle the array (this is O(n)), then visit the pixels in the order in the shuffled array. This could require quite a lot of memory though.
Here's a method which wastes some CPU time but probably doesn't waste as much as a more complicated method would do.
Compute a rectangle that circumscribes the triangle. It will be easy to "linearize" that rectangle, each scan line followed by the next. Use the algorithm that you already know in order to traverse the pixels of the rectangle. When you hit each pixel, check if the pixel is in the triangle, and if not then skip it.
I would consider the lines of the triangle as single line, which is cut into segments. The segments would be stored in an array where the length of the segment also stored as well as the offset in the total length of the lines. Then depending on the value of O, you can select which array element contains the pixel you want to draw at that moment based on this information and paint the pixel based on the values in the element.