193
193
CanvasAxonomGrid::CanvasAxonomGrid (SPNamedView * nv, Inkscape::XML::Node * in_repr, SPDocument * in_doc)
194
194
: CanvasGrid(nv, in_repr, in_doc, GRID_AXONOMETRIC)
196
gridunit = sp_unit_get_by_abbreviation( prefs_get_string_attribute("options.grids.axonom", "units") );
196
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
197
gridunit = sp_unit_get_by_abbreviation( prefs->getString("/options/grids/axonom/units").data() );
198
199
gridunit = &sp_unit_get_by_id(SP_UNIT_PX);
199
origin[NR::X] = sp_units_get_pixels( prefs_get_double_attribute ("options.grids.axonom", "origin_x", 0.0), *(gridunit) );
200
origin[NR::Y] = sp_units_get_pixels( prefs_get_double_attribute ("options.grids.axonom", "origin_y", 0.0), *(gridunit) );
201
color = prefs_get_int_attribute("options.grids.axonom", "color", 0x0000ff20);
202
empcolor = prefs_get_int_attribute("options.grids.axonom", "empcolor", 0x0000ff40);
203
empspacing = prefs_get_int_attribute("options.grids.axonom", "empspacing", 5);
204
lengthy = sp_units_get_pixels( prefs_get_double_attribute ("options.grids.axonom", "spacing_y", 1.0), *(gridunit) );
205
angle_deg[X] = prefs_get_double_attribute ("options.grids.axonom", "angle_x", 30.0);
206
angle_deg[Z] = prefs_get_double_attribute ("options.grids.axonom", "angle_z", 30.0);
200
origin[Geom::X] = sp_units_get_pixels( prefs->getDouble("/options/grids/axonom/origin_x", 0.0), *gridunit );
201
origin[Geom::Y] = sp_units_get_pixels( prefs->getDouble("/options/grids/axonom/origin_y", 0.0), *gridunit );
202
color = prefs->getInt("/options/grids/axonom/color", 0x0000ff20);
203
empcolor = prefs->getInt("/options/grids/axonom/empcolor", 0x0000ff40);
204
empspacing = prefs->getInt("/options/grids/axonom/empspacing", 5);
205
lengthy = sp_units_get_pixels( prefs->getDouble("/options/grids/axonom/spacing_y", 1.0), *gridunit );
206
angle_deg[X] = prefs->getDouble("/options/grids/axonom/angle_x", 30.0);
207
angle_deg[Z] = prefs->getDouble("/options/grids/axonom/angle_z", 30.0);
207
208
angle_deg[Y] = 0;
209
210
angle_rad[X] = deg_to_rad(angle_deg[X]);
387
393
_wr.setUpdating (true);
389
Inkscape::UI::Widget::RegisteredUnitMenu *_rumg = new Inkscape::UI::Widget::RegisteredUnitMenu();
390
Inkscape::UI::Widget::RegisteredScalarUnit *_rsu_ox = new Inkscape::UI::Widget::RegisteredScalarUnit();
391
Inkscape::UI::Widget::RegisteredScalarUnit *_rsu_oy = new Inkscape::UI::Widget::RegisteredScalarUnit();
392
Inkscape::UI::Widget::RegisteredScalarUnit *_rsu_sy = new Inkscape::UI::Widget::RegisteredScalarUnit();
395
Inkscape::UI::Widget::RegisteredUnitMenu *_rumg = Gtk::manage( new Inkscape::UI::Widget::RegisteredUnitMenu(
396
_("Grid _units:"), "units", _wr, repr, doc) );
397
Inkscape::UI::Widget::RegisteredScalarUnit *_rsu_ox = Gtk::manage( new Inkscape::UI::Widget::RegisteredScalarUnit(
398
_("_Origin X:"), _("X coordinate of grid origin"), "originx", *_rumg, _wr, repr, doc) );
399
Inkscape::UI::Widget::RegisteredScalarUnit *_rsu_oy = Gtk::manage( new Inkscape::UI::Widget::RegisteredScalarUnit(
400
_("O_rigin Y:"), _("Y coordinate of grid origin"), "originy", *_rumg, _wr, repr, doc) );
401
Inkscape::UI::Widget::RegisteredScalarUnit *_rsu_sy = Gtk::manage( new Inkscape::UI::Widget::RegisteredScalarUnit(
402
_("Spacing _Y:"), _("Base length of z-axis"), "spacingy", *_rumg, _wr, repr, doc) );
393
403
Inkscape::UI::Widget::RegisteredScalar *_rsu_ax = Gtk::manage( new Inkscape::UI::Widget::RegisteredScalar(
394
404
_("Angle X:"), _("Angle of x-axis"), "gridanglex", _wr, repr, doc ) );
395
405
Inkscape::UI::Widget::RegisteredScalar *_rsu_az = Gtk::manage( new Inkscape::UI::Widget::RegisteredScalar(
398
408
Inkscape::UI::Widget::RegisteredColorPicker *_rcp_gcol = Gtk::manage(
399
409
new Inkscape::UI::Widget::RegisteredColorPicker(
400
_("Grid line _color:"), _("Grid line color"), _("Color of grid lines"),
410
_("Grid line _color:"), _("Grid line color"), _("Color of grid lines"),
401
411
"color", "opacity", _wr, repr, doc));
403
413
Inkscape::UI::Widget::RegisteredColorPicker *_rcp_gmcol = Gtk::manage(
404
414
new Inkscape::UI::Widget::RegisteredColorPicker(
405
_("Ma_jor grid line color:"), _("Major grid line color"),
415
_("Ma_jor grid line color:"), _("Major grid line color"),
406
416
_("Color of the major (highlighted) grid lines"),
407
417
"empcolor", "empopacity", _wr, repr, doc));
409
Inkscape::UI::Widget::RegisteredSuffixedInteger *_rsi = new Inkscape::UI::Widget::RegisteredSuffixedInteger();
411
Inkscape::UI::Widget::ScalarUnit * sutemp = NULL;
412
_rumg->init (_("Grid _units:"), "units", _wr, repr, doc);
413
_rsu_ox->init (_("_Origin X:"), _("X coordinate of grid origin"),
414
"originx", *_rumg, _wr, repr, doc);
415
sutemp = _rsu_ox->getSU();
416
sutemp->setDigits(4);
417
sutemp->setIncrements(0.1, 1.0);
418
_rsu_oy->init (_("O_rigin Y:"), _("Y coordinate of grid origin"),
419
"originy", *_rumg, _wr, repr, doc);
420
sutemp = _rsu_oy->getSU();
421
sutemp->setDigits(4);
422
sutemp->setIncrements(0.1, 1.0);
423
_rsu_sy->init (_("Spacing _Y:"), _("Base length of z-axis"),
424
"spacingy", *_rumg, _wr, repr, doc);
425
sutemp = _rsu_sy->getSU();
426
sutemp->setDigits(4);
427
sutemp->setIncrements(0.1, 1.0);
428
_rsi->init (_("_Major grid line every:"), _("lines"), "empspacing", _wr, repr, doc);
419
Inkscape::UI::Widget::RegisteredSuffixedInteger *_rsi = Gtk::manage( new Inkscape::UI::Widget::RegisteredSuffixedInteger(
420
_("_Major grid line every:"), "", _("lines"), "empspacing", _wr, repr, doc ) );
422
_rsu_ox->setDigits(4);
423
_rsu_ox->setIncrements(0.1, 1.0);
425
_rsu_oy->setDigits(4);
426
_rsu_oy->setIncrements(0.1, 1.0);
428
_rsu_sy->setDigits(4);
429
_rsu_sy->setIncrements(0.1, 1.0);
429
431
_wr.setUpdating (false);
431
433
Gtk::Widget const *const widget_array[] = {
432
_rumg->_label, _rumg->_sel,
438
440
_rcp_gcol->_label, _rcp_gcol,
440
442
_rcp_gmcol->_label, _rcp_gmcol,
441
_rsi->_label, &_rsi->_hbox,
444
446
attach_all (*table, widget_array, sizeof(widget_array));
675
/* This is to make sure we snap to only visible grid lines */
676
double scaled_spacing_h = grid->spacing_ylines; // this is spacing of visible lines if screen pixels
677
double scaled_spacing_v = grid->lyw; // vertical
679
// convert screen pixels to px
680
// FIXME: after we switch to snapping dist in screen pixels, this will be unnecessary
681
if (SP_ACTIVE_DESKTOP) {
682
scaled_spacing_h /= SP_ACTIVE_DESKTOP->current_zoom();
683
scaled_spacing_v /= SP_ACTIVE_DESKTOP->current_zoom();
696
if (getSnapVisibleOnly()) {
697
// Only snapping to visible grid lines
698
spacing_h = grid->spacing_ylines; // this is the spacing of the visible grid lines measured in screen pixels
699
spacing_v = grid->lyw; // vertical
700
// convert screen pixels to px
701
// FIXME: after we switch to snapping dist in screen pixels, this will be unnecessary
702
SPDesktop const *dt = _snapmanager->getDesktop();
704
spacing_h /= dt->current_zoom();
705
spacing_v /= dt->current_zoom();
708
// Snapping to any grid line, whether it's visible or not
709
spacing_h = grid->lengthy /(grid->tan_angle[X] + grid->tan_angle[Z]);
710
spacing_v = grid->lengthy;
686
714
// In an axonometric grid, any point will be surrounded by 6 grid lines:
687
715
// - 2 vertical grid lines, one left and one right from the point
688
716
// - 2 angled z grid lines, one above and one below the point
689
717
// - 2 angled x grid lines, one above and one below the point
691
719
// Calculate the x coordinate of the vertical grid lines
692
NR::Coord x_max = Inkscape::Util::round_to_upper_multiple_plus(p[NR::X], scaled_spacing_h, grid->origin[NR::X]);
693
NR::Coord x_min = Inkscape::Util::round_to_lower_multiple_plus(p[NR::X], scaled_spacing_h, grid->origin[NR::X]);
720
Geom::Coord x_max = Inkscape::Util::round_to_upper_multiple_plus(p[Geom::X], spacing_h, grid->origin[Geom::X]);
721
Geom::Coord x_min = Inkscape::Util::round_to_lower_multiple_plus(p[Geom::X], spacing_h, grid->origin[Geom::X]);
695
723
// Calculate the y coordinate of the intersection of the angled grid lines with the y-axis
696
double y_proj_along_z = p[NR::Y] - grid->tan_angle[Z]*(p[NR::X] - grid->origin[NR::X]);
697
double y_proj_along_x = p[NR::Y] + grid->tan_angle[X]*(p[NR::X] - grid->origin[NR::X]);
698
double y_proj_along_z_max = Inkscape::Util::round_to_upper_multiple_plus(y_proj_along_z, scaled_spacing_v, grid->origin[NR::Y]);
699
double y_proj_along_z_min = Inkscape::Util::round_to_lower_multiple_plus(y_proj_along_z, scaled_spacing_v, grid->origin[NR::Y]);
700
double y_proj_along_x_max = Inkscape::Util::round_to_upper_multiple_plus(y_proj_along_x, scaled_spacing_v, grid->origin[NR::Y]);
701
double y_proj_along_x_min = Inkscape::Util::round_to_lower_multiple_plus(y_proj_along_x, scaled_spacing_v, grid->origin[NR::Y]);
724
double y_proj_along_z = p[Geom::Y] - grid->tan_angle[Z]*(p[Geom::X] - grid->origin[Geom::X]);
725
double y_proj_along_x = p[Geom::Y] + grid->tan_angle[X]*(p[Geom::X] - grid->origin[Geom::X]);
726
double y_proj_along_z_max = Inkscape::Util::round_to_upper_multiple_plus(y_proj_along_z, spacing_v, grid->origin[Geom::Y]);
727
double y_proj_along_z_min = Inkscape::Util::round_to_lower_multiple_plus(y_proj_along_z, spacing_v, grid->origin[Geom::Y]);
728
double y_proj_along_x_max = Inkscape::Util::round_to_upper_multiple_plus(y_proj_along_x, spacing_v, grid->origin[Geom::Y]);
729
double y_proj_along_x_min = Inkscape::Util::round_to_lower_multiple_plus(y_proj_along_x, spacing_v, grid->origin[Geom::Y]);
731
// Calculate the versor for the angled grid lines
732
Geom::Point vers_x = Geom::Point(1, -grid->tan_angle[X]);
733
Geom::Point vers_z = Geom::Point(1, grid->tan_angle[Z]);
703
735
// Calculate the normal for the angled grid lines
704
NR::Point norm_x = NR::rot90(NR::Point(1, -grid->tan_angle[X]));
705
NR::Point norm_z = NR::rot90(NR::Point(1, grid->tan_angle[Z]));
707
// The four angled grid lines form a parallellogram, enclosing the point
708
// One of the two vertical grid lines divides this parallellogram in two triangles
709
// We will now try to find out in which half (i.e. triangle) our point is, and return
710
// only the three grid lines defining that triangle
712
// The vertical grid line is at the intersection of two angled grid lines.
736
Geom::Point norm_x = Geom::rot90(vers_x);
737
Geom::Point norm_z = Geom::rot90(vers_z);
739
// The four angled grid lines form a parallelogram, enclosing the point
740
// One of the two vertical grid lines divides this parallelogram in two triangles
741
// We will now try to find out in which half (i.e. triangle) our point is, and return
742
// only the three grid lines defining that triangle
744
// The vertical grid line is at the intersection of two angled grid lines.
713
745
// Now go find that intersection!
715
Geom::IntersectorKind is = line_intersection(norm_x.to_2geom(), norm_x[NR::Y]*y_proj_along_x_max,
716
norm_z.to_2geom(), norm_z[NR::Y]*y_proj_along_z_max,
719
// Determine which half of the parallellogram to use
746
Geom::Point p_x(0, y_proj_along_x_max);
747
Geom::Line line_x(p_x, p_x + vers_x);
748
Geom::Point p_z(0, y_proj_along_z_max);
749
Geom::Line line_z(p_z, p_z + vers_z);
751
Geom::OptCrossing inters = Geom::OptCrossing(); // empty by default
754
inters = Geom::intersection(line_x, line_z);
756
catch (Geom::InfiniteSolutions e)
758
// We're probably dealing with parallel lines; this is useless!
762
// Determine which half of the parallelogram to use
720
763
bool use_left_half = true;
721
764
bool use_right_half = true;
723
if (is == Geom::intersects) {
724
use_left_half = (p[NR::X] - grid->origin[NR::X]) < result[Geom::X];
725
use_right_half = !use_left_half;
767
Geom::Point inters_pt = line_x.pointAt((*inters).ta);
768
use_left_half = (p[Geom::X] - grid->origin[Geom::X]) < inters_pt[Geom::X];
769
use_right_half = !use_left_half;
728
//std::cout << "intersection at " << result << " leads to use_left_half = " << use_left_half << " and use_right_half = " << use_right_half << std::endl;
730
772
// Return the three grid lines which define the triangle that encloses our point
731
773
// If we didn't find an intersection above, all 6 grid lines will be returned
732
774
if (use_left_half) {
733
s.push_back(std::make_pair(norm_z, NR::Point(grid->origin[NR::X], y_proj_along_z_max)));
734
s.push_back(std::make_pair(norm_x, NR::Point(grid->origin[NR::X], y_proj_along_x_min)));
735
s.push_back(std::make_pair(component_vectors[NR::X], NR::Point(x_max, 0)));
775
s.push_back(std::make_pair(norm_z, Geom::Point(grid->origin[Geom::X], y_proj_along_z_max)));
776
s.push_back(std::make_pair(norm_x, Geom::Point(grid->origin[Geom::X], y_proj_along_x_min)));
777
s.push_back(std::make_pair(component_vectors[Geom::X], Geom::Point(x_max, 0)));
738
780
if (use_right_half) {
739
s.push_back(std::make_pair(norm_z, NR::Point(grid->origin[NR::X], y_proj_along_z_min)));
740
s.push_back(std::make_pair(norm_x, NR::Point(grid->origin[NR::X], y_proj_along_x_max)));
741
s.push_back(std::make_pair(component_vectors[NR::X], NR::Point(x_min, 0)));
781
s.push_back(std::make_pair(norm_z, Geom::Point(grid->origin[Geom::X], y_proj_along_z_min)));
782
s.push_back(std::make_pair(norm_x, Geom::Point(grid->origin[Geom::X], y_proj_along_x_max)));
783
s.push_back(std::make_pair(component_vectors[Geom::X], Geom::Point(x_min, 0)));
747
void CanvasAxonomGridSnapper::_addSnappedLine(SnappedConstraints &sc, NR::Point const snapped_point, NR::Coord const snapped_distance, NR::Point const normal_to_line, NR::Point const point_on_line) const
789
void CanvasAxonomGridSnapper::_addSnappedLine(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source, Geom::Point const normal_to_line, Geom::Point const point_on_line) const
749
SnappedLine dummy = SnappedLine(snapped_point, snapped_distance, getSnapperTolerance(), getSnapperAlwaysSnap(), normal_to_line, point_on_line);
791
SnappedLine dummy = SnappedLine(snapped_point, snapped_distance, source, Inkscape::SNAPTARGET_GRID, getSnapperTolerance(), getSnapperAlwaysSnap(), normal_to_line, point_on_line);
750
792
sc.grid_lines.push_back(dummy);
795
void CanvasAxonomGridSnapper::_addSnappedPoint(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source) const
797
SnappedPoint dummy = SnappedPoint(snapped_point, source, Inkscape::SNAPTARGET_GRID, snapped_distance, getSnapperTolerance(), getSnapperAlwaysSnap(), true);
798
sc.points.push_back(dummy);
801
bool CanvasAxonomGridSnapper::ThisSnapperMightSnap() const
803
return _snap_enabled && _snapmanager->snapprefs.getSnapToGrids() && _snapmanager->snapprefs.getSnapModeBBoxOrNodes();
755
807
}; // namespace Inkscape