From b2dfb5760b4ff97eabdaa0272ba7ed7f0dd8c6eb Mon Sep 17 00:00:00 2001 From: cilix42 Date: Mon, 6 Aug 2007 06:51:01 +0000 Subject: [PATCH] Write/read perspectives to/from SVG; store ratios of the distances from corners to VPs (preparation for dragging) --- src/attributes.cpp | 1 + src/attributes.h | 1 + src/box3d-context.cpp | 1 + src/box3d.cpp | 164 ++++++++++++++++++++++++++++++++++++---- src/box3d.h | 10 +++ src/desktop.cpp | 19 ++++- src/desktop.h | 1 + src/knotholder.cpp | 3 +- src/knotholder.h | 3 + src/perspective3d.cpp | 92 +++++++++++++++++++++- src/perspective3d.h | 6 ++ src/vanishing-point.cpp | 9 +++ src/vanishing-point.h | 8 ++ 13 files changed, 299 insertions(+), 19 deletions(-) diff --git a/src/attributes.cpp b/src/attributes.cpp index ee7ebff69..90f3e0280 100644 --- a/src/attributes.cpp +++ b/src/attributes.cpp @@ -113,6 +113,7 @@ static SPStyleProp const props[] = { {SP_ATTR_INKSCAPE_3DBOX_CORNER_A, "inkscape:box3dcornerA"}, // "upper left front" corner {SP_ATTR_INKSCAPE_3DBOX_CORNER_B, "inkscape:box3dcornerB"}, // "lower right front" corner {SP_ATTR_INKSCAPE_3DBOX_CORNER_C, "inkscape:box3dcornerC"}, // "lower right rear" corner + {SP_ATTR_INKSCAPE_3DBOX_PERSPECTIVE, "inkscape:perspective"}, /* SPEllipse */ {SP_ATTR_R, "r"}, {SP_ATTR_CX, "cx"}, diff --git a/src/attributes.h b/src/attributes.h index 5eb906320..9a969dc8c 100644 --- a/src/attributes.h +++ b/src/attributes.h @@ -113,6 +113,7 @@ enum SPAttributeEnum { SP_ATTR_INKSCAPE_3DBOX_CORNER_A, // "upper left front" corner SP_ATTR_INKSCAPE_3DBOX_CORNER_B, // "lower right front" corner SP_ATTR_INKSCAPE_3DBOX_CORNER_C, // "lower right rear" corner + SP_ATTR_INKSCAPE_3DBOX_PERSPECTIVE, /* SPEllipse */ SP_ATTR_R, SP_ATTR_CX, diff --git a/src/box3d-context.cpp b/src/box3d-context.cpp index fc4e74629..c82728c97 100644 --- a/src/box3d-context.cpp +++ b/src/box3d-context.cpp @@ -554,6 +554,7 @@ static void sp_3dbox_finish(SP3DBoxContext *bc) desktop = SP_EVENT_CONTEXT_DESKTOP(bc); SP_OBJECT(bc->item)->updateRepr(); + sp_3dbox_set_ratios(SP_3DBOX(bc->item)); sp_canvas_end_forced_full_redraws(desktop->canvas); diff --git a/src/box3d.cpp b/src/box3d.cpp index 76dad605b..44b2c9bbe 100644 --- a/src/box3d.cpp +++ b/src/box3d.cpp @@ -32,11 +32,13 @@ static Inkscape::XML::Node *sp_3dbox_write(SPObject *object, Inkscape::XML::Node static gchar *sp_3dbox_description(SPItem *item); //static void sp_3dbox_set_shape(SPShape *shape); -static void sp_3dbox_set_shape(SP3DBox *box3d); +//static void sp_3dbox_set_shape(SP3DBox *box3d); static void sp_3dbox_update_corner_with_value_from_svg (SPObject *object, guint corner_id, const gchar *value); +static void sp_3dbox_update_perspective (Box3D::Perspective3D *persp, const gchar *value); static gchar * sp_3dbox_get_corner_coords_string (SP3DBox *box, guint id); static std::pair sp_3dbox_get_coord_pair_from_string (const gchar *); +static gchar * sp_3dbox_get_perspective_string (SP3DBox *box); static SPGroupClass *parent_class; @@ -97,7 +99,33 @@ sp_3dbox_build(SPObject *object, SPDocument *document, Inkscape::XML::Node *repr SP3DBox *box = SP_3DBOX (object); - Box3D::Perspective3D::current_perspective->add_box (box); + if (repr->attribute ("inkscape:perspective") == NULL) { + // we are creating a new box; link it to the current perspective + Box3D::Perspective3D::current_perspective->add_box (box); + } else { + // create a new perspective that we can compare with existing ones + Box3D::Perspective3D *persp = new Box3D::Perspective3D (Box3D::VanishingPoint (0,0), + Box3D::VanishingPoint (0,0), + Box3D::VanishingPoint (0,0)); + sp_3dbox_update_perspective (persp, repr->attribute ("inkscape:perspective")); + SPDesktop *desktop = inkscape_active_desktop(); + Box3D::Perspective3D *comp = desktop->find_perspective (persp); + if (comp == NULL) { + // perspective doesn't exist yet + desktop->add_perspective (persp); + persp->add_box (box); + } else { + // link the box to the existing perspective and delete the temporary one + comp->add_box (box); + delete persp; + //g_assert (Box3D::get_persp_of_box (box) == comp); + + // FIXME: If the paths of the box's faces do not correspond to the svg representation of the perspective + // the box is shown with a "wrong" initial shape that is only corrected after dragging. + // Should we "repair" this by updating the paths at the end of sp_3dbox_build()? + // Maybe it would be better to simply destroy and rebuild them in sp_3dbox_link_to_existing_paths(). + } + } sp_object_read_attr(object, "inkscape:box3dcornerA"); sp_object_read_attr(object, "inkscape:box3dcornerB"); @@ -127,6 +155,8 @@ sp_3dbox_build(SPObject *object, SPDocument *document, Inkscape::XML::Node *repr // Check whether the paths of the faces of the box need to be linked to existing paths in the // document (e.g., after a 'redo' operation or after opening a file) and do so if necessary. sp_3dbox_link_to_existing_paths (box, repr); + + sp_3dbox_set_ratios (box); } static void @@ -160,6 +190,9 @@ static void sp_3dbox_set(SPObject *object, unsigned int key, const gchar *value) case SP_ATTR_INKSCAPE_3DBOX_CORNER_C: sp_3dbox_update_corner_with_value_from_svg (object, 5, value); break; + case SP_ATTR_INKSCAPE_3DBOX_PERSPECTIVE: + sp_3dbox_update_perspective (Box3D::get_persp_of_box (SP_3DBOX (object)), value); + break; default: if (((SPObjectClass *) (parent_class))->set) { ((SPObjectClass *) (parent_class))->set(object, key, value); @@ -206,17 +239,21 @@ static Inkscape::XML::Node *sp_3dbox_write(SPObject *object, Inkscape::XML::Node } if (flags & SP_OBJECT_WRITE_EXT) { - gchar *coords; - coords = sp_3dbox_get_corner_coords_string (box, 2); - repr->setAttribute("inkscape:box3dcornerA", coords); + gchar *str; + str = sp_3dbox_get_corner_coords_string (box, 2); + repr->setAttribute("inkscape:box3dcornerA", str); + + str = sp_3dbox_get_corner_coords_string (box, 1); + repr->setAttribute("inkscape:box3dcornerB", str); - coords = sp_3dbox_get_corner_coords_string (box, 1); - repr->setAttribute("inkscape:box3dcornerB", coords); + str = sp_3dbox_get_corner_coords_string (box, 5); + repr->setAttribute("inkscape:box3dcornerC", str); - coords = sp_3dbox_get_corner_coords_string (box, 5); - repr->setAttribute("inkscape:box3dcornerC", coords); + str = sp_3dbox_get_perspective_string (box); + repr->setAttribute("inkscape:perspective", str); + sp_3dbox_set_ratios (box); - g_free ((void *) coords); + g_free ((void *) str); } if (((SPObjectClass *) (parent_class))->write) { @@ -234,6 +271,27 @@ sp_3dbox_description(SPItem *item) return g_strdup(_("3D Box")); } +void sp_3dbox_set_ratios (SP3DBox *box, Box3D::Axis axes) +{ + Box3D::Perspective3D *persp = Box3D::get_persp_of_box (box); + NR::Point pt; + + if (axes & Box3D::X) { + pt = persp->get_vanishing_point (Box3D::X)->get_pos(); + box->ratio_x = NR::L2 (pt - box->corners[2]) / NR::L2 (pt - box->corners[3]); + } + + if (axes & Box3D::Y) { + pt = persp->get_vanishing_point (Box3D::Y)->get_pos(); + box->ratio_y = NR::L2 (pt - box->corners[2]) / NR::L2 (pt - box->corners[0]); + } + + if (axes & Box3D::Z) { + pt = persp->get_vanishing_point (Box3D::Z)->get_pos(); + box->ratio_z = NR::L2 (pt - box->corners[4]) / NR::L2 (pt - box->corners[0]); + } +} + void sp_3dbox_position_set (SP3DBoxContext &bc) { @@ -255,12 +313,13 @@ sp_3dbox_position_set (SP3DBoxContext &bc) ***/ } -static void +//static +void // FIXME: Note that this is _not_ the virtual set_shape() method inherited from SPShape, // since SP3DBox is inherited from SPGroup. The following method is "artificially" // called from sp_3dbox_update(). //sp_3dbox_set_shape(SPShape *shape) -sp_3dbox_set_shape(SP3DBox *box3d) +sp_3dbox_set_shape(SP3DBox *box3d, bool use_previous_corners) { // FIXME: How to handle other contexts??? // FIXME: Is tools_isactive(..) more recommended to check for the current context/tool? @@ -270,7 +329,11 @@ sp_3dbox_set_shape(SP3DBox *box3d) /* Only update the curves during dragging; setting the svg representations is expensive and only done once at the end */ - sp_3dbox_recompute_corners (box3d, bc->drag_origin, bc->drag_ptB, bc->drag_ptC); + if (!use_previous_corners) { + sp_3dbox_recompute_corners (box3d, bc->drag_origin, bc->drag_ptB, bc->drag_ptC); + } else { + sp_3dbox_recompute_corners (box3d, box3d->corners[2], box3d->corners[1], box3d->corners[5]); + } if (bc->extruded) { box3d->faces[0]->set_corners (box3d->corners[0], box3d->corners[4], box3d->corners[6], box3d->corners[2]); box3d->faces[1]->set_corners (box3d->corners[1], box3d->corners[5], box3d->corners[7], box3d->corners[3]); @@ -457,7 +520,50 @@ sp_3dbox_get_coord_pair_from_string (const gchar *coords) return std::make_pair(coord1, coord2); } -// auxiliary function +static gchar * +sp_3dbox_get_perspective_string (SP3DBox *box) +{ + + return sp_3dbox_get_svg_descr_of_persp (Box3D::get_persp_of_box (box)); +} + +gchar * +sp_3dbox_get_svg_descr_of_persp (Box3D::Perspective3D *persp) +{ + // FIXME: We should move this code to perspective3d.cpp, but this yields compiler errors. Why? + Inkscape::SVGOStringStream os; + + Box3D::VanishingPoint vp = *(persp->get_vanishing_point (Box3D::X)); + os << vp[NR::X] << "," << vp[NR::Y] << ","; + os << vp.v_dir[NR::X] << "," << vp.v_dir[NR::Y] << ","; + if (vp.is_finite()) { + os << "finite,"; + } else { + os << "infinite,"; + } + + vp = *(persp->get_vanishing_point (Box3D::Y)); + os << vp[NR::X] << "," << vp[NR::Y] << ","; + os << vp.v_dir[NR::X] << "," << vp.v_dir[NR::Y] << ","; + if (vp.is_finite()) { + os << "finite,"; + } else { + os << "infinite,"; + } + + vp = *(persp->get_vanishing_point (Box3D::Z)); + os << vp[NR::X] << "," << vp[NR::Y] << ","; + os << vp.v_dir[NR::X] << "," << vp.v_dir[NR::Y] << ","; + if (vp.is_finite()) { + os << "finite"; + } else { + os << "infinite"; + } + + return g_strdup(os.str().c_str()); +} + +// auxiliary functions static void sp_3dbox_update_corner_with_value_from_svg (SPObject *object, guint corner_id, const gchar *value) { @@ -470,6 +576,36 @@ sp_3dbox_update_corner_with_value_from_svg (SPObject *object, guint corner_id, c object->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); } +static void +sp_3dbox_update_perspective (Box3D::Perspective3D *persp, const gchar *value) +{ + // WARNING! This function changes the perspective associated to 'box'. Since there may be + // many other boxes linked to the same perspective, their perspective is also changed. + // If this behaviour is not desired in all cases, we need a different function. + if (value == NULL) return; + + gchar **vps = g_strsplit( value, ",", 0); + for (int i = 0; i < 15; ++i) { + if (vps[i] == NULL) { + g_warning ("Malformed svg attribute 'perspective'\n"); + return; + } + } + + persp->set_vanishing_point (Box3D::X, g_ascii_strtod (vps[0], NULL), g_ascii_strtod (vps[1], NULL), + g_ascii_strtod (vps[2], NULL), g_ascii_strtod (vps[3], NULL), + Box3D::VP_FINITE); + persp->set_vanishing_point (Box3D::Y, g_ascii_strtod (vps[5], NULL), g_ascii_strtod (vps[6], NULL), + g_ascii_strtod (vps[7], NULL), g_ascii_strtod (vps[8], NULL), + Box3D::VP_FINITE); + persp->set_vanishing_point (Box3D::Z, g_ascii_strtod (vps[10], NULL), g_ascii_strtod (vps[11], NULL), + g_ascii_strtod (vps[12], NULL), g_ascii_strtod (vps[13], NULL), + Box3D::VP_FINITE); + + // update the other boxes linked to the same perspective + persp->reshape_boxes (Box3D::XYZ); +} + /* Local Variables: mode:c++ diff --git a/src/box3d.h b/src/box3d.h index ee0f30c81..1b40afa76 100644 --- a/src/box3d.h +++ b/src/box3d.h @@ -36,6 +36,12 @@ struct SP3DBox : public SPGroup { NR::Point corners[8]; Box3DFace *faces[6]; + + // TODO: Keeping/updating the ratios works reasonably well but is still an ad hoc implementation. + // Use a mathematically correct model to update the boxes. + double ratio_x; + double ratio_y; + double ratio_z; }; struct SP3DBoxClass { @@ -45,14 +51,18 @@ struct SP3DBoxClass { GType sp_3dbox_get_type (void); void sp_3dbox_position_set (SP3DBoxContext &bc); +void sp_3dbox_set_shape(SP3DBox *box3d, bool use_previous_corners = false); void sp_3dbox_recompute_corners (SP3DBox *box, NR::Point const pt1, NR::Point const pt2, NR::Point const pt3); void sp_3dbox_update_curves (SP3DBox *box); void sp_3dbox_link_to_existing_paths (SP3DBox *box, Inkscape::XML::Node *repr); +void sp_3dbox_set_ratios (SP3DBox *box, Box3D::Axis axes = Box3D::XYZ); void sp_3dbox_move_corner_in_XY_plane (SP3DBox *box, guint id, NR::Point pt, Box3D::Axis axes = Box3D::XY); void sp_3dbox_move_corner_in_Z_direction (SP3DBox *box, guint id, NR::Point pt, bool constrained = true); NR::Maybe sp_3dbox_get_center (SP3DBox *box); NR::Maybe sp_3dbox_get_midpoint_between_corners (SP3DBox *box, guint id_corner1, guint id_corner2); +gchar * sp_3dbox_get_svg_descr_of_persp (Box3D::Perspective3D *persp); + inline NR::Point sp_3dbox_get_corner (SP3DBox *box, guint id) { return box->corners[id]; } inline bool sp_3dbox_corners_are_adjacent (guint id_corner1, guint id_corner2) { return Box3D::is_single_axis_direction ((Box3D::Axis) (id_corner1 ^ id_corner2)); diff --git a/src/desktop.cpp b/src/desktop.cpp index 6314621c1..f58864955 100644 --- a/src/desktop.cpp +++ b/src/desktop.cpp @@ -720,7 +720,13 @@ void SPDesktop::set_display_area(NR::Rect const &a, NR::Coord b, bool log) void SPDesktop::add_perspective (Box3D::Perspective3D * const persp) { + // check that the perspective is not yet linked to another desktop + if (persp->desktop != NULL) { + g_assert (persp->desktop == this); + } + // FIXME: Should we handle the case that the perspectives have equal VPs but are not identical? + // If so, we need to take care of relinking the boxes, etc. if (persp == NULL || g_slist_find (this->perspectives, persp)) return; this->perspectives = g_slist_prepend (this->perspectives, persp); persp->desktop = this; @@ -729,15 +735,24 @@ SPDesktop::add_perspective (Box3D::Perspective3D * const persp) void SPDesktop::remove_perspective (Box3D::Perspective3D * const persp) { if (persp == NULL) return; - if (!g_slist_find (this->perspectives, persp)) { g_warning ("Could not find perspective in current desktop. Not removed.\n"); return; } - this->perspectives = g_slist_remove (this->perspectives, persp); } +// find an existing perspective whose VPs are equal to those of persp +Box3D::Perspective3D * SPDesktop::find_perspective (Box3D::Perspective3D * const persp) +{ + for (GSList *p = this->perspectives; p != NULL; p = p->next) { + if (*((Box3D::Perspective3D *) p->data) == *persp) { + return ((Box3D::Perspective3D *) p->data); + } + } + return NULL; // perspective was not found +} + /** * Return viewbox dimensions. */ diff --git a/src/desktop.h b/src/desktop.h index fa6602651..5f4e2cfab 100644 --- a/src/desktop.h +++ b/src/desktop.h @@ -209,6 +209,7 @@ struct SPDesktop : public Inkscape::UI::View::View // Methods to handle 3D perspective void add_perspective (Box3D::Perspective3D * const persp); void remove_perspective (Box3D::Perspective3D * const persp); + Box3D::Perspective3D * find_perspective (Box3D::Perspective3D * const persp); // find an existing perspective whose VPs are equal to those of persp NR::Rect get_display_area() const; void set_display_area (double x0, double y0, double x1, double y1, double border, bool log = true); diff --git a/src/knotholder.cpp b/src/knotholder.cpp index a24bb1625..d8776cca7 100644 --- a/src/knotholder.cpp +++ b/src/knotholder.cpp @@ -195,7 +195,8 @@ void sp_knot_holder_add_full( * \param p In desktop coordinates. */ -static void knotholder_update_knots(SPKnotHolder *knot_holder, SPItem *item) +//static +void knotholder_update_knots(SPKnotHolder *knot_holder, SPItem *item) { NR::Matrix const i2d(sp_item_i2d_affine(item)); diff --git a/src/knotholder.h b/src/knotholder.h index 971dae3b0..18b6c4165 100644 --- a/src/knotholder.h +++ b/src/knotholder.h @@ -68,6 +68,9 @@ void sp_knot_holder_add_full(SPKnotHolder *knot_holder, GType sp_knot_holder_get_type(); +// For testing. What is the right way to update the knots from Perspective3D::reshape_boxes() ? +void knotholder_update_knots(SPKnotHolder *knot_holder, SPItem *item); + #define SP_TYPE_KNOT_HOLDER (sp_knot_holder_get_type()) #endif /* !__SP_KNOTHOLDER_H__ */ diff --git a/src/perspective3d.cpp b/src/perspective3d.cpp index 27366e564..d4990fd39 100644 --- a/src/perspective3d.cpp +++ b/src/perspective3d.cpp @@ -11,6 +11,7 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ +#include "box3d.h" #include "box3d-context.h" #include "perspective-line.h" #include @@ -18,6 +19,7 @@ // can probably be removed later #include "inkscape.h" +#include "knotholder.h" namespace Box3D { @@ -80,8 +82,10 @@ Perspective3D::Perspective3D (Perspective3D &other) Perspective3D::~Perspective3D () { - g_assert (desktop != NULL); - desktop->remove_perspective (this); + // we can have desktop == NULL when building a box whose attribute "inkscape:perspective" is set + if (desktop != NULL) { + desktop->remove_perspective (this); + } delete vp_x; delete vp_y; @@ -90,6 +94,12 @@ Perspective3D::~Perspective3D () g_slist_free (boxes); } +bool +Perspective3D::operator==(Perspective3D const &other) +{ + // Two perspectives are equal iff their vanishing points coincide and have identical states + return (*vp_x == *other.vp_x && *vp_y == *other.vp_y && *vp_z == *other.vp_z); +} VanishingPoint * Perspective3D::get_vanishing_point (Box3D::Axis const dir) @@ -134,6 +144,30 @@ Perspective3D::set_vanishing_point (Box3D::Axis const dir, VanishingPoint const } } +void +Perspective3D::set_vanishing_point (Box3D::Axis const dir, gdouble pt_x, gdouble pt_y, gdouble dir_x, gdouble dir_y, VPState st) +{ + VanishingPoint *vp; + switch (dir) { + case X: + vp = vp_x; + break; + case Y: + vp = vp_y; + break; + case Z: + vp = vp_z; + break; + case NONE: + // no vanishing point to set + return; + } + + vp->set_pos (pt_x, pt_y); + vp->v_dir = NR::Point (dir_x, dir_y); + vp->state = st; +} + void Perspective3D::add_box (SP3DBox *box) { @@ -160,6 +194,60 @@ Perspective3D::has_box (const SP3DBox *box) return (g_slist_find (this->boxes, box) != NULL); } +/** + * Update the shape of a box after a handle was dragged or a VP was changed, according to the stored ratios. + */ +void +Perspective3D::reshape_boxes (Box3D::Axis axes) +{ + // TODO: Leave the "correct" corner fixed according to which face is supposed to be on front. + NR::Point new_pt; + VanishingPoint *vp; + for (const GSList *i = this->boxes; i != NULL; i = i->next) { + SP3DBox *box = SP_3DBOX (i->data); + if (axes & Box3D::X) { + vp = this->get_vanishing_point (Box3D::X); + new_pt = vp->get_pos() + box->ratio_x * (box->corners[3] - vp->get_pos()); + sp_3dbox_move_corner_in_XY_plane (box, 2, new_pt); + } + if (axes & Box3D::Y) { + vp = this->get_vanishing_point (Box3D::Y); + new_pt = vp->get_pos() + box->ratio_y * (box->corners[0] - vp->get_pos()); + sp_3dbox_move_corner_in_XY_plane (box, 2, new_pt); + } + if (axes & Box3D::Z) { + vp = this->get_vanishing_point (Box3D::Z); + new_pt = vp->get_pos() + box->ratio_z * (box->corners[0] - vp->get_pos()); + sp_3dbox_move_corner_in_Z_direction (box, 4, new_pt); + } + + sp_3dbox_set_shape (box, true); + // FIXME: Is there a way update the knots without accessing the + // statically linked function knotholder_update_knots? + SPEventContext *ec = inkscape_active_event_context(); + g_assert (ec != NULL); + if (ec->shape_knot_holder != NULL) { + knotholder_update_knots(ec->shape_knot_holder, (SPItem *) box); + } + } +} + +void +Perspective3D::update_box_reprs () +{ + for (GSList *i = this->boxes; i != NULL; i = i->next) { + SP_OBJECT(SP_3DBOX (i->data))->updateRepr(SP_OBJECT_WRITE_EXT); + } +} + +// FIXME: We get compiler errors when we try to move the code from sp_3dbox_get_perspective_string to this function +/*** +gchar * +Perspective3D::svg_string () +{ +} +***/ + } // namespace Box3D /* diff --git a/src/perspective3d.h b/src/perspective3d.h index afecb2e48..2cffd3419 100644 --- a/src/perspective3d.h +++ b/src/perspective3d.h @@ -13,6 +13,7 @@ #define SEEN_PERSPECTIVE3D_H #include "vanishing-point.h" +#include "svg/stringstream.h" class SP3DBox; @@ -26,11 +27,16 @@ public: Perspective3D(Perspective3D &other); ~Perspective3D(); + bool operator== (Perspective3D const &other); + VanishingPoint *get_vanishing_point (Box3D::Axis const dir); void set_vanishing_point (Box3D::Axis const dir, VanishingPoint const &pt); + void set_vanishing_point (Box3D::Axis const dir, gdouble pt_x, gdouble pt_y, gdouble dir_x, gdouble dir_y, VPState st); void add_box (SP3DBox *box); void remove_box (const SP3DBox *box); bool has_box (const SP3DBox *box); + void reshape_boxes (Box3D::Axis axes); + void update_box_reprs (); static Perspective3D * current_perspective; // should current_perspective be moved to desktop.h? diff --git a/src/vanishing-point.cpp b/src/vanishing-point.cpp index 20c67cb28..5f40936cf 100644 --- a/src/vanishing-point.cpp +++ b/src/vanishing-point.cpp @@ -45,6 +45,15 @@ VanishingPoint::VanishingPoint(VanishingPoint const &rhs) : NR::Point (rhs) this->v_dir = rhs.v_dir; } +bool VanishingPoint::operator== (VanishingPoint const &other) +{ + // Should we compare the parent perspectives, too? Probably not. + if ((*this)[NR::X] == other[NR::X] && (*this)[NR::Y] == other[NR::Y] + && this->state == other.state && this->v_dir == other.v_dir) { + return true; + } + return false; +} bool VanishingPoint::is_finite() const { diff --git a/src/vanishing-point.h b/src/vanishing-point.h index 85b7434e2..918b27fc7 100644 --- a/src/vanishing-point.h +++ b/src/vanishing-point.h @@ -47,6 +47,14 @@ public: VanishingPoint(NR::Coord x, NR::Coord y, NR::Coord dir_x, NR::Coord dir_y); VanishingPoint(VanishingPoint const &rhs); + bool operator== (VanishingPoint const &other); + + inline NR::Point get_pos() const { return NR::Point ((*this)[NR::X], (*this)[NR::Y]); } + inline void set_pos(NR::Point const &pt) { (*this)[NR::X] = pt[NR::X]; + (*this)[NR::Y] = pt[NR::Y]; } + inline void set_pos(const double pt_x, const double pt_y) { (*this)[NR::X] = pt_x; + (*this)[NR::Y] = pt_y; } + bool is_finite() const; VPState toggle_parallel(); void draw(Box3D::Axis const axis); // Draws a point on the canvas if state == VP_FINITE -- 2.30.2