jceipek / pyShiva

Very easy 2d drawing library for python.
9 stars 5 forks source link

Sample Code for Drawing Paths? #14

Open itdaniher opened 11 years ago

itdaniher commented 11 years ago

Is this project capable of drawing vector lines, bezziers or the like? If so, could some documentation for this functionality be added?

Thanks!

jceipek commented 11 years ago

Thanks for showing interest in pyshiva, Ian.

Currently, the documentation is fully up to date with the exception of strokes. @berit and I plan to add support for arbitrary vector paths over the next few weeks. Text support is also hopefully coming soon.

Let me know if there are any other features you think we should prioritize.

jceipek commented 11 years ago

@itdaniher @berit @dianavermilya, I investigated arbitrary path support. The C implementation seems trivial to expose to Python, but deciding on a Python API that makes sense is very challenging because of the way that paths are defined in C.

Here's an example of a smooth curve defining a pear and its stem in C:

  VGPath temp;

  VGubyte segs[] = {
    VG_MOVE_TO_ABS, VG_CUBIC_TO_ABS, VG_CUBIC_TO_ABS, VG_CUBIC_TO_ABS,
    VG_CUBIC_TO_ABS, VG_CUBIC_TO_ABS, VG_CUBIC_TO_ABS, VG_CUBIC_TO_ABS,
    VG_CUBIC_TO_ABS, VG_CUBIC_TO_ABS, VG_CUBIC_TO_ABS, VG_CLOSE_PATH,
    VG_MOVE_TO_ABS, VG_CUBIC_TO_ABS, VG_CUBIC_TO_ABS, VG_CLOSE_PATH };

  VGfloat data[] = {
    0.0625,-90.625001, -29.44062,-89.191161, -23.07159,-32.309301,
    -30.5625,-14.062501, -38.29681,4.7771994, -56.8077,20.767199,
    -56.46875,42.812499, -56.1298,64.502999, -40.15822,79.731799,
    -22.34375,79.812499, -4.17446,79.893199, -1.93369,71.113999,
    4.15625,71.156199, 10.49619,71.198499, 13.70293,80.336799,
    30.4375,80.281199, 42.49257,80.241199, 53.53251,70.782999,
    58.75,58.218799, 47.0442,54.768499, 38.5,43.943499,
    38.5,31.124999, 38.50001,22.754099, 42.14686,15.236999,
    47.9375,10.062499, 42.2834,1.5737994, 36.5413,-6.6199006,
    34.09375,-14.062501, 28.48694,-31.111801, 32.99356,-90.265511,
    1.5,-90.625001,

    5.1056438,-97.8762, -12.766585,-99.48239, -22.244878,-111.09615,
    -22.325466,-129.98288, -6.486451,-125.28908, 2.8790668,-113.87186,
    5.1056438,-97.8762 };

  temp = testCreatePath();
  vgAppendPathData(temp, sizeof(segs), segs, data);

Alternatively, a triangle:

void createArrow(VGPath p, VGfloat cx, VGfloat cy, VGfloat dx, VGfloat dy)
{
  VGfloat px = -dy, py = dx;
  testMoveTo(p, cx + 10*dx, cy + 10*dy, VG_ABSOLUTE);
  testLineTo(p, cx +  5*px, cy +  5*py, VG_ABSOLUTE);
  testLineTo(p, cx -  5*px, cy -  5*py, VG_ABSOLUTE);
  testClosePath(p);
}

One thing I could do within about an hour is to make a Polygon class for closed shapes that follow a sequence of points. While this might be useful, It doesn't scale to graphics with smooth curves.

One option could be to make an empty Path class that has methods like add_line_to(x,y), add_cubic_to(x,y), and close_path(). Can any of you think of a better API?

Note: I'm in Austria, which means that I have a terrible internet connection and that it is 1:30 PM for me right now.

dianavermilya commented 11 years ago

There already is a polygon class in shivaVG

On Sat, Dec 22, 2012 at 7:37 AM, Julian Ceipek notifications@github.comwrote:

@itdaniher https://github.com/itdaniher @berithttps://github.com/berit @dianavermilya https://github.com/dianavermilya, I investigated arbitrary path support. The C implementation seems trivial to expose to Python, but deciding on a Python API that makes sense is very challenging because of the way that paths are defined in C.

Here's an example of a smooth curve defining a pear and its stem in C:

VGPath temp;

VGubyte segs[] = { VG_MOVE_TO_ABS, VG_CUBIC_TO_ABS, VG_CUBIC_TO_ABS, VG_CUBIC_TO_ABS, VG_CUBIC_TO_ABS, VG_CUBIC_TO_ABS, VG_CUBIC_TO_ABS, VG_CUBIC_TO_ABS, VG_CUBIC_TO_ABS, VG_CUBIC_TO_ABS, VG_CUBIC_TO_ABS, VG_CLOSE_PATH, VG_MOVE_TO_ABS, VG_CUBIC_TO_ABS, VG_CUBIC_TO_ABS, VG_CLOSE_PATH };

VGfloat data[] = { 0.0625,-90.625001, -29.44062,-89.191161, -23.07159,-32.309301, -30.5625,-14.062501, -38.29681,4.7771994, -56.8077,20.767199, -56.46875,42.812499, -56.1298,64.502999, -40.15822,79.731799, -22.34375,79.812499, -4.17446,79.893199, -1.93369,71.113999, 4.15625,71.156199, 10.49619,71.198499, 13.70293,80.336799, 30.4375,80.281199, 42.49257,80.241199, 53.53251,70.782999, 58.75,58.218799, 47.0442,54.768499, 38.5,43.943499, 38.5,31.124999, 38.50001,22.754099, 42.14686,15.236999, 47.9375,10.062499, 42.2834,1.5737994, 36.5413,-6.6199006, 34.09375,-14.062501, 28.48694,-31.111801, 32.99356,-90.265511, 1.5,-90.625001,

5.1056438,-97.8762, -12.766585,-99.48239, -22.244878,-111.09615,
-22.325466,-129.98288, -6.486451,-125.28908, 2.8790668,-113.87186,
5.1056438,-97.8762 };

temp = testCreatePath(); vgAppendPathData(temp, sizeof(segs), segs, data);

Alternatively, a triangle:

void createArrow(VGPath p, VGfloat cx, VGfloat cy, VGfloat dx, VGfloat dy) { VGfloat px = -dy, py = dx; testMoveTo(p, cx + 10_dx, cy + 10_dy, VG_ABSOLUTE); testLineTo(p, cx + 5_px, cy + 5_py, VG_ABSOLUTE); testLineTo(p, cx - 5_px, cy - 5_py, VG_ABSOLUTE); testClosePath(p); }

One thing I could do within about an hour is to make a Polygon class for closed shapes that follow a sequence of points. While this might be useful, It doesn't scale to graphics with smooth curves.

One option could be to make an empty Path class that has methods like add_line_to(x,y), add_cubic_to(x,y), and close_path(). Can any of you think of a better API?

Note: I'm in Austria, which means that I have a terrible internet connection and that it is 1:30 PM for me right now.

— Reply to this email directly or view it on GitHubhttps://github.com/jceipek/pyShiva/issues/14#issuecomment-11636782.

jceipek commented 11 years ago

@dianavermilya, we can indeed use

VGU_API_CALL VGUErrorCode vguPolygon(VGPath path,
                                     const VGfloat * points, VGint count,
                                     VGboolean closed)

However, that does not address the issue of bezier curves. I'm not going to do much implementation work until the desired API for arbitrary paths is confirmed. Thoughts? Is the Path class I proposed a good solution? Can you think of a better one, @itdaniher, @berit, or @dianavermilya?

itdaniher commented 11 years ago

One option could be to make an empty Path class that has methods like add_line_to(x,y), add_cubic_to(x,y), and close_path(). Can any of you think of a better API?

That does mesh well with my intended use case, doing high performance-ish audio / data visualization work. With fir_filter.py and pyShiva, I'm about halfway to some really really neat datastream hacking in Python.

jceipek commented 11 years ago

I'd love to hear how it goes, @itdaniher. I just started the implementation. Currently, it uses absolute coordinates, but relative coordinates will come soon. I only added support for straight lines for now, but more interesting paths will be possible over the next few days (maybe as soon as tomorrow!).

Let me know what you think of path_test.py, which creates a right triangle.

jceipek commented 11 years ago

Added support for quadratic curves in 0356243dc8301cde3b6e3fc22a311aec6da4d7d3 and provided an example in path_test.py.

Everything I have done so far is immutable (existing paths cannot yet be modified), but maybe it is already useful to some degree? I'll look into mutability soon.

jceipek commented 11 years ago

@itdaniher Making paths mutable is more challenging than I expected, both API-wise and from the C side of things. You can take a look at the paths branch if you are curious.

How do you want to be able to modify paths?

I was considering giving paths a list of PathElements that can be modified with the following API:

p = ps.Path(100,100)#,color=(1,0,0,1))
p.add_line_to(0,100)
p.add_line_to(100,100)
w.add(p)
p[0].x = math.sin(t)*100 # Modifying the x coordinate of the first line segment

However, this feels ugly to me and seems to make modifications to paths more challenging than I would like.

ShivaVG has the function VG_API_CALL void vgModifyPathCoords(VGPath dstPath, VGint startIndex, VGint numSegments, const void * data), which overwrites the coordinates for a specified number of segments (as far as I can tell, lines, quads, etc... are known as segments in ShivaVG). It looks like changing the type of a segment is not possible without recreating the path (but I could make that transparent to Python).

Going to sleep now. Let me know what you think, @itdaniher, @berit, @dianavermilya.