Splitting SVG Paths Programmatically - svg

I have an SVG image consisting exclusively of straight line segments connected by nodes. I wish to apply a transform on the coordinates of those nodes of the form (x,y) --> (x',y') such that x' = f(x,y), y' = g(x,y) but only in a certain region of the xy plane.
My question is this: if there is a node inside this region connected with a straight line segment to a node outside this region how do I split this line segment at the boundary of the region so that two nodes are created, as close as possible to each other on either side of the boundary, leaving behind a tiny gap in the original line segment at the boundary. The idea is to create two line segments from the original single line segment, with four nodes in total instead of two, and then apply the transform to the two nodes of the line segment inside the region and not to the two nodes of the line segment outside the region.
Note: The mathematics behind this are not the issue, the issue is programming it. This splitting business will of necessity require the creation of additional paths, which I don't quite know how to program. Any programming language would be fine, so long as it got the job done. If it is of any help, I am using Inkscape for editing the SVG. Thanks.

Related

How can I use 2D infinite lines as keys of an associative container that can be queried by proximity?

I have a thousands of line segments that I'd like to cluster by colinearity. One way to do this is to make an associative container with keys that are infinite lines. With such a container I could use a collection of line segments as values and add a line segment by determining the infinite line of which it is a segment and inserting into the corresponding bin.
Given such a set up, what is the best way to characterize the infinite lines for supporting the ability to query the data structure for line keys that are near a given line?
For example I was thinking of using an R-tree of points (Elsewhere in this project I am already using Boost.Geometry R-trees) where each point is the x-intercept and y-intercept of an infinite line. However, this only works for non-vertical and non-horizontal lines. I could handle vertical and horizontal lines as special cases but then I would not be able to easily query for lines that are "near" a vertical or horizontal line the way that I will be able to query for lines that are near a non-axis aligned line by doing a 2D range query of the intercept points in the R-tree.
I'm wondering if there is some elegant way of handling this problem. How can I represent infinite 2D lines as points such that horizontal and vertical lines are no different than any other kind of line and such that lines that are near each other map to points that are near each other?
I have two solutions.
The first is a simple one with some limitations:
For each infinite line, you could compute the point on the line where the perpendicular drawn from the origin meets the line. You could store the coordinates of this point as a "signature" of that line. This solution will work for all lines except those that pass through the origin. That is because when the line passes through the origin, the "signature" point will always be the origin no matter the slope of the line.
The second solution extends the first one to solve that problem:
In addition to the coordinates of the point described above, you can also store the angle the normal of the line makes with the x-axis. So you'd be representing each line with an ordered triplet (x, y, theta). You can store these triplets in an rtree for 3d points and query that tree.
Two lines that pass through the origin could have a theta value of pi/4 radians and 5*pi/4 respectively. They'd be coincident, but the way they are stored in the rtree doesn't reflect that. So just for the lines that pass through the origin, you could enforce a convention, say - theta must be between 0 and pi. Such a convention would fix the problem. This convention should only be enforced for lines that pass through the origin.
Update:
Coming up with a solution that is better optimized for your use-case will require a clear definition of how you measure the "proximity" between two infinite lines.

Create offset line contours from a line set with arbitrary topology

Example image:
Given a set of connected lines (see thick black lines in example image), how can you generate a set of offset contour lines that form loops (see thin blue lines)? The offset is constant across all lines, and the contours are always parallel to its associated lines.
The input line topology is arbitrary: i.e. it may contain cycles. Note that the number of contour loops is equal to the number of cycles plus one. A solution that just deals with tree topologies only (no cycles) could also be of interest.
Any papers or relevant algorithms out there that tackle this problem?
The basic method is to construct the bissectrix of the angles (on the right side) and draw on it a length such that it achieves the desired offset (a little of trigonometry). And to link them in the loop traversal order. Different capping rules can be used at free endpoints.
For this to be possible, you need a representation of the geometry as a planar graph (quad-edge for instance). Maybe have a look here: https://mathoverflow.net/q/23811.
Anyway, this method will not avoid the overlaps that can arise, nor self-intersecting offsets. These are much more difficult problems that require a global approach, and are similar to the polygon union problem.

SVG Path and morphing

I have a bit of a theoretical questions.
Lets say i have 2 paths in svg. Each with a different number of points. One has 4 Bézier curves and the other 3.
What i want to do is morph one into the other.
Now, i know they have to have the same exact structure and same number of points to do so.
So, the question is, can i add "virtual points" into their paths to get the same structure and number of points, without changing the shape of the objects?
For example, taking one point in one of the paths and just adding the same point after it to increase the number of points. Or creating a Bézier curve in both paths that would actually pretend to be a line instead of a curve. Would that change the object? And if i have points on x=1 y=1 and x=4 y=4, would using this form make Bézier curve a line? (M1 1C1 1 4 4 4 4)
Figured it out. Using control points anywhere on the same line as the coordiantes transforms the Bézier into a line, also if you use the same point as both the control points, start and end coordinate you can make the curve into a point. Adding more of these points into path doesnt change the look of the object, just adds more data into the path.
http://www.petercollingridge.co.uk/book/export/html/560
Down at the cubic curves you can align the points in the described manner to get the desired result
I have a simple to use d3 plugin to animate svg path which supports different number of points, also it animates only the parts of the path which differs from original path, not the whole path.
7kb minified: https://pratyushcrd.github.io/d3-path-morphing/

How to test if a line intersects a convex polygon?

Assume you are given the equation of a line (in 2d), and the equations of lines that form a convex polygon (the polygon could be unbounded). How do I determine if the line intersects the polygon?
Furthermore, are there computational geometry libraries where such tasks are pre-defined? I ask because I'm interested not just in the 2D version but n-dimensional geometry.
For the 2D case, I think the problem simplifies a bit.
The line partitions the space into two regions.
If the polygon is present in only one of those regions, then the line does not intersect it.
If the polygon is present in both regions, then the line does intersect it.
So:
Take any perpendicular to the line, making the intersection with the
line the origin.
Project each vertex of the polytope onto the perpendicular.
If those projections occur with both signs, then the polygon
intersects the line.
[Update following elexhobby's comment.]
Forgot to include the handling of the unbounded case.
I meant to add that one could create a "virtual vertex" to represent the open area. What we really need is the "direction" of the open area. We can take this as the mean of the vectors for the bounding edges of the open area.
We then treat the dot product of that direction with the normal and add that to the set of vertex projections.
In geometry, typically see wikipedia a polygon is bounded.
What you are describing is usually called a polytope or a polyhedron see wikipedia
There are a few geometry libraries available, two that come to mind are boost (polygon) and CGAL. Generally, there is a distinct split between computational methods that deal with 2d,3d, and N-d - for obvious reasons.
For your problem, I would use a somewhat Binary Space Partitioning Tree approach. I would take the first line of your "poly" and trim the query line against it, creating a ray. The ray would start at the intersection of the two lines, and proceed in direction of the interior of the half-space generated by the first line of the "poly". Now I would repeat the procedure with the ray and the second line of the "poly". (this could generate a segment instead of ray) If at some point the ray (or now segment) origin lies on the outer side of a poly line currently considered and does not intersect it, then the answer is no - the line does not intersect your "poly". Otherwise it intersects. Take special care with various parallel edge cases. Fairly straight forward and works for multi-dimensional cases.
I am not fully sure, but I guess you can address this by use of duality. First normalize your line equations as a.x+b.y=1, and consider the set of points (a,b).
These must form a convex polygon, and my guess is that the new line may not correspond to a point inside the polygon. This is readily checked by verifying that the new point is on the same side of all the edges. (If you don't know the order of the lines, first construct the convex hull.)
Let's start from finite polygons.
To intersect polygon a line must intersect one of its edges. Intersection between line and an edge is possible only if two points lie on different sides from the line.
That can be easily checked with sign(cross_product(Ep-Lp,Ld)) for two points of the edge. Ep - edge point, Lp - some point on the line, Ld - direction vector of the line, cross_product(A,B)=Ax*By-Ay*Bx.
To deal with infinite polygons we may introduce "infinite points". If we have a half infinite edge with point E1 and direction Ed, its "second point" is something like E1+infinity*Ed, where infinity is "big enough number".
For "infinite points" the check will be slightly different:
cross_product(Ep-Lp,Ld)=
=cross_product(E1+infinity*Ed-Lp,Ld)=
=cross_product(E1-Lp+infinity*Ed,Ld)=
=cross_product(E1-Lp,Ld)+cross_product(infinity*Ed,Ld)=
=cross_product(E1-Lp,Ld)+infinity*cross_product(Ed,Ld)
If cross_product(Ed,Ld) is zero (the line is parallel to the edge), the sign will be determined by the first component. Otherwise the second component will dominate and determine the sign.

Projecting a line segment onto a polygon mesh

I am working on a 3d application and am currently looking for a way to project a line segment defined by two points in screen-space onto a three-dimensional polygonal mesh (in my case a triangle mesh). The goal is to find the intersection points in world-space of the line segment with the edges of the mesh.
I can only think of two ways to do this, but neither is ideal. The first is to sample the line segment (in screen-space) at small intervals and ray trace at those intervals to find the world-space coordinates where the ray hits the mesh, but this does not easily give me the intersection points of the line segment with the mesh edges.
The other way I can think of is to somehow back-project the mesh into screen-space, find the intersections there (in 2d) and then project those intersection points back to 3d. The problem with this is that the screen-space coordinate system may change between the selection of the first and second endpoints of the line segment (due to moving the camera).
If any of that was confusing, then here is an image that approximately shows what I'm trying to do (the white dots indicate the points that I want to find). However, in my case the yellow curve is simply a line segment.
[Yunjin Lee, et al. "Mesh scissoring with minima rule and part salience." 2005]
Any help is very much appreciated.
Here's my suggestion:
Project the screen line into world space (getting a plane in world space).
Intersect the plane with the triangles in the mesh, getting a set of edges.
Add the edges to a data structure that keeps only the parts of the edges that are closest to the camera plane (see the diagram below, in which the red line segments and their endpoints are the ones we want to keep). This is like building up an image via a Z-buffer, except that because we know that this set is piecewise linear, we don't have to rasterize it, we can just maintain a sorted list of endpoints.

Resources