Code

more unreffing temporary styles properly
[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) : 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()
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);
115 /**
116  * Write the path's "d" attribute to the SVG representation.
117  */
118 void Box3DFace::set_path_repr()
120     SP_OBJECT(this->path)->repr->setAttribute("d", svg_repr_string());
123 void Box3DFace::set_curve()
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);
138 gchar * Box3DFace::svg_repr_string()
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;
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 :