[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-commits
Subject:    [Calligra] a9be43f: implement perspective value calculation
From:       Geoffry Song <goffrie () gmail ! com>
Date:       2010-12-31 23:27:34
Message-ID: 20101231232734.28C4AA6092 () git ! kde ! org
[Download RAW message or body]


	A	 krita/ui/kis_abstract_perspective_grid.h	 [License: UNKNOWN]

commit a9be43f3a1d52b80bfa461a9c851c22064d215c7
Author: Geoffry Song <goffrie@gmail.com>
Date:   Wed Dec 29 21:50:06 2010 -0500

    implement perspective value calculation

diff --git a/krita/plugins/assistants/RulerAssistant/PerspectiveAssistant.cc \
b/krita/plugins/assistants/RulerAssistant/PerspectiveAssistant.cc index \
                0442ded..95d1106 100644
--- a/krita/plugins/assistants/RulerAssistant/PerspectiveAssistant.cc
+++ b/krita/plugins/assistants/RulerAssistant/PerspectiveAssistant.cc
@@ -28,8 +28,8 @@
 #include "kis_coordinates_converter.h"
 
 #include <math.h>
-
 #include <limits>
+#include <algorithm>
 
 PerspectiveAssistant::PerspectiveAssistant()
         : KisPaintingAssistant("perspective", i18n("Perspective assistant"))
@@ -104,6 +104,51 @@ void PerspectiveAssistant::endStroke()
     snapLine = QLineF();
 }
 
+bool PerspectiveAssistant::contains(const QPointF& pt) const
+{
+    QPolygonF poly;
+    if (!quad(poly)) return false;
+    return poly.containsPoint(pt, Qt::OddEvenFill);
+}
+
+inline qreal lengthSquared(const QPointF& vector)
+{
+    return vector.x() * vector.x() + vector.y() * vector.y();
+}
+
+inline qreal distanceSquared(const QTransform& transform, QPointF pt, QPointF orig)
+{
+    const qreal epsilon = 1e-5, epsilonSquared = epsilon * epsilon;
+    qreal xSizeSquared = lengthSquared(transform.map(pt + QPointF(epsilon, 0.0)) - \
orig) / epsilonSquared; +    qreal ySizeSquared = lengthSquared(transform.map(pt + \
QPointF(0.0, epsilon)) - orig) / epsilonSquared; +    xSizeSquared /= \
lengthSquared(transform.map(QPointF(0.0, pt.y())) - transform.map(QPointF(1.0, \
pt.y()))); +    ySizeSquared /= lengthSquared(transform.map(QPointF(pt.x(), 0.0)) - \
transform.map(QPointF(pt.x(), 1.0))); +    return xSizeSquared + ySizeSquared;
+}
+
+qreal PerspectiveAssistant::distance(const QPointF& pt) const
+{
+    QPolygonF poly;
+    if (!quad(poly)) return 1.0;
+    QTransform transform;
+    if (!QTransform::squareToQuad(poly, transform)) return 1.0;
+    bool invertible;
+    QTransform inverse = transform.inverted(&invertible);
+    if (!invertible) return 1.0;
+    if (inverse.m13() * pt.x() + inverse.m23() * pt.y() + inverse.m33() == 0.0) {
+        // point at infinity
+        return 0.0;
+    }
+    QPointF realPoint = inverse.map(pt);
+    const qreal corners[4] = {
+        distanceSquared(transform, QPointF(0.0, 0.0), transform.map(QPointF(0.0, \
0.0))), +        distanceSquared(transform, QPointF(0.0, 1.0), \
transform.map(QPointF(0.0, 1.0))), +        distanceSquared(transform, QPointF(1.0, \
0.0), transform.map(QPointF(1.0, 0.0))), +        distanceSquared(transform, \
QPointF(1.0, 1.0), transform.map(QPointF(1.0, 1.0)))}; +    const qreal max = \
std::max(std::max(corners[0], corners[1]), std::max(corners[2], corners[3])); +    \
return sqrt(distanceSquared(transform, realPoint, pt) / max); +}
+
 // draw a vanishing point marker
 inline void drawX(QPainter& gc, const QPointF& pt)
 {
diff --git a/krita/plugins/assistants/RulerAssistant/PerspectiveAssistant.h \
b/krita/plugins/assistants/RulerAssistant/PerspectiveAssistant.h index \
                4048f0d..19fea0e 100644
--- a/krita/plugins/assistants/RulerAssistant/PerspectiveAssistant.h
+++ b/krita/plugins/assistants/RulerAssistant/PerspectiveAssistant.h
@@ -19,12 +19,13 @@
 #ifndef _PERSPECTIVE_ASSISTANT_H_
 #define _PERSPECTIVE_ASSISTANT_H_
 
+#include "kis_abstract_perspective_grid.h"
 #include "kis_painting_assistant.h"
 #include <QObject>
 #include <QPolygonF>
 #include <QLineF>
 
-class PerspectiveAssistant : public KisPaintingAssistant
+class PerspectiveAssistant : public KisPaintingAssistant, public \
KisAbstractPerspectiveGrid  {
 public:
     PerspectiveAssistant();
@@ -33,6 +34,9 @@ public:
     void drawAssistant(QPainter& gc, const QRectF& updateRect, const \
KisCoordinatesConverter *converter);  virtual QPointF buttonPosition() const;
     virtual int numHandles() const { return 4; }
+
+    virtual bool contains(const QPointF& point) const;
+    virtual qreal distance(const QPointF& point) const;
 private:
     QPointF project(const QPointF& pt, const QPointF& strokeBegin);
     // creates the convex hull, returns false if it's not a quadrilateral
diff --git a/krita/ui/kis_abstract_perspective_grid.h \
b/krita/ui/kis_abstract_perspective_grid.h new file mode 100644
index 0000000..864b482
--- /dev/null
+++ b/krita/ui/kis_abstract_perspective_grid.h
@@ -0,0 +1,38 @@
+/*
+ * This file is part of Krita
+ *
+ *  Copyright (c) 2010 Geoffry Song <goffrie@gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef KIS_ABSTRACT_PERSPECTIVE_GRID_H
+#define KIS_ABSTRACT_PERSPECTIVE_GRID_H
+
+#include <QPointF>
+
+class KisAbstractPerspectiveGrid
+{
+public:
+    virtual bool contains(const QPointF& pt) const = 0;
+    /**
+     * Returns the reciprocal of the distance from the given point
+     * to the 'observer', in the range [0, 1] where 0 = inifinite
+     * distance and 1 = closest.
+     */
+    virtual qreal distance(const QPointF& pt) const = 0;
+};
+
+#endif
diff --git a/krita/ui/tool/kis_tool_freehand.cc b/krita/ui/tool/kis_tool_freehand.cc
index 702c6dc..2359aea 100644
--- a/krita/ui/tool/kis_tool_freehand.cc
+++ b/krita/ui/tool/kis_tool_freehand.cc
@@ -48,6 +48,7 @@
 
 
 // Krita/ui
+#include "kis_abstract_perspective_grid.h"
 #include "kis_config.h"
 #include <opengl/kis_opengl.h>
 #include "canvas/kis_canvas2.h"
@@ -141,10 +142,19 @@ void KisToolFreehand::mousePressEvent(KoPointerEvent *e)
      * FIXME: we need some better way to implement modifiers
      * for a paintop level
      */
+    QPointF pos = adjustPosition(e->point, e->point);
+    qreal perspective = 1.0;
+    foreach (const KisPaintingAssistant* assistant, \
static_cast<KisCanvas2*>(canvas())->view()->paintingAssistantManager()->assistants()) \
{ +        const KisAbstractPerspectiveGrid* perspectiveGrid = dynamic_cast<const \
KisAbstractPerspectiveGrid*>(assistant); +        if (!perspectiveGrid) continue;
+        if (!perspectiveGrid->contains(pos)) continue;
+        perspective = perspectiveGrid->distance(pos);
+        break;
+    }
     bool ignoreEvent = \
currentPaintOpPreset()->settings()->mousePressEvent(KisPaintInformation(convertToPixelCoord(e->point),
                
                                                          \
                pressureToCurve(e->pressure()), e->xTilt(), e->yTilt(),
                                                          KisVector2D::Zero(),
-                                                         e->rotation(), \
e->tangentialPressure(), 1.0, m_strokeTimeMeasure.elapsed()),e->modifiers()); +       \
e->rotation(), e->tangentialPressure(), perspective, \
m_strokeTimeMeasure.elapsed()),e->modifiers());  if (!ignoreEvent){
         e->accept();
         return;
@@ -168,7 +178,7 @@ void KisToolFreehand::mousePressEvent(KoPointerEvent *e)
         m_previousPaintInformation = \
                KisPaintInformation(convertToPixelCoord(adjustPosition(e->point, \
                e->point)),
                                                          \
                pressureToCurve(e->pressure()), e->xTilt(), e->yTilt(),
                                                          KisVector2D::Zero(),
-                                                         e->rotation(), \
e->tangentialPressure(), 1.0, m_strokeTimeMeasure.elapsed()); +                       \
e->rotation(), e->tangentialPressure(), perspective, m_strokeTimeMeasure.elapsed());  \
m_strokeBegin = e->point;  
         e->accept();
@@ -212,13 +222,23 @@ void KisToolFreehand::mouseMoveEvent(KoPointerEvent *e)
     /**
      * Actual painting
      */
-    QPointF pos = convertToPixelCoord(adjustPosition(e->point, m_strokeBegin));
+    QPointF adjusted = adjustPosition(e->point, m_strokeBegin);
+    QPointF pos = convertToPixelCoord(adjusted);
     QPointF dragVec = pos - m_previousPaintInformation.pos();
 
+    qreal perspective = 1.0;
+    foreach (const KisPaintingAssistant* assistant, \
static_cast<KisCanvas2*>(canvas())->view()->paintingAssistantManager()->assistants()) \
{ +        const KisAbstractPerspectiveGrid* perspectiveGrid = dynamic_cast<const \
KisAbstractPerspectiveGrid*>(assistant); +        if (!perspectiveGrid) continue;
+        if (!perspectiveGrid->contains(adjusted)) continue;
+        perspective = perspectiveGrid->distance(adjusted);
+        break;
+    }
+
     KisPaintInformation info =
         KisPaintInformation(pos, pressureToCurve(e->pressure()),
                             e->xTilt(), e->yTilt(), toKisVector2D(dragVec),
-                            e->rotation(), e->tangentialPressure(), 1.0,
+                            e->rotation(), e->tangentialPressure(), perspective,
                             m_strokeTimeMeasure.elapsed());
 
     if (m_smooth) {


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic