diff --git a/src/perspective3d.cpp b/src/perspective3d.cpp
index e5b1f62126f25983d026002cc3a8e5d3fefc3bbc..489e88dfc859d46786ec28cb4872b229b2f90fca 100644 (file)
--- a/src/perspective3d.cpp
+++ b/src/perspective3d.cpp
#include "perspective-line.h"
#include <iostream>
#include "perspective3d.h"
+#include "desktop-handles.h"
// can probably be removed later
#include "inkscape.h"
-#include "knotholder.h"
namespace Box3D {
gint Perspective3D::counter = 0;
-GSList * Perspective3D::perspectives = NULL;
-Perspective3D * Perspective3D::current_perspective = NULL;
-
-Perspective3D *
-get_persp_of_box (const SP3DBox *box)
-{
- for (GSList *p = Perspective3D::perspectives; p != NULL; p = p->next) {
- if (((Perspective3D *) p->data)->has_box (box))
- return (Perspective3D *) p->data;
- }
- g_warning ("Stray 3D box!\n");
- g_assert_not_reached();
-}
-
-Perspective3D *
-get_persp_of_VP (const VanishingPoint *vp)
-{
- Perspective3D *persp;
- for (GSList *p = Perspective3D::perspectives; p != NULL; p = p->next) {
- persp = (Perspective3D *) p->data;
- // we compare the pointers, not the position/state of the VPs; is this correct?
- if (persp->get_vanishing_point (Box3D::X) == vp ||
- persp->get_vanishing_point (Box3D::Y) == vp ||
- persp->get_vanishing_point (Box3D::Z) == vp)
- return persp;
- }
-
- g_warning ("Stray vanishing point!\n");
- g_assert_not_reached();
-}
/**
* Computes the intersection of the two perspective lines from pt1 and pt2 to the respective
perspective_line_snap (NR::Point line_pt, Box3D::Axis dir, NR::Point ext_pt, Perspective3D *persp)
{
return PerspectiveLine(line_pt, dir, persp).closest_to(ext_pt);
-}
+}
-Perspective3D::Perspective3D (VanishingPoint const &pt_x, VanishingPoint const &pt_y, VanishingPoint const &pt_z)
- : boxes (NULL)
+Perspective3D::Perspective3D (VanishingPoint const &pt_x, VanishingPoint const &pt_y, VanishingPoint const &pt_z, SPDocument *doc)
+ : boxes (NULL),
+ document (doc)
{
vp_x = new VanishingPoint (pt_x);
vp_y = new VanishingPoint (pt_y);
vp_z = new VanishingPoint (pt_z);
my_counter = Perspective3D::counter++;
+
+ if (document == NULL) {
+ g_warning ("What to do now?\n");
+ }
}
Perspective3D::Perspective3D (Perspective3D &other)
vp_z = new VanishingPoint (*other.vp_z);
my_counter = Perspective3D::counter++;
+
+ document = other.document;
}
Perspective3D::~Perspective3D ()
{
- Perspective3D::remove_perspective (this);
+ if (document) {
+ document->remove_perspective (this);
+ } else {
+ g_warning ("No document found!\n");
+ }
// Remove the VPs from their draggers
SPEventContext *ec = inkscape_active_event_context();
}
bool
-Perspective3D::operator==(Perspective3D const &other)
+Perspective3D::operator==(Perspective3D const &other) const
{
// 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);
}
+bool
+Perspective3D::has_vanishing_point (VanishingPoint *vp)
+{
+ return (vp == vp_x || vp == vp_y || vp == vp_z);
+}
+
VanishingPoint *
Perspective3D::get_vanishing_point (Box3D::Axis const dir)
{
@@ -187,12 +174,48 @@ Perspective3D::set_vanishing_point (Box3D::Axis const dir, VanishingPoint const
case Z:
(*vp_z) = pt;
break;
- case NONE:
+ default:
// no vanishing point to set
break;
}
}
+void
+Perspective3D::set_infinite_direction (Box3D::Axis axis, NR::Point const dir)
+{
+ Box3D::Axis axis1 = Box3D::get_remaining_axes (axis).first;
+ Box3D::Axis axis2 = Box3D::get_remaining_axes (axis).second;
+ Box3D::VanishingPoint *vp1 = get_vanishing_point (axis1);
+ Box3D::VanishingPoint *vp2 = get_vanishing_point (axis2);
+ if (fabs (Box3D::determinant (vp1->v_dir, dir)) < Box3D::epsilon ||
+ fabs (Box3D::determinant (vp2->v_dir, dir)) < Box3D::epsilon) {
+ // This is an ad-hoc correction; we should fix this more thoroughly
+ double a = NR::atan2 (dir) + 0.01;
+ this->set_infinite_direction (axis, NR::Point (cos (a), sin (a))); // we call this function again in case there is another conflict (which is unlikely, but possible)
+ return;
+ }
+
+ get_vanishing_point (axis)->set_infinite_direction (dir);
+ for (GSList *i = this->boxes; i != NULL; i = i->next) {
+ sp_3dbox_reshape_after_VP_rotation (SP_3DBOX (i->data), axis);
+ sp_3dbox_set_z_orders_later_on (SP_3DBOX (i->data));
+ }
+ update_box_reprs();
+}
+
+void
+Perspective3D::rotate (Box3D::Axis const axis, double const angle, bool const alt_pressed)
+{
+ Box3D::VanishingPoint *vp = get_vanishing_point (axis);
+ if (!vp->is_finite()) {
+ //double add_value = angle;
+ double a = NR::atan2 (vp->v_dir) * 180/M_PI;
+ a += alt_pressed ? 0.5 * ((angle > 0 ) - (angle < 0)) : angle; // the r.h.s. yields +/-0.5 or angle
+ a *= M_PI/180;
+ this->set_infinite_direction (axis, NR::Point (cos (a), sin (a)));
+ }
+}
+
Axis
Perspective3D::get_axis_of_VP (VanishingPoint *vp)
{
@@ -218,7 +241,7 @@ Perspective3D::set_vanishing_point (Box3D::Axis const dir, gdouble pt_x, gdouble
case Z:
vp = vp_z;
break;
- case NONE:
+ default:
// no vanishing point to set
return;
}
}
bool
-Perspective3D::has_box (const SP3DBox *box)
+Perspective3D::has_box (const SP3DBox *box) const
{
return (g_slist_find (this->boxes, box) != NULL);
}
+bool
+Perspective3D::all_boxes_occur_in_list (GSList *boxes_to_do)
+{
+ for (GSList *i = boxes; i != NULL; i = i->next) {
+ if (!g_slist_find (boxes_to_do, i->data)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+GSList *
+Perspective3D::boxes_occurring_in_list (GSList * list_of_boxes)
+{
+ GSList * result = NULL;
+ for (GSList *i = list_of_boxes; i != NULL; i = i->next) {
+ if (this->has_box (SP_3DBOX (i->data))) {
+ result = g_slist_prepend (result, i->data);
+ }
+ }
+ // we reverse so as to retain the same order as in list_of_boxes
+ return g_slist_reverse (result);
+}
+
/**
* Update the shape of a box after a handle was dragged or a VP was changed, according to the stored ratios.
*/
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 (vp->is_finite()) {
+ 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 (vp->is_finite()) {
+ 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);
- }
+ if (vp->is_finite()) {
+ 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::toggle_boxes (Box3D::Axis axis)
+{
+ get_vanishing_point (axis)->toggle_parallel();
+ for (GSList *i = this->boxes; i != NULL; i = i->next) {
+ sp_3dbox_reshape_after_VP_toggling (SP_3DBOX (i->data), axis);
+ }
+ update_box_reprs();
+
+ SP3DBoxContext *bc = SP_3DBOX_CONTEXT (inkscape_active_event_context());
+ bc->_vpdrag->updateDraggers ();
+}
+
void
Perspective3D::update_box_reprs ()
{
}
}
-// 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 ()
+void
+Perspective3D::update_z_orders ()
{
+ for (GSList *i = this->boxes; i != NULL; i = i->next) {
+ sp_3dbox_set_z_orders_later_on (SP_3DBOX (i->data));
+ }
}
-***/
-void
-Perspective3D::add_perspective (Box3D::Perspective3D * const persp)
+/* the direction from a point pt towards the specified vanishing point of the perspective */
+NR::Point
+Perspective3D::direction (NR::Point pt, Box3D::Axis axis)
{
- // 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 (Perspective3D::perspectives, persp)) return;
- Perspective3D::perspectives = g_slist_prepend (Perspective3D::perspectives, persp);
+ Box3D::VanishingPoint *vp = this->get_vanishing_point (axis);
+ if (!vp->is_finite()) {
+ return vp->v_dir;
+ }
+ return (vp->get_pos() - pt);
}
+// swallow the list of boxes from the other perspective and delete it
void
-Perspective3D::remove_perspective (Box3D::Perspective3D * const persp)
+Perspective3D::absorb (Perspective3D *other)
{
- if (persp == NULL || !g_slist_find (Perspective3D::perspectives, persp)) return;
- Perspective3D::perspectives = g_slist_remove (Perspective3D::perspectives, persp);
+ g_return_if_fail (*this == *other);
+
+ // FIXME: Is copying necessary? Is other->boxes invalidated when other is deleted below?
+ this->boxes = g_slist_concat (this->boxes, g_slist_copy (other->boxes));
+
+ // Should we delete the other perspective here or at the place from where absorb() is called?
+ delete other;
+ other = NULL;
}
-// find an existing perspective whose VPs are equal to those of persp
-Box3D::Perspective3D *
-Perspective3D::find_perspective (Box3D::Perspective3D * const persp)
+// 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 ()
{
- for (GSList *p = Perspective3D::perspectives; p != NULL; p = p->next) {
- if (*((Box3D::Perspective3D *) p->data) == *persp) {
- return ((Box3D::Perspective3D *) p->data);
- }
- }
- return NULL; // perspective was not found
}
+***/
void
Perspective3D::print_debugging_info ()
{
g_print ("====================================================\n");
- for (GSList *i = Perspective3D::perspectives; i != NULL; i = i->next) {
+ for (GSList *i = sp_desktop_document (inkscape_active_desktop())->perspectives; i != NULL; i = i->next) {
Perspective3D *persp = (Perspective3D *) i->data;
g_print ("Perspective %d:\n", persp->my_counter);
if (j != NULL) {
g_print ("%d", SP_3DBOX (j->data)->my_counter);
}
+ g_print ("\n");
}
+ g_print ("\n");
}
- g_print ("\n====================================================\n");
+ g_print ("====================================================\n");
}
-} // namespace Box3D
-
+} // namespace Box3D
+
/*
Local Variables:
mode:c++