[calligra/calligra/2.9] krita: Adding a Fish Eye Vanishing Point assistant.

Wolthera van Hovell griffinvalley at gmail.com
Mon Jun 8 16:47:32 UTC 2015


Git commit aa07868288b87687cd6bcdf56ed26a27ba55bda2 by Wolthera van Hovell.
Committed on 08/06/2015 at 16:47.
Pushed by woltherav into branch 'calligra/2.9'.

Adding a Fish Eye Vanishing Point assistant.

This adds the ability to draw perspective that look lens-deformed.
Like the vanishing point assistant, this assistant is per a set of parallel
lines in a 3d space. So to use it effectively, use two, where the second is at
a 90 degree angle of the first, and add a vanishing point to the center of
both. Or combine one with a parallel ruler and a vanishing point, or even
one with two vanishing points. The possibilities are quite large.

This assistant will not just give feedback/snapping between the vanishing
points, but also give feedback to the relative left and right of the assistant.
This is so you can use it in edge-cases like panoramas with relative ease.

Confirmed to work and to save and load, have fun!

CCMAIL:kimageshop at kde.org

M  +1    -0    krita/plugins/assistants/RulerAssistant/CMakeLists.txt
A  +216  -0    krita/plugins/assistants/RulerAssistant/FisheyePointAssistant.cc     [License: LGPL]
A  +59   -0    krita/plugins/assistants/RulerAssistant/FisheyePointAssistant.h     [License: LGPL]
M  +2    -0    krita/plugins/assistants/RulerAssistant/ruler_assistant_tool.cc
M  +6    -0    krita/ui/kis_painting_assistant.cc
M  +5    -1    krita/ui/kra/kis_kra_saver.cpp

http://commits.kde.org/calligra/aa07868288b87687cd6bcdf56ed26a27ba55bda2

diff --git a/krita/plugins/assistants/RulerAssistant/CMakeLists.txt b/krita/plugins/assistants/RulerAssistant/CMakeLists.txt
index 24a90d5..f90a8bc 100644
--- a/krita/plugins/assistants/RulerAssistant/CMakeLists.txt
+++ b/krita/plugins/assistants/RulerAssistant/CMakeLists.txt
@@ -12,6 +12,7 @@ set(kritarulerassistanttool_PART_SRCS
     ConcentricEllipseAssistant.cc
     ruler_assistant_tool.cc
     kis_ruler_assistant_tool.cc
+    FisheyePointAssistant.cc
     )
 
 kde4_add_ui_files(kritarulerassistanttool_PART_SRCS AssistantsToolOptions.ui )
diff --git a/krita/plugins/assistants/RulerAssistant/FisheyePointAssistant.cc b/krita/plugins/assistants/RulerAssistant/FisheyePointAssistant.cc
new file mode 100644
index 0000000..fb91123
--- /dev/null
+++ b/krita/plugins/assistants/RulerAssistant/FisheyePointAssistant.cc
@@ -0,0 +1,216 @@
+/*
+ * Copyright (c) 2008 Cyrille Berger <cberger at cberger.net>
+ * Copyright (c) 2010 Geoffry Song <goffrie at gmail.com>
+ * Copyright (c) 2014 Wolthera van Hövell tot Westerflier <griffinvalley at gmail.com>
+ *
+ *  This library is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU Lesser General Public License as published by
+ *  the Free Software Foundation; version 2.1 of the License.
+ *
+ *  This library 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 Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser 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.
+ */
+
+#include "FisheyePointAssistant.h"
+
+#include "kis_debug.h"
+#include <klocale.h>
+
+#include <QPainter>
+#include <QLinearGradient>
+#include <QTransform>
+
+#include "kis_coordinates_converter.h"
+#include "kis_algebra_2d.h"
+
+#include <math.h>
+#include <limits>
+
+FisheyePointAssistant::FisheyePointAssistant()
+        : KisPaintingAssistant("fisheye-point", i18n("Fish Eye Point assistant"))
+{
+}
+
+QPointF FisheyePointAssistant::project(const QPointF& pt, const QPointF& strokeBegin)
+{
+    const static QPointF nullPoint(std::numeric_limits<qreal>::quiet_NaN(), std::numeric_limits<qreal>::quiet_NaN());
+    Q_ASSERT(handles().size() == 3);
+    e.set(*handles()[0], *handles()[1], *handles()[2]);
+
+    qreal
+            dx = pt.x() - strokeBegin.x(),
+            dy = pt.y() - strokeBegin.y();
+        if (dx * dx + dy * dy < 4.0) {
+            // allow some movement before snapping
+            return strokeBegin;
+        }
+
+    //set the extrapolation ellipse.
+    if (e.set(*handles()[0], *handles()[1], *handles()[2])){
+        QLineF radius(*handles()[1], *handles()[0]);
+        radius.setAngle(fmod(radius.angle()+180.0,360.0));
+        QLineF radius2(*handles()[0], *handles()[1]);
+        radius2.setAngle(fmod(radius2.angle()+180.0,360.0));
+        if ( extraE.set(*handles()[0], *handles()[1],strokeBegin ) ) {
+            return extraE.project(pt);
+        } else if (extraE.set(radius.p1(), radius.p2(),strokeBegin)) {
+            return extraE.project(pt);
+        } else if (extraE.set(radius2.p1(), radius2.p2(),strokeBegin)){
+            return extraE.project(pt);
+        }   
+    }
+    
+    return nullPoint;
+    
+}
+
+QPointF FisheyePointAssistant::adjustPosition(const QPointF& pt, const QPointF& strokeBegin)
+{
+    return project(pt, strokeBegin);
+}
+
+void FisheyePointAssistant::drawAssistant(QPainter& gc, const QRectF& updateRect, const KisCoordinatesConverter* converter, bool cached, KisCanvas2* canvas, bool assistantVisible, bool previewVisible)
+{
+    gc.save();
+    gc.resetTransform();
+    QPointF delta(0,0);
+    QPointF mousePos(0,0);
+    QPointF endPoint(0,0);//this is the final point that the line is being extended to, we seek it just outside the view port//
+    QPointF otherHandle(0,0);
+    
+    if (canvas){
+        //simplest, cheapest way to get the mouse-position//
+        mousePos= canvas->canvasWidget()->mapFromGlobal(QCursor::pos());
+    }
+    else {
+        //...of course, you need to have access to a canvas-widget for that.//
+        mousePos = QCursor::pos();//this'll give an offset//
+        dbgFile<<"canvas does not exist in ruler, you may have passed arguments incorrectly:"<<canvas;
+    }
+    
+    QTransform initialTransform = converter->documentToWidgetTransform();
+    
+    if (outline()==true && previewVisible==true){
+        if (handles().size() > 2){
+        
+        
+            if (e.set(*handles()[0], *handles()[1], *handles()[2])) {
+                if (extraE.set(*handles()[0], *handles()[1], initialTransform.inverted().map(mousePos))){
+                    gc.setTransform(initialTransform);
+                    gc.setTransform(e.getInverse(), true);
+                    QPainterPath path;
+                    // Draw the ellipse
+                    path.addEllipse(QPointF(0, 0), extraE.semiMajor(), extraE.semiMinor());
+                    drawPreview(gc, path);
+                }
+                QLineF radius(*handles()[1], *handles()[0]);
+                radius.setAngle(fmod(radius.angle()+180.0,360.0));
+                if (extraE.set(radius.p1(), radius.p2(), initialTransform.inverted().map(mousePos))){
+                    gc.setTransform(initialTransform);
+                    gc.setTransform(extraE.getInverse(), true);
+                    QPainterPath path;
+                    // Draw the ellipse
+                    path.addEllipse(QPointF(0, 0), extraE.semiMajor(), extraE.semiMinor());
+                    drawPreview(gc, path);
+                }
+                QLineF radius2(*handles()[0], *handles()[1]);
+                radius2.setAngle(fmod(radius2.angle()+180.0,360.0));
+                if (extraE.set(radius2.p1(), radius2.p2(), initialTransform.inverted().map(mousePos))){
+                    gc.setTransform(initialTransform);
+                    gc.setTransform(extraE.getInverse(), true);
+                    QPainterPath path;
+                    // Draw the ellipse
+                    path.addEllipse(QPointF(0, 0), extraE.semiMajor(), extraE.semiMinor());
+                    drawPreview(gc, path);
+                }
+                
+            }
+        }
+    }
+    gc.restore();
+    
+    KisPaintingAssistant::drawAssistant(gc, updateRect, converter, cached, canvas, assistantVisible, previewVisible);
+
+}
+
+void FisheyePointAssistant::drawCache(QPainter& gc, const KisCoordinatesConverter *converter, bool assistantVisible)
+{
+    if (assistantVisible==false){return;}
+    
+    QTransform initialTransform = converter->documentToWidgetTransform();
+
+    if (handles().size() == 2) {
+        // just draw the axis
+        gc.setTransform(initialTransform);
+        QPainterPath path;
+        path.moveTo(*handles()[0]);
+        path.lineTo(*handles()[1]);
+        drawPath(gc, path, snapping());
+        return;
+    }
+    if (e.set(*handles()[0], *handles()[1], *handles()[2])) {
+        // valid ellipse
+
+        gc.setTransform(initialTransform);
+        gc.setTransform(e.getInverse(), true);
+        QPainterPath path;
+        //path.moveTo(QPointF(-e.semiMajor(), -e.semiMinor())); path.lineTo(QPointF(e.semiMajor(), -e.semiMinor()));
+        path.moveTo(QPointF(-e.semiMajor(), -e.semiMinor())); path.lineTo(QPointF(-e.semiMajor(), e.semiMinor()));
+        //path.moveTo(QPointF(-e.semiMajor(), e.semiMinor())); path.lineTo(QPointF(e.semiMajor(), e.semiMinor()));
+        path.moveTo(QPointF(e.semiMajor(), -e.semiMinor())); path.lineTo(QPointF(e.semiMajor(), e.semiMinor()));
+        path.moveTo(QPointF(-(e.semiMajor()*3), -e.semiMinor())); path.lineTo(QPointF(-(e.semiMajor()*3), e.semiMinor()));
+        path.moveTo(QPointF((e.semiMajor()*3), -e.semiMinor())); path.lineTo(QPointF((e.semiMajor()*3), e.semiMinor()));
+        path.moveTo(QPointF(-e.semiMajor(), 0)); path.lineTo(QPointF(e.semiMajor(), 0));
+        //path.moveTo(QPointF(0, -e.semiMinor())); path.lineTo(QPointF(0, e.semiMinor()));
+        // Draw the ellipse
+        path.addEllipse(QPointF(0, 0), e.semiMajor(), e.semiMinor());
+        drawPath(gc, path, snapping());
+    }
+    
+}
+
+QRect FisheyePointAssistant::boundingRect() const
+{
+    if (handles().size() != 3) return KisPaintingAssistant::boundingRect();
+    if (e.set(*handles()[0], *handles()[1], *handles()[2])) {
+        return e.boundingRect().adjusted(-(e.semiMajor()*2), -2, (e.semiMajor()*2), 2).toAlignedRect();
+    } else {
+        return QRect();
+    }
+}
+
+QPointF FisheyePointAssistant::buttonPosition() const
+{
+    return (*handles()[0] + *handles()[1]) * 0.5;
+}
+
+
+
+FisheyePointAssistantFactory::FisheyePointAssistantFactory()
+{
+}
+
+FisheyePointAssistantFactory::~FisheyePointAssistantFactory()
+{
+}
+
+QString FisheyePointAssistantFactory::id() const
+{
+    return "fisheye-point";
+}
+
+QString FisheyePointAssistantFactory::name() const
+{
+    return i18n("Fish Eye Point");
+}
+
+KisPaintingAssistant* FisheyePointAssistantFactory::createPaintingAssistant() const
+{
+    return new FisheyePointAssistant;
+}
diff --git a/krita/plugins/assistants/RulerAssistant/FisheyePointAssistant.h b/krita/plugins/assistants/RulerAssistant/FisheyePointAssistant.h
new file mode 100644
index 0000000..8d02a26
--- /dev/null
+++ b/krita/plugins/assistants/RulerAssistant/FisheyePointAssistant.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2008 Cyrille Berger <cberger at cberger.net>
+ * Copyright (c) 2010 Geoffry Song <goffrie at gmail.com>
+ * Copyright (c) 2014 Wolthera van Hövell tot Westerflier <griffinvalley at gmail.com>
+ *
+ *  This library is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU Lesser General Public License as published by
+ *  the Free Software Foundation; version 2.1 of the License.
+ *
+ *  This library 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 Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser 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 _FISHEYEPOINT_ASSISTANT_H_
+#define _FISHEYEPOINT_ASSISTANT_H_
+
+#include "kis_painting_assistant.h"
+#include "Ellipse.h"
+#include <QObject>
+#include <QPolygonF>
+#include <QLineF>
+#include <QTransform>
+//class FisheyePoint;
+
+class FisheyePointAssistant : public KisPaintingAssistant
+{
+public:
+    FisheyePointAssistant();
+    virtual QPointF adjustPosition(const QPointF& point, const QPointF& strokeBegin);
+    //virtual void endStroke();
+    virtual QPointF buttonPosition() const;
+    virtual int numHandles() const { return 3; }
+protected:
+    virtual QRect boundingRect() const;
+    virtual void drawAssistant(QPainter& gc, const QRectF& updateRect, const KisCoordinatesConverter* converter, bool  cached = true,KisCanvas2* canvas=0, bool assistantVisible=true, bool previewVisible=true);
+    virtual void drawCache(QPainter& gc, const KisCoordinatesConverter *converter,  bool assistantVisible=true);
+private:
+    QPointF project(const QPointF& pt, const QPointF& strokeBegin);
+    mutable Ellipse e;
+    mutable Ellipse extraE;
+};
+
+class FisheyePointAssistantFactory : public KisPaintingAssistantFactory
+{
+public:
+    FisheyePointAssistantFactory();
+    virtual ~FisheyePointAssistantFactory();
+    virtual QString id() const;
+    virtual QString name() const;
+    virtual KisPaintingAssistant* createPaintingAssistant() const;
+};
+
+#endif
diff --git a/krita/plugins/assistants/RulerAssistant/ruler_assistant_tool.cc b/krita/plugins/assistants/RulerAssistant/ruler_assistant_tool.cc
index 7aa1c86..11ebc6c 100644
--- a/krita/plugins/assistants/RulerAssistant/ruler_assistant_tool.cc
+++ b/krita/plugins/assistants/RulerAssistant/ruler_assistant_tool.cc
@@ -28,6 +28,7 @@
 #include "InfiniteRulerAssistant.h"
 #include "ParallelRulerAssistant.h"
 #include "ConcentricEllipseAssistant.h"
+#include "FisheyePointAssistant.h"
 //#include "mesh_assistant.h"
 
 K_PLUGIN_FACTORY(RulerAssistantToolFactory, registerPlugin<RulerAssistantToolPlugin>();)
@@ -48,6 +49,7 @@ RulerAssistantToolPlugin::RulerAssistantToolPlugin(QObject *parent, const QVaria
     KisPaintingAssistantFactoryRegistry::instance()->add(new InfiniteRulerAssistantFactory);
     KisPaintingAssistantFactoryRegistry::instance()->add(new ParallelRulerAssistantFactory);
     KisPaintingAssistantFactoryRegistry::instance()->add(new ConcentricEllipseAssistantFactory);
+    KisPaintingAssistantFactoryRegistry::instance()->add(new FisheyePointAssistantFactory);
 //    KisPaintingAssistantFactoryRegistry::instance()->add(new MeshAssistantFactory);
 }
 
diff --git a/krita/ui/kis_painting_assistant.cc b/krita/ui/kis_painting_assistant.cc
index b5a792e..8f4f2a5 100644
--- a/krita/ui/kis_painting_assistant.cc
+++ b/krita/ui/kis_painting_assistant.cc
@@ -418,6 +418,12 @@ void KisPaintingAssistant::saveXmlList(QDomDocument& doc, QDomElement& assistant
         assistantElement.setAttribute("filename", QString("concentric ellipse%1.assistant").arg(count));
         assistantsElement.appendChild(assistantElement);
     }
+    else if (d->id == "fisheye-point"){
+        QDomElement assistantElement = doc.createElement("assistant");
+        assistantElement.setAttribute("type", "fisheye-point");
+        assistantElement.setAttribute("filename", QString("fisheye-point%1.assistant").arg(count));
+        assistantsElement.appendChild(assistantElement);
+    }
     else if (d->id == "ruler"){
         QDomElement assistantElement = doc.createElement("assistant");
         assistantElement.setAttribute("type", "ruler");
diff --git a/krita/ui/kra/kis_kra_saver.cpp b/krita/ui/kra/kis_kra_saver.cpp
index 48d685a..ecc4bac 100644
--- a/krita/ui/kra/kis_kra_saver.cpp
+++ b/krita/ui/kra/kis_kra_saver.cpp
@@ -251,7 +251,7 @@ bool KisKraSaver::saveAssistants(KoStore* store, QString uri, bool external)
 
 bool KisKraSaver::saveAssistantsList(QDomDocument& doc, QDomElement& element)
 {
-    int count_ellipse = 0, count_perspective = 0, count_ruler = 0, count_vanishingpoint = 0,count_infiniteruler = 0, count_parallelruler = 0, count_concentricellipse = 0, count_spline = 0;
+    int count_ellipse = 0, count_perspective = 0, count_ruler = 0, count_vanishingpoint = 0,count_infiniteruler = 0, count_parallelruler = 0, count_concentricellipse = 0, count_fisheyepoint = 0, count_spline = 0;
     QList<KisPaintingAssistant*> assistants =  m_d->doc->assistants();
     if (!assistants.isEmpty()) {
         QDomElement assistantsElement = doc.createElement("assistants");
@@ -284,6 +284,10 @@ bool KisKraSaver::saveAssistantsList(QDomDocument& doc, QDomElement& element)
                 assist->saveXmlList(doc, assistantsElement, count_concentricellipse);
                 count_concentricellipse++;
             }
+            else if (assist->id() == "fisheye-point"){
+                assist->saveXmlList(doc, assistantsElement, count_fisheyepoint);
+                count_fisheyepoint++;
+            }
             else if (assist->id() == "ruler"){
                 assist->saveXmlList(doc, assistantsElement, count_ruler);
                 count_ruler++;


More information about the kimageshop mailing list