SVG curve through predetermined points - math

I am a beginner in SVG.
I need an SVG curve that passes through a list of points. It is a math function that is calculated in C++ and the output result is supposed to be written in an SVG file. My problem is that the path tag in SVG does not pass through all points. Instead, it skips some of them in the middle and just tends to them. Does SVG have any facility to pass the curve through the whole points and bend the curve appropriately in automatic way?
<svg height="400" width="450">
<path d="M 80 90 C 190 40, 300 60, 380 160" stroke="blue" stroke-width="5" fill="none" />
<path d="M 80 90 L 190 40, 300 60, 380 160" stroke="green" stroke-width="1" fill="none"/>
<g stroke="black" stroke-width="3" fill="black">
<circle id="pointC" cx="80" cy="90" r="3" stroke="black"/>
<circle id="pointA" cx="190" cy="40" r="3" stroke="green"/>
<circle id="pointC" cx="300" cy="60" r="3" stroke="red"/>
<circle id="pointB" cx="380" cy="160" r="3" stroke="blue"/>
</g>
Sorry, your browser does not support inline SVG.
</svg>

If you need to draw smooth curve through many points, considering using Catmull Rom splines or Overhauser splines. Both algorithms will result in a cubic spline with C1 continuity at the segment junctions. Also, they are easier to implement than implementing C2 B-spline interpolation as the latter requires you to solve a linear equation set. You can also convert Catmull Rom spline or Overhauser spline back to Bezier form easily.

in SVG path thee Bezier curve is approximation not interpolation so it is usually not passing through all the control points.
Sp what to do:
use interpolation cubic curve and convert it to Bezier
Look here: Interpolation cubic to Bezier cubic (needed this for similar reasons like you)
I use a specific interpolation cubic there with connectivity C1 (position and 1st derivation) the translation to Bezier is there so you can use it just convert the control points ... Do not forget to 3x multiple only first and last control point for the whole Bezier path not for each Bezier patch !!!
use many lines instead of single Bezier
this will be choppy of coarse (depending on the lines density) just interpolate enough points and connect them by lines
duplicate control points
if you have multipled control points (3x) then the Bezier will go through this point. So if you have curve points: p0,p1,p2,p3,... then do multiple Beziers from them like this:
p0,p0,p0,p1
p0,p0,p1,p2
p0,p1,p2,p3
p1,p2,p3,p3
p2,p3,p3,p3
p3,p3,p3,p4
p3,p3,p4,p5
p3,p4,p5,p6
p4,p5,p6,p6
p5,p6,p6,p6,...
this will go through the points p0,p3,p6,... so you still need to evaluate the non passing control points to ensure desired connectivity

If you need to draw curve through 4 points only, look at the solution in this topic and linked tinaja page.
If you have to draw smooth curve through many points, consider building interpolation cubic splines (NR book, page 113), than transform these splines to Bezier form (change bazis from polynomial to Bernstein)

Related

What is a generic data structure for bezier curves or b-splines?

I am wondering how you would model arbitrarily complex Bézier curves. I am not quite understanding the underlying abstraction yet of what a bezier curve is fundamentally composed of, as there are too many equations. I would like to have a generic struct that defines a bezier curve. The SVG path gives many examples of the types of curves you can create. They include linear, cubic, and quadratic bezier curves.
If a B-spline is a better generic model, then that would be fine to use too. I am not familiar with those yet tho. Difference between bezier segment and b-spline. I guess "a B-spline curve is a curve that consists of Bezier curves as segments", so that is what I am looking for.
SVG docs say:
Cubic Béziers take in two control points for each point.
<path d="M 10 10 C 20 20, 40 20, 50 10" stroke="black" fill="transparent"/>
Several Bézier curves can be stringed together to create extended, smooth shapes. Often, the control point on one side of a point will be a reflection of the control point used on the other side to keep the slope constant. In this case, a shortcut version of the cubic Bézier can be used, designated by the command S (or s).
<path d="M 10 80 C 40 10, 65 10, 95 80 S 150 150, 180 80" stroke="black" fill="transparent"/>
The other type of Bézier curve, the quadratic curve called with Q, is actually a simpler curve than the cubic one. It requires one control point which determines the slope of the curve at both the start point and the end point. It takes two parameters: the control point and the end point of the curve.
<path d="M 10 80 Q 95 10 180 80" stroke="black" fill="transparent"/>
Arcs and NURBS (non-uniform rational B-splines) are more complex than just plain bezier curves, but it would be nice if the model could be generalized enough to include these as well. Basically I would like a generic model of bezier curves/b-splines/nurbs to use in a drawing/graphics framework, and not sure what that would be.
Must each bezier class be implemented separately, or can they be combined into one generic class?
If separate, are they each basically just an array of control points?
So basically I start to think:
class CubicBezierCurve
include ActiveModel::Model
has_many :control_points
end
class ControlPoint
include ActiveModel::Model
attr_accessor :x, :y
end
But that doesn't quite seem right. A primitive cubic bezier curve, for instance, consists of 2 control points for each point. So perhaps (though, starting to get lost):
class CubicBezierCurve
include ActiveModel::Model
has_many :control_points, class_name: 'CubicBezierCurveControlPoint'
end
class CubicBezierCurveControlPoint
include ActiveModel::Model
attr_accessor :x, :y
end
class Point
include ActiveModel::Model
attr_accessor :x, :y
end
Basically, what is a good generic model for these 3 types of bezier curves (linear, cubic, and quadratic). If it's possible to make them all aspects of the same generic model that would be ideal (as it would mean the fewest number of classes), but if it requires class-specific other classes (like those specific to a cubic bezier curve), that would be fine too.
Implementation can be in any language, such as C structs, typescript, or Ruby models, Python classes, etc..
The reason for this question is so I can then build a DSL for creating curves on top of it, like the SVG path syntax. But the underlying data model will be the compile target.
For further reference, I will be researching these:
https://github.com/twobitcircus/ofxTinyspline, e.g. these structs
https://github.com/pradeep-pyro/tinynurbs/blob/master/include/tinynurbs/core/surface.h
https://github.com/orbingol/NURBS-Python/blob/5.x/geomdl/NURBS.py
https://github.com/StandardCyborg/nurbs
This is just for 2D graphics.
The most generic data structure for a Bezier curve is simply one that contains an array of control points. The degree of the Bezier curve is the number of control points - 1. So, linear, quadratic and cubic Bezier curves can all use the same data structure with difference in number of control points.
For B-spline curve, the generic data structure will contain
Degree (D)
Number of control points (N)
Array of control points
Knot sequence.
The knot sequence is simply a "double[ ]" of length = N+D+1. The knot values need to be in non-decreasing order.
A Bézier curve of degree n is simply d polynomials, one for each dimension.
Each polynomial is written in Bernstein form and has n plus one coefficients (better known as control points). These coefficients alone determine the polynomial. It may thus be helpful to treat each dimension (polynomial) separately, as the Bernstein basis is a rather intuitive way to describe polynomials. See also the paper cited below.
REFERENCES:
Farouki, R.T., 2012. The Bernstein polynomial basis: A centennial retrospective. Computer Aided Geometric Design, 29(6), pp.379-419.

Draw multiple polylines using pyvips

I want to draw a polygon/polyline on to a big image.
So, I am migrating from PIL/opencv to pyvips. Recently, I came across loadsvg_buffer method that can actually do it without the use of draw_mask and draw_image methods.
Can someone give me one fill example using loadsvg_buffer or draw_mask or draw_image. The documentation wasn't much helpful.
Also, what if I have to draw multiple polylines?
Any other insights are welcome.
svgload docs are here:
https://libvips.github.io/libvips/API/current/VipsForeignSave.html#vips-svgload
You can draw any SVG figure. For example:
import pyvips
x = pyvips.Image.svgload_buffer(b"""
<svg viewBox="0 0 200 200">
<circle r="100" cx="100" cy="100" fill="#900"/>
</svg>
""")
x.write_to_file("x.png")
To generate:
The libvips SVG loader is very fast and can make images of any size. It renders progressively, so it doesn't need much memory either.
Use the boolean operators to mask other images with the result, or use composite to layer images together with the PDF blend modes.

How can I convert BezierCurve to B-Spline?

I'm trying to create an animation of a complex path using HTML5 canvas. I've divided my path into some bezier curve and draw each one of them using the cubic bezier curves formula and javascript function lineTo(). The problem is the points that the curves connected to each other. They're not connecting smoothly. I've realized that this problem will be solved if I use the B-Spline curve instead of bezier curves. So, I'm wondering if there is any method to convert bezier curves to b-spline?
Theoretically, a Bezier curve can be considered as a single segment B-spline curve. So, there is really no such thing as "converting a Bezier curve to a B-spline curve". If you can implement cubic Bezier curve evaluation function according to the info in the Wikipedia page, it should not be difficult to implement B-spline curves according to the De Boor algorithm.
If you do not want to go with the extra length of implementing B-spline curves, then what you can do is to modify the Bezier curve's control points locally to make them smoothly joined together. Assuming you have two cubic Bezier curve C1(t) defined by P0,P1,P2 and P3 and C2(t) defined by Q0, Q1, Q2 and Q3 with P3=Q0. You can make C1(t) and C2(t) joined smoothly by projecting P2 and Q1 on a line passing thru the common point P3. How do you choose the line's direction is up to you.

how SVG curveTo ( C ) works?

I need your help , I am confused a little.
My question is how SVG curveTo works, really I can't understand.
look for this example
<svg height="400" width="400">
<path d="M 200 90 C 200 90 0 0 90 300 " stroke="black" fill="none" stroke-width="3"/>
</svg>
this code draws this shape
but really I can't understand how that done , I can't understand how the curve identified and what control points are and what 0 0 coordinate represents in my example.
You are drawing a Cubic Bezier curve (with two control points). But one of the control points has the same coordinates as the starting point.
Move (M) to (200,90).
Draw a Cubic (C) Bezier Curve
a. starting at current position (200,90)
b. first control point at (200,90) - same as starting point
c. second control point at (0,0)
d. ending at (90,300)
Bezier curves are a bit tricky to get the sense of. Perhaps the section at http://www.w3.org/Graphics/SVG/IG/resources/svgprimer.html#path_C might help, and maybe the section before that on quadratic Beziers. As the earlier poster pointed out, having your start point and the control point coincident makes your case a bit odder, still, perhaps.

Convert HTML Path to SVG

I've grabbed some code from somewhere to create an interactive UK map using SVG.
You can see it here:
I'm wondering how I can get the blue area into one big polygon as opposed to separate areas. Any help would seriously appreciated!
Many thanks in advance.
You can group the smaller polygon paths like
<g id="England">
<path .... />
<path .... />
<path .... />
</g>
and then treat them as 1 larger polygon for the purposes of color fill and click area. If you want to remove the inner borders just set the stroke to the same color as the fill.
The only thing you can't do is stroke the outer group since it itself doesn't have a shape, its just the collection of the inner shapes and theres no way to just stroke the edges that do not border another group member. For that you probably would need to actually merge the polygons, which might be easier to do in Inkscape or Adobe Illustrator
See my example here where I've grouped the western US states. Click anywhere in the group to change the color. In the svg(html panel) code, the CA-WA-OR are the last 3 paths at the bottom...
http://jsfiddle.net/webchemist/K9jdD/
Get the original geographic data file in a 'shapefile' or other geospatial data format, load into a GIS package (Quantum GIS is free, open source, and featureful) then do a polygon dissolve operation.
You can also do this with the GEOS library which has an interface to C, Python and R if you can program in any of those languages.

Resources