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) : corner1 (0, 0), corner2 (0, 0), corner3 (0, 0), corner4 (0, 0),
18 dir1 (Box3D::NONE), dir2 (Box3D::NONE), path (NULL), parent_box3d (box3d)
19 {
20 }
22 void Box3DFace::set_shape(NR::Point const ul, NR::Point const lr,
23 Box3D::PerspDir const dir1, Box3D::PerspDir const dir2,
24 unsigned int shift_count, NR::Maybe<NR::Point> pt_align, bool align_along_PL)
25 {
26 corner1 = ul;
27 if (!pt_align) {
28 corner3 = lr;
29 } else {
30 if (align_along_PL) {
31 Box3D::PerspDir dir3;
32 if (dir1 == Box3D::X && dir2 == Box3D::Y) dir3 = Box3D::Z;
33 if (dir1 == Box3D::X && dir2 == Box3D::Z) dir3 = Box3D::Y;
34 if (dir1 == Box3D::Y && dir2 == Box3D::X) dir3 = Box3D::Z;
35 if (dir1 == Box3D::Y && dir2 == Box3D::Z) dir3 = Box3D::X;
36 if (dir1 == Box3D::Z && dir2 == Box3D::X) dir3 = Box3D::Y;
37 if (dir1 == Box3D::Z && dir2 == Box3D::Y) dir3 = Box3D::X;
38 Box3D::Line line1(*SP3DBoxContext::current_perspective->get_vanishing_point(dir1), lr);
39 Box3D::Line line2(*pt_align, *SP3DBoxContext::current_perspective->get_vanishing_point(dir3));
40 corner3 = *line1.intersect(line2);
41 } else {
42 corner3 = Box3D::Line(*pt_align, *SP3DBoxContext::current_perspective->get_vanishing_point(dir1)).closest_to(lr);
43 }
44 }
46 Box3D::PerspectiveLine first_line (corner1, dir1);
47 Box3D::PerspectiveLine second_line (corner3, dir2);
48 NR::Maybe<NR::Point> ur = first_line.intersect(second_line);
50 Box3D::PerspectiveLine third_line (corner1, dir2);
51 Box3D::PerspectiveLine fourth_line (corner3, dir1);
52 NR::Maybe<NR::Point> ll = third_line.intersect(fourth_line);
54 // FIXME: How to handle the case if one of the intersections doesn't exist?
55 // Maybe set them equal to the corresponding VPs?
56 if (!ur) ur = NR::Point(0.0, 0.0);
57 if (!ll) ll = NR::Point(0.0, 0.0);
59 corner2 = *ll;
60 corner4 = *ur;
62 this->dir1 = dir1;
63 this->dir2 = dir2;
65 // FIXME: More effective with array of corners
66 NR::Point tmp_pt;
67 for (unsigned int i=0; i < shift_count; i++) {
68 tmp_pt = corner4;
69 corner2 = corner1;
70 corner3 = corner2;
71 corner4 = corner3;
72 corner1 = tmp_pt;
73 }
74 }
76 Box3DFace::Box3DFace(Box3DFace const &box3dface)
77 {
78 this->corner1 = box3dface.corner1;
79 this->corner2 = box3dface.corner2;
80 this->corner3 = box3dface.corner3;
81 this->corner4 = box3dface.corner4;
82 this->dir1 = box3dface.dir1;
83 this->dir2 = box3dface.dir2;
84 }
86 NR::Point Box3DFace::operator[](unsigned int i)
87 {
88 unsigned int index = i % 4;
89 switch (index) {
90 case 0: return corner1; break;
91 case 1: return corner2; break;
92 case 2: return corner3; break;
93 case 3: return corner4; break;
94 }
95 // The following two lines are just to prevent a compiler warning ("control reaches
96 // end of non-void function); they can be removed if desired
97 g_message ("Error: This code line hould not be reached\n");
98 return NR::Point (0, 0);
99 }
101 /**
102 * Append the curve's path as a child to the given 3D box (since SP3DBox
103 * is derived from SPGroup, so we can append children to its svg representation)
104 */
105 void Box3DFace::hook_path_to_3dbox()
106 {
107 SPDesktop *desktop = inkscape_active_desktop();
108 Inkscape::XML::Document *xml_doc = sp_document_repr_doc(SP_EVENT_CONTEXT_DOCUMENT(inkscape_active_event_context()));
109 Inkscape::XML::Node *repr_face = xml_doc->createElement("svg:path");
110 sp_desktop_apply_style_tool (desktop, repr_face, "tools.shapes.3dbox", false);
111 this->path = SP_PATH(SP_OBJECT(parent_box3d)->appendChildRepr(repr_face));
112 Inkscape::GC::release(repr_face);
113 }
115 /**
116 * Write the path's "d" attribute to the SVG representation.
117 */
118 void Box3DFace::set_path_repr()
119 {
120 SP_OBJECT(this->path)->repr->setAttribute("d", svg_repr_string());
121 }
123 void Box3DFace::set_curve()
124 {
125 SPDocument *doc = SP_OBJECT_DOCUMENT(this->parent_box3d);
126 gdouble height = sp_document_height(doc);
128 SPCurve *curve = sp_curve_new();
129 sp_curve_moveto(curve, corner1[NR::X], height - corner1[NR::Y]);
130 sp_curve_lineto(curve, corner2[NR::X], height - corner2[NR::Y]);
131 sp_curve_lineto(curve, corner3[NR::X], height - corner3[NR::Y]);
132 sp_curve_lineto(curve, corner4[NR::X], height - corner4[NR::Y]);
133 sp_curve_closepath(curve);
134 sp_shape_set_curve(SP_SHAPE(this->path), curve, true);
135 sp_curve_unref(curve);
136 }
138 gchar * Box3DFace::svg_repr_string()
139 {
140 SPDocument *doc = SP_OBJECT_DOCUMENT(this->parent_box3d);
141 gdouble height = sp_document_height(doc);
143 GString *pstring = g_string_new("");
144 g_string_sprintf (pstring, "M %f,%f L %f,%f L %f,%f L %f,%f z",
145 corner1[NR::X], height - corner1[NR::Y],
146 corner2[NR::X], height - corner2[NR::Y],
147 corner3[NR::X], height - corner3[NR::Y],
148 corner4[NR::X], height - corner4[NR::Y]);
149 return pstring->str;
150 }
152 /*
153 Local Variables:
154 mode:c++
155 c-file-style:"stroustrup"
156 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
157 indent-tabs-mode:nil
158 fill-column:99
159 End:
160 */
161 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :