Code

Swap axis directions Y and Z (for consistency)
[inkscape.git] / src / box3d-face.cpp
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::PerspDir const dir1, Box3D::PerspDir 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::PerspDir dir3;
34             if (dir1 == Box3D::X && dir2 == Box3D::Z) dir3 = Box3D::Y;
35             if (dir1 == Box3D::X && dir2 == Box3D::Y) dir3 = Box3D::Z;
36             if (dir1 == Box3D::Z && dir2 == Box3D::X) dir3 = Box3D::Y;
37             if (dir1 == Box3D::Z && dir2 == Box3D::Y) dir3 = Box3D::X;
38             if (dir1 == Box3D::Y && dir2 == Box3D::X) dir3 = Box3D::Z;
39             if (dir1 == Box3D::Y && dir2 == Box3D::Z) dir3 = Box3D::X;
40             Box3D::Line line1(*SP3DBoxContext::current_perspective->get_vanishing_point(dir1), lr);
41             Box3D::Line line2(*pt_align, *SP3DBoxContext::current_perspective->get_vanishing_point(dir3));
42             corners[2] = *line1.intersect(line2);
43         } else {
44             corners[2] = Box3D::Line(*pt_align, *SP3DBoxContext::current_perspective->get_vanishing_point(dir1)).closest_to(lr);
45         }
46     }
48     Box3D::PerspectiveLine first_line  (corners[0], dir1);
49     Box3D::PerspectiveLine second_line (corners[2], dir2);
50     NR::Maybe<NR::Point> ur = first_line.intersect(second_line);
52     Box3D::PerspectiveLine third_line  (corners[0], dir2);
53     Box3D::PerspectiveLine fourth_line (corners[2], dir1);
54     NR::Maybe<NR::Point> ll = third_line.intersect(fourth_line);
56     // FIXME: How to handle the case if one of the intersections doesn't exist?
57     //        Maybe set them equal to the corresponding VPs? 
58     if (!ur) ur = NR::Point(0.0, 0.0);    
59     if (!ll) ll = NR::Point(0.0, 0.0);
61     corners[1] = *ll;
62     corners[3] = *ur;
64     this->dir1 = dir1;
65     this->dir2 = dir2;
67     // FIXME: Can be made more concise
68     NR::Point tmp_pt;
69     for (unsigned int i=0; i < shift_count; i++) {
70         tmp_pt = corners[3];
71         corners[1] = corners[0];
72         corners[2] = corners[1];
73         corners[3] = corners[2];
74         corners[0] = tmp_pt;
75     }
76 }
78 Box3DFace::Box3DFace(Box3DFace const &box3dface)
79 {
80     for (int i = 0; i < 4; ++i) {
81         this->corners[i] = box3dface.corners[i];
82     }
83     this->dir1 = box3dface.dir1;
84     this->dir2 = box3dface.dir2;
85 }
87 NR::Point Box3DFace::operator[](unsigned int i)
88 {
89     return corners[i % 4];
90 }
92 /**
93  * Append the curve's path as a child to the given 3D box (since SP3DBox
94  * is derived from SPGroup, so we can append children to its svg representation)
95  */
96 void Box3DFace::hook_path_to_3dbox()
97 {
98     SPDesktop *desktop = inkscape_active_desktop();
99     Inkscape::XML::Document *xml_doc = sp_document_repr_doc(SP_EVENT_CONTEXT_DOCUMENT(inkscape_active_event_context()));
100     Inkscape::XML::Node *repr_face = xml_doc->createElement("svg:path");
101     sp_desktop_apply_style_tool (desktop, repr_face, "tools.shapes.3dbox", false);
102     this->path = SP_PATH(SP_OBJECT(parent_box3d)->appendChildRepr(repr_face));
103     Inkscape::GC::release(repr_face);
106 /**
107  * Write the path's "d" attribute to the SVG representation.
108  */
109 void Box3DFace::set_path_repr()
111     SP_OBJECT(this->path)->repr->setAttribute("d", svg_repr_string());
114 void Box3DFace::set_curve()
116     SPDocument *doc = SP_OBJECT_DOCUMENT(this->parent_box3d);
117     gdouble height = sp_document_height(doc);
119     SPCurve *curve = sp_curve_new();
120     sp_curve_moveto(curve, corners[0][NR::X], height - corners[0][NR::Y]);
121     sp_curve_lineto(curve, corners[1][NR::X], height - corners[1][NR::Y]);
122     sp_curve_lineto(curve, corners[2][NR::X], height - corners[2][NR::Y]);
123     sp_curve_lineto(curve, corners[3][NR::X], height - corners[3][NR::Y]);
124     sp_curve_closepath(curve);
125     sp_shape_set_curve(SP_SHAPE(this->path), curve, true);
126     sp_curve_unref(curve);
129 gchar * Box3DFace::svg_repr_string()
131     SPDocument *doc = SP_OBJECT_DOCUMENT(this->parent_box3d);
132     gdouble height = sp_document_height(doc);
134     GString *pstring = g_string_new("");
135     g_string_sprintf (pstring, "M %f,%f L %f,%f L %f,%f L %f,%f z",
136                                corners[0][NR::X], height - corners[0][NR::Y],
137                                corners[1][NR::X], height - corners[1][NR::Y],
138                                corners[2][NR::X], height - corners[2][NR::Y],
139                                corners[3][NR::X], height - corners[3][NR::Y]);
140     return pstring->str;
143 /*
144   Local Variables:
145   mode:c++
146   c-file-style:"stroustrup"
147   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
148   indent-tabs-mode:nil
149   fill-column:99
150   End:
151 */
152 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :