1ad910bfad249cd102f31bd320f4380ec2bbcda6
1 #define __PERSPECTIVE3D_C__
3 /*
4 * Class modelling a 3D perspective
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-context.h"
15 #include "perspective-line.h"
16 #include <iostream>
17 #include "desktop.h"
19 // can probably be removed later
20 #include "inkscape.h"
22 namespace Box3D {
24 Perspective3D *
25 get_persp_of_box (const SP3DBox *box)
26 {
27 SPDesktop *desktop = inkscape_active_desktop(); // Should we pass the desktop as an argument?
28 for (GSList *p = desktop->perspectives; p != NULL; p = p->next) {
29 if (((Perspective3D *) p->data)->has_box (box))
30 return (Perspective3D *) p->data;
31 }
32 g_warning ("Stray 3D box!\n");
33 g_assert_not_reached();
34 }
36 /**
37 * Computes the intersection of the two perspective lines from pt1 and pt2 to the respective
38 * vanishing points in the given directions.
39 */
40 // FIXME: This has been moved to a virtual method inside PerspectiveLine; can probably be purged
41 NR::Point
42 perspective_intersection (NR::Point pt1, Box3D::Axis dir1, NR::Point pt2, Box3D::Axis dir2, Perspective3D *persp)
43 {
44 VanishingPoint const *vp1 = persp->get_vanishing_point(dir1);
45 VanishingPoint const *vp2 = persp->get_vanishing_point(dir2);
46 NR::Maybe<NR::Point> meet = Line(pt1, *vp1).intersect(Line(pt2, *vp2));
47 // FIXME: How to handle parallel lines (also depends on the type of the VPs)?
48 if (!meet) { meet = NR::Point (0.0, 0.0); }
49 return *meet;
50 }
52 /**
53 * Find the point on the perspective line from line_pt to the
54 * vanishing point in direction dir that is closest to ext_pt.
55 */
56 NR::Point
57 perspective_line_snap (NR::Point line_pt, Box3D::Axis dir, NR::Point ext_pt, Perspective3D *persp)
58 {
59 return PerspectiveLine(line_pt, dir, persp).closest_to(ext_pt);
60 }
62 Perspective3D::Perspective3D (VanishingPoint const &pt_x, VanishingPoint const &pt_y, VanishingPoint const &pt_z)
63 : desktop (NULL),
64 vp_x (pt_x),
65 vp_y (pt_y),
66 vp_z (pt_z),
67 boxes (NULL)
68 {
69 }
71 Perspective3D::~Perspective3D ()
72 {
73 g_assert (desktop != NULL);
74 desktop->remove_perspective (this);
76 g_slist_free (boxes);
77 }
80 VanishingPoint *
81 Perspective3D::get_vanishing_point (Box3D::Axis const dir)
82 {
83 // FIXME: Also handle value 'NONE' in switch
84 switch (dir) {
85 case X:
86 return &vp_x;
87 break;
88 case Y:
89 return &vp_y;
90 break;
91 case Z:
92 return &vp_z;
93 break;
94 }
95 }
97 void
98 Perspective3D::set_vanishing_point (Box3D::Axis const dir, VanishingPoint const &pt)
99 {
100 switch (dir) {
101 case X:
102 vp_x = pt;
103 break;
104 case Y:
105 vp_y = pt;
106 break;
107 case Z:
108 vp_z = pt;
109 break;
110 case NONE:
111 // no vanishing point to set
112 break;
113 }
114 }
116 void
117 Perspective3D::add_box (SP3DBox *box)
118 {
119 if (g_slist_find (this->boxes, box) != NULL) {
120 // Don't add the same box twice
121 g_warning ("Box already uses the current perspective. We don't add it again.\n");
122 return;
123 }
124 this->boxes = g_slist_append (this->boxes, box);
125 }
127 void
128 Perspective3D::remove_box (const SP3DBox *box)
129 {
130 if (!g_slist_find (this->boxes, box)) {
131 g_warning ("Could not find box that is to be removed in the current perspective.\n");
132 }
133 this->boxes = g_slist_remove (this->boxes, box);
134 }
136 bool
137 Perspective3D::has_box (const SP3DBox *box)
138 {
139 return (g_slist_find (this->boxes, box) != NULL);
140 }
142 } // namespace Box3D
144 /*
145 Local Variables:
146 mode:c++
147 c-file-style:"stroustrup"
148 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
149 indent-tabs-mode:nil
150 fill-column:99
151 End:
152 */
153 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :