-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathrender.cpp
More file actions
64 lines (59 loc) · 2.18 KB
/
render.cpp
File metadata and controls
64 lines (59 loc) · 2.18 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
/*
* Vectorix -- line-based image vectorizer
* (c) 2016 Jan Hadrava <had@atrey.karlin.mff.cuni.cz>
*/
#include <cstdlib>
#include <cstdarg>
#include <cstdio>
#include "v_image.h"
#include "pnm_handler.h"
#include "render.h"
// Simple renderer from v_image to pnm bitmap
// Does not need OpenCV
// Warning: Ignores fill type -- renders everything as lines
namespace vectorix {
void renderer::bezier_render(pnm_image &bitmap, const v_line &line) { // Render one path made of bezier curves (or straight line)
if (bitmap.type != pnm_variant_type::binary_pgm) {
logger log(log_level::error);
log.log<log_level::error>("Error: Image type %i not supported.\n", bitmap.type);
return;
}
auto two = line.segment.cbegin();
auto one = two;
if (two != line.segment.cend())
two++;
while (two != line.segment.cend()) { // Cycle throught every segment
for (p u = 0; u <= 1; u += 0.0005) { // Rendering is done with fixed step
// This is definitely not a good idea. It is
// unnecessarily slow on short paths and may leave
// white spots on large paths. Fortunately there is
// completely different approach implemented in
// opencv_render.
p v = 1-u;
p x = v*v*v*one->main.x + 3*v*v*u*one->control_next.x + 3*v*u*u*two->control_prev.x + u*u*u*two->main.x; // Bezier coefficients
p y = v*v*v*one->main.y + 3*v*v*u*one->control_next.y + 3*v*u*u*two->control_prev.y + u*u*u*two->main.y;
p w = v*one->width + u*two->width;
for (int j = y - w/2; j<= y + w/2; j++) { // Line has some width -- thick lines are realy slow to render
if (j<0 || j>=bitmap.height) // Do not draw outside of an image
continue;
for (int i = x - w/2; i<= x + w/2; i++) {
if (i<0 || i>=bitmap.width)
continue;
if ((x-i)*(x-i) + (y-j)*(y-j) <= w*w/4) // Check if we are in distance <= radius
bitmap.data[i+j*bitmap.width] = 0;
}
}
}
one = two; // Move to next segment
two++;
}
}
pnm_image renderer::render(const v_image &vector) {
auto bitmap = pnm_image(vector.width, vector.height, pnm_variant_type::binary_pgm, *par);
bitmap.erase_image();
for (v_line line: vector.line) { // Render each line in image
bezier_render(bitmap, line);
}
return bitmap;
}
}; // namespace