1 #define __SP_3DBOX_FACE_C__
3 /*
4 * Face of a 3D box ('perspectivic rectangle')
5 *
6 * Authors:
7 * Maximilian Albert <Anhalter42@gmx.de>
8 *
9 * Copyright (C) 2007 authors
10 *
11 * Released under GNU GPL, read the file 'COPYING' for more information
12 */
14 #include "box3d-face.h"
15 #include <iostream>
17 Box3DFace::Box3DFace(SP3DBox *box3d) : dir1 (Box3D::NONE), dir2 (Box3D::NONE), path (NULL), parent_box3d (box3d)
18 {
19 for (int i = 0; i < 4; ++i) {
20 this->corners[i] = NR::Point(0, 0);
21 }
22 }
24 void Box3DFace::set_shape(NR::Point const ul, NR::Point const lr,
25 Box3D::Axis const dir1, Box3D::Axis const dir2,
26 unsigned int shift_count, NR::Maybe<NR::Point> pt_align, bool align_along_PL)
27 {
28 corners[0] = ul;
29 if (!pt_align) {
30 corners[2] = lr;
31 } else {
32 if (align_along_PL) {
33 Box3D::Axis dir3 = Box3D::third_axis_direction (dir1, dir2);
34 Box3D::Line line1(*SP3DBoxContext::current_perspective->get_vanishing_point(dir1), lr);
35 Box3D::Line line2(*pt_align, *SP3DBoxContext::current_perspective->get_vanishing_point(dir3));
36 corners[2] = *line1.intersect(line2);
37 } else {
38 corners[2] = Box3D::Line(*pt_align, *SP3DBoxContext::current_perspective->get_vanishing_point(dir1)).closest_to(lr);
39 }
40 }
42 Box3D::PerspectiveLine first_line (corners[0], dir1);
43 Box3D::PerspectiveLine second_line (corners[2], dir2);
44 NR::Maybe<NR::Point> ur = first_line.intersect(second_line);
46 Box3D::PerspectiveLine third_line (corners[0], dir2);
47 Box3D::PerspectiveLine fourth_line (corners[2], dir1);
48 NR::Maybe<NR::Point> ll = third_line.intersect(fourth_line);
50 // FIXME: How to handle the case if one of the intersections doesn't exist?
51 // Maybe set them equal to the corresponding VPs?
52 if (!ur) ur = NR::Point(0.0, 0.0);
53 if (!ll) ll = NR::Point(0.0, 0.0);
55 corners[1] = *ll;
56 corners[3] = *ur;
58 this->dir1 = dir1;
59 this->dir2 = dir2;
61 // FIXME: Can be made more concise
62 NR::Point tmp_pt;
63 for (unsigned int i=0; i < shift_count; i++) {
64 tmp_pt = corners[3];
65 corners[1] = corners[0];
66 corners[2] = corners[1];
67 corners[3] = corners[2];
68 corners[0] = tmp_pt;
69 }
70 }
72 Box3DFace::Box3DFace(Box3DFace const &box3dface)
73 {
74 for (int i = 0; i < 4; ++i) {
75 this->corners[i] = box3dface.corners[i];
76 }
77 this->dir1 = box3dface.dir1;
78 this->dir2 = box3dface.dir2;
79 }
81 NR::Point Box3DFace::operator[](unsigned int i)
82 {
83 return corners[i % 4];
84 }
86 /**
87 * Append the curve's path as a child to the given 3D box (since SP3DBox
88 * is derived from SPGroup, so we can append children to its svg representation)
89 */
90 void Box3DFace::hook_path_to_3dbox()
91 {
92 SPDesktop *desktop = inkscape_active_desktop();
93 Inkscape::XML::Document *xml_doc = sp_document_repr_doc(SP_EVENT_CONTEXT_DOCUMENT(inkscape_active_event_context()));
94 Inkscape::XML::Node *repr_face = xml_doc->createElement("svg:path");
95 sp_desktop_apply_style_tool (desktop, repr_face, "tools.shapes.3dbox", false);
96 this->path = SP_PATH(SP_OBJECT(parent_box3d)->appendChildRepr(repr_face));
97 Inkscape::GC::release(repr_face);
98 }
100 /**
101 * Write the path's "d" attribute to the SVG representation.
102 */
103 void Box3DFace::set_path_repr()
104 {
105 SP_OBJECT(this->path)->repr->setAttribute("d", svg_repr_string());
106 }
108 void Box3DFace::set_curve()
109 {
110 SPDocument *doc = SP_OBJECT_DOCUMENT(this->parent_box3d);
111 gdouble height = sp_document_height(doc);
113 SPCurve *curve = sp_curve_new();
114 sp_curve_moveto(curve, corners[0][NR::X], height - corners[0][NR::Y]);
115 sp_curve_lineto(curve, corners[1][NR::X], height - corners[1][NR::Y]);
116 sp_curve_lineto(curve, corners[2][NR::X], height - corners[2][NR::Y]);
117 sp_curve_lineto(curve, corners[3][NR::X], height - corners[3][NR::Y]);
118 sp_curve_closepath(curve);
119 sp_shape_set_curve(SP_SHAPE(this->path), curve, true);
120 sp_curve_unref(curve);
121 }
123 gchar * Box3DFace::svg_repr_string()
124 {
125 SPDocument *doc = SP_OBJECT_DOCUMENT(this->parent_box3d);
126 gdouble height = sp_document_height(doc);
128 GString *pstring = g_string_new("");
129 g_string_sprintf (pstring, "M %f,%f L %f,%f L %f,%f L %f,%f z",
130 corners[0][NR::X], height - corners[0][NR::Y],
131 corners[1][NR::X], height - corners[1][NR::Y],
132 corners[2][NR::X], height - corners[2][NR::Y],
133 corners[3][NR::X], height - corners[3][NR::Y]);
134 return pstring->str;
135 }
137 /*
138 Local Variables:
139 mode:c++
140 c-file-style:"stroustrup"
141 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
142 indent-tabs-mode:nil
143 fill-column:99
144 End:
145 */
146 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :