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

List:       kstars-devel
Subject:    Re: [Kstars-devel] Drawing comet tail patch
From:       Charles <chp516 () gmail ! com>
Date:       2009-04-15 4:49:36
Message-ID: 89298fc00904142149r2327d392wba0c9044ba299129 () mail ! gmail ! com
[Download RAW message or body]

Hi all,

Sorry about the hasty submission last night, the patch was still
incorrect. I made a correction when the sun is in the second or the
third quadrant relative to the comet where the return value of the
atan function needs to be adjusted.

I find another defect with my patch: if the Sun is not on screen, the
map->toScreen((SkyPoint *) Sun) returns (-10000000, -10000000) which
makes the rotation incorrect. Can someone tell me whether there is a
more decent way to determine the location of the Sun?

Regards,
-- 
Charles

["comettail.patch" (application/octet-stream)]

Index: kstars/kstars/skycomponents/cometscomponent.cpp
===================================================================
--- kstars/kstars/skycomponents/cometscomponent.cpp	(revision 954089)
+++ kstars/kstars/skycomponents/cometscomponent.cpp	(working copy)
@@ -21,7 +21,10 @@
 #include <QFile>
 #include <QPen>
 #include <QPainter>
+#include <QRadialGradient>
+#include <QPainterPath>
 #include <kglobal.h>
+#include <cmath>
 
 #include "Options.h"
 #include "skyobjects/kscomet.h"
@@ -93,11 +96,17 @@
 
     SkyMap *map = SkyMap::Instance();
 
+    // The following line is copied from skyobjects/ksmoon.cpp, they should be fix \
synchronously. +    // TODO: Get rid of this ugly thing by making KSSun singleton.
+    KSSun *Sun = (KSSun*)KStarsData::Instance()->skyComposite()->findByName( "Sun" \
); +
+    // Fixme: If the Sun is not on screen, toScreen will return (-10000000.0, \
-10000000.0). +    QPointF sp = map->toScreen( (SkyPoint *)Sun );
+
     bool hideLabels =  ! Options::showCometNames() || (map->isSlewing() && \
Options::hideLabels() );  double rsunLabelLimit = Options::maxRadCometName();
 
-    psky.setPen( QPen( QColor( "darkcyan" ) ) );
-    psky.setBrush( QBrush( QColor( "darkcyan" ) ) );
+    psky.setPen( Qt::NoPen );
 
     foreach ( SkyObject *so, objectList() ) {
         KSComet *com = (KSComet*)so;
@@ -109,18 +118,76 @@
         if ( ! map->onScreen( o ) ) continue;
         //if ( ( o.x() >= 0. && o.x() <= Width && o.y() >= 0. && o.y() <= Height ) )
 
+	float rot;
+	if ( abs( sp.x() - o.x() ) < 0.001 * abs( sp.y() - o.y() ) ) {
+	    if ( sp.y() > o.y() )
+		rot = 90.0;
+	    else
+		rot = -90.0;
+	} else {
+	    float dy = sp.y() - o.y();
+	    float dx = sp.x() - o.x();
+
+	    rot = atan( dy / dx );
+	    rot = rot * 180 / dms::PI;
+	    if ( dx < 0 )
+		rot += 180;
+	}
+
         float size = com->angSize() * map->scale() * dms::PI * \
Options::zoomFactor()/10800.0; +	float radius = 0.5 * size;
+
+	psky.translate( o );
+	psky.rotate( rot );
+	psky.translate( QPointF( radius, 0 ) );
+
+	QRadialGradient gn( QPointF( -radius, 0 ),
+			    radius,
+			    QPointF( -radius, 0 ) );
+	gn.setColorAt( 0.0, QColor( "darkcyan" ) );
+	gn.setColorAt( 1.0, Qt::transparent );
+	psky.setBrush( gn );
+
 	if ( size < 1.0 ) {
-            psky.drawPoint( o );
+            psky.drawPoint( QPointF( -radius, 0 ) );
         } else {
-            float x1 = o.x() - 0.5*size;
-            float y1 = o.y() - 0.5*size;
+	    float x1 = -size;
+            float y1 = -radius;
 
             psky.drawEllipse( QRectF( x1, y1, size, size ) );
         }
 
         float tailsize = com->getTailAngSize().Degrees() * map->scale() * dms::PI * \
Options::zoomFactor()/10800.0;  
+	QRadialGradient gt( QPointF( -radius, 0 ),
+			    tailsize + radius,
+			    QPointF( -radius, 0 ) );
+	gt.setColorAt( 0.0, QColor( "darkcyan" ) );
+	gt.setColorAt( 1.0, Qt::transparent );
+	psky.setBrush( gt );
+
+	// Using cubic bezier curve to draw the nucleus (the 2nd time) and the tail.
+	QPainterPath pt;
+	float len = tailsize + size;
+	float u; // an empirical scale factor
+	// If the comet is small, the shape doesn't matter much.
+	// Here u = 2 is to avoid a / radius resulting a NaN.
+	if ( radius < 0.1 )
+	    u = 2;
+	else
+	    u = sqrt( len / radius ); // empirical approximation
+	float v = sqrt( u / 2);
+	pt.moveTo( QPointF( -len, v * radius ) );
+	pt.cubicTo( QPointF( len / 3, u * radius ),
+		    QPointF( len / 3, -u * radius ),
+		    QPointF( -len, -v * radius ) );
+	pt.closeSubpath();
+	psky.drawPath( pt );
+
+	psky.translate( QPointF( -radius, 0 ) );
+	psky.rotate( -rot );
+	psky.translate( QPointF( -o.x(), -o.y() ) );
+
         if ( hideLabels || com->rsun() >= rsunLabelLimit ) continue;
         SkyLabeler::AddLabel( o, com, SkyLabeler::COMET_LABEL );
     }


["screenshot.png" (image/png)]

_______________________________________________
Kstars-devel mailing list
Kstars-devel@kde.org
https://mail.kde.org/mailman/listinfo/kstars-devel


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

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