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