14#include <cairomm/enums.h>
26 int step = std::max(major, 1);
29 while (length * multiply < 8.0 && watchdog < 100) {
50 , _major_line_interval(5)
80 std::vector<Geom::Point> intersections;
81 for (
int i = 0; i < 4; ++i) {
85 intersections.emplace_back(line.
pointAt(oc->ta));
162 _name =
"CanvasItemGridXY";
175 for (
int dim : {0, 1}) {
177 sw[dim] *= scaling_factor;
178 scaled[dim] = scaling_factor > 1;
191 buf.cr->translate(-
buf.rect.left(), -
buf.rect.top());
192 buf.cr->set_line_width(1.0);
193 buf.cr->set_line_cap(Cairo::Context::LineCap::SQUARE);
198 for (
int dim : {0, 1}) {
199 int const nrm = dim ^ 0x1;
211 for (
int c = 0;
c < 4; ++
c) {
224 int start = std::floor(min / spacing);
225 int stop = std::floor(max / spacing);
228 for (
int j =
start + 1; j <= stop; ++j) {
239 std::swap(x[0], x[1]);
245 buf.cr->move_to(
floor(x[0].x()) + 0.5,
floor(x[0].y()) + 0.5);
246 buf.cr->line_to(
floor(x[1].x()) + 0.5,
floor(x[1].y()) + 0.5);
257 uint32_t _empdot = (empcolor & 0xff) << 2;
260 _empdot += (empcolor & 0xffffff00);
262 uint32_t _colordot = (color & 0xff) << 2;
263 if (_colordot > 0xff)
265 _colordot += (color & 0xffffff00);
274 std::vector<double> dashes;
277 dashes.push_back(1.0);
278 dashes.push_back(dash - 1.0);
284 dashes.push_back(3.0);
285 dashes.push_back(dash - 3.0);
291 buf.cr->set_line_cap(Cairo::Context::LineCap::BUTT);
296 uint32_t col = noemp ? color : empcolor;
304 std::cerr <<
"CanvasItemGridXY::render: Grid line doesn't intersect!" << std::endl;
323 _name =
"CanvasItemGridAxonom";
346 lyw *= scaling_factor;
347 scaled = scaling_factor > 1;
364 angle_deg[X] = std::clamp(deg, 0.0, 89.0);
384 buf.cr->move_to(0.5 + x0, 0.5 + y0);
385 buf.cr->line_to(0.5 + x1, 0.5 + y1);
393 if (x <
buf.rect.left() || x >=
buf.rect.right())
396 buf.cr->move_to(0.5 + x, 0.5 + ys);
397 buf.cr->line_to(0.5 + x, 0.5 + ye);
414 buf.cr->translate(-
buf.rect.left(), -
buf.rect.top());
415 buf.cr->set_line_width(1.0);
416 buf.cr->set_line_cap(Cairo::Context::LineCap::SQUARE);
423 auto const buf_tl_gc =
buf.rect.min() -
ow;
428 double const xintercept_y_bc = (buf_tl_gc.x() *
tan_angle[X]) - buf_tl_gc.
y();
429 double const xstart_y_sc = (xintercept_y_bc - std::floor(xintercept_y_bc /
lyw) *
lyw) +
buf.rect.top();
430 int const xlinestart = std::round((xstart_y_sc - buf_tl_gc.x() *
tan_angle[X] -
ow.
y()) /
lyw);
431 int xlinenum = xlinestart;
434 for (
double y = xstart_y_sc; y <
buf.rect.bottom(); y +=
lyw, xlinenum++) {
435 int const x0 =
buf.rect.left();
436 int const y0 = round(y);
437 int x1 = x0 + round((
buf.rect.bottom() - y) /
tan_angle[X]);
438 int y1 =
buf.rect.bottom();
440 x1 =
buf.rect.right();
445 drawline(
buf, x0, y0, x1, y1, noemp ? color : empcolor);
450 double const xstart_x_sc =
buf.rect.left() + (
lxw_x - (xstart_y_sc -
buf.rect.top()) /
tan_angle[X]);
451 xlinenum = xlinestart-1;
452 for (
double x = xstart_x_sc; x <
buf.rect.right(); x +=
lxw_x, xlinenum--) {
453 int const y0 =
buf.rect.top();
454 int const y1 =
buf.rect.bottom();
455 int const x0 = round(x);
456 int const x1 = x0 + round((y1 - y0) /
tan_angle[X]);
459 drawline(
buf, x0, y0, x1, y1, noemp ? color : empcolor);
466 int ylinenum = ylinestart;
467 for (
double x = ystart_x_sc; x <
buf.rect.right(); x +=
spacing_ylines, ylinenum++) {
468 int const x0 =
floor(x);
472 vline(
buf, x0,
buf.rect.top(),
buf.rect.bottom() - 1, noemp ? color : empcolor);
476 double const zintercept_y_bc = (buf_tl_gc.x() * -
tan_angle[
Z]) - buf_tl_gc.y();
477 double const zstart_y_sc = (zintercept_y_bc - std::floor(zintercept_y_bc /
lyw) *
lyw) +
buf.rect.top();
478 int const zlinestart = std::round((zstart_y_sc + buf_tl_gc.x() *
tan_angle[
Z] -
ow.
y()) /
lyw);
479 int zlinenum = zlinestart;
481 double next_y = zstart_y_sc;
482 for (
double y = zstart_y_sc; y <
buf.rect.bottom(); y +=
lyw, zlinenum++, next_y = y) {
483 int const x0 =
buf.rect.left();
484 int const y0 = round(y);
486 int y1 =
buf.rect.top();
488 x1 =
buf.rect.right();
493 drawline(
buf, x0, y0, x1, y1, noemp ? color : empcolor);
498 double const zstart_x_sc =
buf.rect.left() + (next_y -
buf.rect.bottom()) /
tan_angle[
Z];
499 for (
double x = zstart_x_sc; x <
buf.rect.right(); x +=
lxw_z, zlinenum++) {
500 int const y0 =
buf.rect.bottom();
501 int const y1 =
buf.rect.top();
502 int const x0 = round(x);
506 drawline(
buf, x0, y0, x1, y1, noemp ? color : empcolor);
516 _name =
"CanvasItemGridTiles";
521 if (
_gap == gap_size)
return;
529 if (
_margin == margin_size)
return;
541 auto pitch = tile +
_gap;
556 buf.cr->translate(-
buf.rect.left(), -
buf.rect.top());
557 buf.cr->set_line_width(1.0);
558 buf.cr->set_line_cap(Cairo::Context::LineCap::BUTT);
563 auto mod = [](
double v,
double m){
564 return v >= 0 ? fmod(v, m) : m - fmod(-v, m);
566 auto min =
Geom::Point(buf_rect_with_margin.min());
577 auto pix_grid = [](
double p){
return floor(p) + 0.5; };
586 auto width = right - left;
587 auto height = bottom - top;
608 auto width = right - left;
609 auto height = bottom - top;
double distance(Shape const *s, Geom::Point const &p)
static int calculate_scaling_factor(double length, int major)
Coord descrim() const
Calculate the descriminant.
Affine withoutTranslation() const
Point pointAt(Coord t) const override
Evaluate the curve at a specified time value.
CPoint corner(unsigned i) const
Return the n-th corner of the rectangle.
Infinite line on a plane.
Point vector() const
Get the line's raw direction vector.
static Line from_origin_and_vector(Point const &o, Point const &v)
Create a line from origin and unit vector.
Point initialPoint() const
Point pointAt(Coord t) const
Point versor() const
Get the line's normalized direction vector.
Two-dimensional point that doubles as a vector.
Coord length() const
Compute the distance from origin.
constexpr Coord y() const noexcept
constexpr Coord x() const noexcept
Axis aligned, non-empty rectangle.
double angle_rad[3]
Angle of each axis (note that angle[2] == 0)
void _update(bool propagate) override
bool scaled
Whether the grid is in scaled mode.
double lyw
Transformed length y by the affine for the zoom.
double tan_angle[3]
tan(angle[.
CanvasItemGridAxonom(CanvasItemGroup *group)
========= Axonometric Grids ========
void set_angle_x(double value)
void _render(CanvasItemBuffer &buf) const override
This function calls Cairo to render a line on a particular canvas buffer.
Geom::Point ow
Transformed origin by the affine for the zoom.
void set_angle_z(double value)
double angle_deg[3]
Angle of each axis (note that angle[2] == 0)
void set_margin_size(Geom::Point margin_size)
CanvasItemGridTiles(CanvasItemGroup *group)
Geom::Point _world_margin
void set_gap_size(Geom::Point gap_size)
void _update(bool propagate) override
Geom::Point _world_origin
void _render(CanvasItemBuffer &buf) const override
Geom::Point ow
Transformed origin by the affine for the zoom.
CanvasItemGridXY(CanvasItemGroup *group)
====== Rectangular Grid ======
void _update(bool propagate) override
void _render(CanvasItemBuffer &buf) const override
Geom::Point sw[2]
Transformed spacing by the affine for the zoom.
bool scaled[2]
Whether the grid is in scaled mode, which can be different in the X or Y direction,...
void set_no_emp_when_zoomed_out(bool noemp)
void set_spacing(Geom::Point const &point)
CanvasItemGrid(CanvasItemGroup *group)
Create a null control grid.
bool _no_emp_when_zoomed_out
void set_minor_color(uint32_t color)
void set_origin(Geom::Point const &point)
Geom::Point _spacing
Spacing between elements of the grid.
std::unique_ptr< Preferences::PreferencesObserver > _pref_tracker
void set_major_line_interval(int n)
bool contains(Geom::Point const &p, double tolerance=0) override
Returns true if point p (in canvas units) is within tolerance (canvas units) distance of grid.
void set_major_color(uint32_t color)
Geom::Affine const & affine() const
static std::unique_ptr< PreferencesObserver > create(Glib::ustring path, std::function< void(const Preferences::Entry &new_value)> callback)
bool getBool(Glib::ustring const &pref_path, bool def=false)
Retrieve a Boolean value.
static Preferences * get()
Access the singleton Preferences object.
constexpr double SP_RGBA32_G_F(uint32_t v)
constexpr double SP_RGBA32_R_F(uint32_t v)
constexpr double SP_RGBA32_A_F(uint32_t v)
constexpr double SP_RGBA32_B_F(uint32_t v)
constexpr Coord infinity()
Get a value representing infinity.
Specific geometry functions for Inkscape, not provided my lib2geom.
auto floor(Geom::Rect const &rect)
auto expandedBy(Geom::IntRect rect, int amount)
Line make_parallel_line(Point const &p, Line const &line)
OptCrossing intersection(Ray const &r1, Line const &l2)
Piecewise< SBasis > cross(Piecewise< D2< SBasis > > const &a, Piecewise< D2< SBasis > > const &b)
T dot(D2< T > const &a, D2< T > const &b)
bool are_near(Affine const &a1, Affine const &a2, Coord eps=EPSILON)
Helper class to stream background task notifications as a series of messages.
static double signed_distance(Geom::Point const &point, Geom::Line const &line)
static void drawline(Inkscape::CanvasItemBuffer &buf, int x0, int y0, int x1, int y1, uint32_t rgba)
static void vline(Inkscape::CanvasItemBuffer &buf, int x, int ys, int ye, uint32_t rgba)
static std::vector< Geom::Point > intersect_line_rectangle(Geom::Line const &line, Geom::Rect const &rect)
Class used when rendering canvas items.