diff --git a/src/box3d-face.cpp b/src/box3d-face.cpp
index d038de84f1f6442a49a37b6489e18932c8407a4e..2cb510277da99f2a730d1fad357d4748f551192b 100644 (file)
--- a/src/box3d-face.cpp
+++ b/src/box3d-face.cpp
#include "box3d-face.h"
#include <iostream>
-Box3DFace::Box3DFace(SP3DBox *box3d) : dir1 (Box3D::NONE), dir2 (Box3D::NONE), path (NULL), parent_box3d (box3d)
+// FIXME: It's quite redundant to pass the box plus the corners plus the axes. At least the corners can
+// theoretically be reconstructed from the box and the axes, but in order to do this we need
+// access to box->corners, which is not possible if we only have a forward declaration of SP3DBox
+// in box3d-face.h. (But we can't include box3d.h itself because the latter already includes
+// box3d-face.h).
+Box3DFace::Box3DFace(SP3DBox *box, NR::Point &A, NR::Point &B, NR::Point &C, NR::Point &D,
+ Box3D::Axis plane, Box3D::FrontOrRear rel_pos)
+ : front_or_rear (rel_pos), path (NULL), parent_box3d (box)
+ {
+ dir1 = extract_first_axis_direction (plane);
+ dir2 = extract_second_axis_direction (plane);
+ /*
+ Box3D::Axis axis = (rel_pos == Box3D::FRONT ? Box3D::NONE : Box3D::third_axis_direction (plane));
+ set_corners (box->corners[axis],
+ box->corners[axis ^ dir1],
+ box->corners[axis ^ dir1 ^ dir2],
+ box->corners[axis ^ dir2]);
+ */
+ set_corners (A, B, C, D);
+}
+
+Box3DFace::~Box3DFace()
{
for (int i = 0; i < 4; ++i) {
- this->corners[i] = NR::Point(0, 0);
+ if (this->corners[i]) {
+ //delete this->corners[i];
+ this->corners[i] = NULL;
+ }
}
}
+void Box3DFace::set_corners(NR::Point &A, NR::Point &B, NR::Point &C, NR::Point &D)
+{
+ corners[0] = &A;
+ corners[1] = &B;
+ corners[2] = &C;
+ corners[3] = &D;
+}
+
+/***
void Box3DFace::set_shape(NR::Point const ul, NR::Point const lr,
Box3D::Axis const dir1, Box3D::Axis const dir2,
unsigned int shift_count, NR::Maybe<NR::Point> pt_align, bool align_along_PL)
corners[0] = tmp_pt;
}
}
+***/
Box3DFace::Box3DFace(Box3DFace const &box3dface)
{
this->dir2 = box3dface.dir2;
}
+/**
+ * Construct a 3D box face with opposite corners A and C whose sides are directed
+ * along axis1 and axis2. The corners have the following order:
+ *
+ * A = corners[0] --> along axis1 --> B = corners[1] --> along axis2 --> C = corners[2]
+ * --> along axis1 --> D = corners[3] --> along axis2 --> D = corners[0].
+ *
+ * Note that several other functions rely on this precise order.
+ */
+void
+Box3DFace::set_face (NR::Point const A, NR::Point const C, Box3D::Axis const axis1, Box3D::Axis const axis2)
+{
+ *corners[0] = A;
+ *corners[2] = C;
+ if (!SP_IS_3DBOX_CONTEXT(inkscape_active_event_context()))
+ return;
+ SP3DBoxContext *bc = SP_3DBOX_CONTEXT(inkscape_active_event_context());
+
+ Box3D::PerspectiveLine line1 (A, axis1);
+ Box3D::PerspectiveLine line2 (C, axis2);
+ NR::Maybe<NR::Point> B = line1.intersect(line2);
+
+ Box3D::PerspectiveLine line3 (*corners[0], axis2);
+ Box3D::PerspectiveLine line4 (*corners[2], axis1);
+ NR::Maybe<NR::Point> D = line3.intersect(line4);
+
+ // FIXME: How to handle the case if one of the intersections doesn't exist?
+ // Maybe set them equal to the corresponding VPs?
+ if (!D) D = NR::Point(0.0, 0.0);
+ if (!B) B = NR::Point(0.0, 0.0);
+
+ *corners[1] = *B;
+ *corners[3] = *D;
+
+ this->dir1 = axis1;
+ this->dir2 = axis2;
+}
+
+
NR::Point Box3DFace::operator[](unsigned int i)
{
- return corners[i % 4];
+ return *corners[i % 4];
}
+
+
/**
* Append the curve's path as a child to the given 3D box (since SP3DBox
* is derived from SPGroup, so we can append children to its svg representation)
*/
-void Box3DFace::hook_path_to_3dbox()
+void Box3DFace::hook_path_to_3dbox(SPPath * existing_path)
{
+ if (this->path) {
+ //g_print ("Path already exists. Returning ...\n");
+ return;
+ }
+
+ if (existing_path != NULL) {
+ // no need to create a new path
+ this->path = existing_path;
+ return;
+ }
+
SPDesktop *desktop = inkscape_active_desktop();
- Inkscape::XML::Document *xml_doc = sp_document_repr_doc(SP_EVENT_CONTEXT_DOCUMENT(inkscape_active_event_context()));
+ Inkscape::XML::Document *xml_doc = sp_document_repr_doc(SP_OBJECT_DOCUMENT(SP_OBJECT(parent_box3d)));
+ GString *pstring = g_string_new("");
+ g_string_printf (pstring, "tools.shapes.3dbox.%s", axes_string());
+
Inkscape::XML::Node *repr_face = xml_doc->createElement("svg:path");
- sp_desktop_apply_style_tool (desktop, repr_face, "tools.shapes.3dbox", false);
+ sp_desktop_apply_style_tool (desktop, repr_face, pstring->str, false);
this->path = SP_PATH(SP_OBJECT(parent_box3d)->appendChildRepr(repr_face));
Inkscape::GC::release(repr_face);
}
void Box3DFace::set_curve()
{
- SPDocument *doc = SP_OBJECT_DOCUMENT(this->parent_box3d);
- gdouble height = sp_document_height(doc);
-
+ if (this->path == NULL) {
+ g_warning("this->path is NULL! \n");
+ return;
+ }
+ NR::Matrix const i2d (sp_item_i2d_affine (SP_ITEM (this->parent_box3d)));
SPCurve *curve = sp_curve_new();
- sp_curve_moveto(curve, corners[0][NR::X], height - corners[0][NR::Y]);
- sp_curve_lineto(curve, corners[1][NR::X], height - corners[1][NR::Y]);
- sp_curve_lineto(curve, corners[2][NR::X], height - corners[2][NR::Y]);
- sp_curve_lineto(curve, corners[3][NR::X], height - corners[3][NR::Y]);
+ sp_curve_moveto(curve, (*corners[0]) * i2d);
+ sp_curve_lineto(curve, (*corners[1]) * i2d);
+ sp_curve_lineto(curve, (*corners[2]) * i2d);
+ sp_curve_lineto(curve, (*corners[3]) * i2d);
sp_curve_closepath(curve);
sp_shape_set_curve(SP_SHAPE(this->path), curve, true);
sp_curve_unref(curve);
}
-gchar * Box3DFace::svg_repr_string()
+gchar * Box3DFace::axes_string()
{
- SPDocument *doc = SP_OBJECT_DOCUMENT(this->parent_box3d);
- gdouble height = sp_document_height(doc);
+ GString *pstring = g_string_new("");
+ g_string_printf (pstring, "%s", Box3D::string_from_axes ((Box3D::Axis) (dir1 ^ dir2)));
+ switch ((Box3D::Axis) (dir1 ^ dir2)) {
+ case Box3D::XY:
+ g_string_append_printf (pstring, (front_or_rear == Box3D::FRONT) ? "front" : "rear");
+ break;
+ case Box3D::XZ:
+ g_string_append_printf (pstring, (front_or_rear == Box3D::FRONT) ? "top" : "bottom");
+ break;
+ case Box3D::YZ:
+ g_string_append_printf (pstring, (front_or_rear == Box3D::FRONT) ? "right" : "left");
+ break;
+ default:
+ break;
+ }
+ return pstring->str;
+}
+gchar * Box3DFace::svg_repr_string()
+{
+ NR::Matrix const i2d (sp_item_i2d_affine (SP_ITEM (this->parent_box3d)));
GString *pstring = g_string_new("");
- g_string_sprintf (pstring, "M %f,%f L %f,%f L %f,%f L %f,%f z",
- corners[0][NR::X], height - corners[0][NR::Y],
- corners[1][NR::X], height - corners[1][NR::Y],
- corners[2][NR::X], height - corners[2][NR::Y],
- corners[3][NR::X], height - corners[3][NR::Y]);
+ g_string_printf (pstring, "M %f,%f L %f,%f L %f,%f L %f,%f z",
+ ((*corners[0]) * i2d)[NR::X], ((*corners[0]) * i2d)[NR::Y],
+ ((*corners[1]) * i2d)[NR::X], ((*corners[1]) * i2d)[NR::Y],
+ ((*corners[2]) * i2d)[NR::X], ((*corners[2]) * i2d)[NR::Y],
+ ((*corners[3]) * i2d)[NR::X], ((*corners[3]) * i2d)[NR::Y]);
return pstring->str;
}