Code

Refactoring SPColor to C++ and removing legacy CMYK implementation
[inkscape.git] / src / box3d.cpp
index 8df5c3b52bd9b975a3cdb048185434aa9a8a4301..ff00a795c57505d50c8475fa83ed835cd16e4740 100644 (file)
@@ -234,7 +234,15 @@ sp_3dbox_update(SPObject *object, SPCtx *ctx, guint flags)
 {
     if (flags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG | SP_OBJECT_VIEWPORT_MODIFIED_FLAG)) {
         SP3DBox *box = SP_3DBOX(object);
-        sp_3dbox_link_to_existing_paths (box, SP_OBJECT_REPR(object));
+        Inkscape::XML::Node *repr = SP_OBJECT_REPR(object);
+        sp_3dbox_link_to_existing_paths (box, repr);
+        SPEventContext *ec = inkscape_active_event_context();
+        if (SP_IS_3DBOX_CONTEXT (ec)) {
+            SP_3DBOX_CONTEXT (ec)->_vpdrag->updateDraggers();
+            // FIXME: Should we update the corners here, too? Maybe this is the reason why the handles
+            //        are off after an undo/redo! On the other hand, if we do so we get warnings about
+            //        updates occuring while other updats are in progress ...
+        }
     }
 
     /* Invoke parent method */
@@ -242,8 +250,6 @@ sp_3dbox_update(SPObject *object, SPCtx *ctx, guint flags)
         ((SPObjectClass *) (parent_class))->update(object, ctx, flags);
 }
 
-
-
 static Inkscape::XML::Node *sp_3dbox_write(SPObject *object, Inkscape::XML::Node *repr, guint flags)
 {
     SP3DBox *box = SP_3DBOX(object);
@@ -666,24 +672,24 @@ static bool sp_3dbox_recompute_z_orders_by_corner_configuration (SP3DBox *box)
                 guint visible_front_corner = (((c_cmp & front_rear_axis) == (c1 & front_rear_axis)) ? c1 : c2);
                 visible_faces = sp_3dbox_faces_meeting_in_corner (visible_front_corner);
             } else {
-                g_print ("Warning: Unhandled case. Current z-orders remain unchanged.\n");
+                /* Under what conditions do we end up here? Can we safely ignore this case? */
                 return false;
             }
             break;
         }
 
         default:
-            g_print ("Warning: Unhandled case. Current z-orders are not changed.\n");
+            /* Under what conditions do we end up here? Can we safely ignore this case? */
             return false;
     }
 
-    // check for weird corner configurations that cannot be handled by the above code
+    /* catch weird corner configurations; these should be theoretically impossible, but maybe
+       occur in (almost) degenerate cases due to rounding errors, for example */
     if (std::find (visible_faces.begin(), visible_faces.end(), -1) != visible_faces.end()) {
-        g_warning ("Theoretically impossible corner configuration\n");
         return false;
     }
 
-    // sort the list of visible faces for later use (although it may be already sorted anyway)
+    /* sort the list of visible faces for later use (although it may be already sorted anyway) */
     std::sort (visible_faces.begin(), visible_faces.end());
 
     std::vector<gint> invisible_faces;
@@ -695,9 +701,8 @@ static bool sp_3dbox_recompute_z_orders_by_corner_configuration (SP3DBox *box)
         std::swap (visible_faces, invisible_faces);
         if (!sp_3dbox_is_subset_or_superset (visible_faces, box->currently_visible_faces) &&
             !sp_3dbox_differ_by_opposite_faces (visible_faces, box->currently_visible_faces)) {
-            // FIXME: Hopefully this case is only caused by rounding errors or something similar;
-            //        does it need further investigation?
-            g_warning ("Can't find out which faces are visible and which aren't ...\n");
+            /* Hopefully this case is only caused by rounding errors or something similar;
+               does it need further investigation? */
             return false;
         }
     }
@@ -801,6 +806,23 @@ sp_3dbox_link_to_existing_paths (SP3DBox *box, Inkscape::XML::Node *repr) {
     }
 }
 
+void
+sp_3dbox_reshape_after_VP_rotation (SP3DBox *box, Box3D::Axis axis)
+{
+    Box3D::Perspective3D *persp = inkscape_active_document()->get_persp_of_box (box);
+    Box3D::VanishingPoint *vp = persp->get_vanishing_point (axis);
+
+    guint c1 = (axis == Box3D::Z) ? 1 : sp_3dbox_get_front_corner_id (box); // hack
+    guint c2 = c1 ^ axis;
+    NR::Point v = box->corners[c1] - box->corners[c2];
+    double dist = NR::L2 (v) * ((NR::dot (v, vp->v_dir) < 0) ? 1 : -1); // "directed" distance
+
+    Box3D::PerspectiveLine pline (box->corners[c1], axis, persp);
+    NR::Point pt = pline.point_from_lambda (dist);
+
+    sp_3dbox_move_corner_in_Z_direction (box, c2, pt, axis == Box3D::Z);
+}
+
 void
 sp_3dbox_move_corner_in_XY_plane (SP3DBox *box, guint id, NR::Point pt, Box3D::Axis axes)
 {
@@ -1022,6 +1044,9 @@ sp_3dbox_new_midpoints (Box3D::Perspective3D *persp, Box3D::Axis axis, NR::Point
         // FIXME: cr == 1 is a degenerate case; how should we deal with it?
         return std::make_pair (NR::Point (0,0), NR::Point (0,0));
     }
+    if (cr1 == NR_HUGE) {
+        return std::make_pair (A, B);
+    }
     Box3D::PerspectiveLine pl (M0, axis, persp);
     NR::Point B_new = pl.pt_with_given_cross_ratio (M0, M, cr1 / (cr1 - 1));
     NR::Point A_new = pl.pt_with_given_cross_ratio (M0, M, 1 - cr2);