[Kstars-devel] KDE/kdeedu/kstars/kstars
Jason Harris
kstars at 30doradus.org
Tue Jun 13 05:25:40 CEST 2006
SVN commit 550894 by harris:
Committing changes from James Bowlin to fix a rendering bug.
Constellation lines were disappearing at high zoom when one of the
endpoints was far off-screen. This patch uses interpolation to truncate
the constellation line at the edge of the visible skymap.
Thanks James!
CCMAIL: kstars-devel at kde.org
M +8 -17 skycomponents/constellationlinescomponent.cpp
M +14 -4 skymap.cpp
M +12 -2 skymap.h
M +94 -0 skymapdraw.cpp
--- trunk/KDE/kdeedu/kstars/kstars/skycomponents/constellationlinescomponent.cpp #550893:550894
@@ -42,26 +42,17 @@
if ( !visible() ) return;
SkyMap *map = ks->map();
- float Width = scale * map->width();
- float Height = scale * map->height();
//Draw Constellation Lines
psky.setPen( QPen( QColor( ks->data()->colorScheme()->colorNamed( "CLineColor" ) ), 1, Qt::SolidLine ) ); //change to CLine color
// int iLast = -1;
- QPointF oStart;
- for ( int i=0; i < pointList().size(); ++i ) {
- QPointF o = map->toScreen( pointList().at(i), scale );
-
- if ( ( o.x() >= -1000. && o.x() <= Width+1000. && o.y() >=-1000. && o.y() <= Height+1000. ) ) {
- if ( oStart.x() != 0 && m_CLineModeList.at(i)=='D' ) {
- if ( Options::useAntialias() )
- psky.drawLine( oStart, o );
- else
- psky.drawLine( QPoint(int(oStart.x()),int(oStart.y())),
- QPoint(int(o.x()), int(o.y())) );
- }
- oStart = o;
- }
- }
+ SkyPoint *pLast = pointList().at(0);
+ for ( int i=1; i < pointList().size(); ++i ) {
+ SkyPoint *pThis = pointList().at(i);
+ if (m_CLineModeList.at(i) == 'D') {
+ map->drawClippedLine( pLast, pThis, psky, scale);
+ }
+ pLast = pThis;
+ }
}
--- trunk/KDE/kdeedu/kstars/kstars/skymap.cpp #550893:550894
@@ -751,7 +751,8 @@
return ( north + o->pa() );
}
-QPointF SkyMap::toScreen( SkyPoint *o, double scale, bool oRefract ) {
+QPointF SkyMap::toScreen( SkyPoint *o, double scale, bool oRefract, bool *clipped) {
+
QPointF p;
double Y, dX;
double sindX, cosdX, sinY, cosY, sinY0, cosY0;
@@ -813,10 +814,19 @@
double c = sinY0*sinY + cosY0*cosY*cosdX;
if ( c < 0.0 ) { //Object is on "back side" of the celestial sphere; don't plot it.
- p.setX( -10000000. );
- p.setY( -10000000. );
- return p;
+ if ( clipped == NULL) {
+ p.setX( -10000000. );
+ p.setY( -10000000. );
+ return p;
+ }
+ *clipped = true;
}
+ else {
+ if ( clipped != NULL ) {
+ *clipped = false;
+ }
+ }
+
double k;
switch ( Options::projection() ) {
--- trunk/KDE/kdeedu/kstars/kstars/skymap.h #550893:550894
@@ -362,7 +362,16 @@
*@see KStars::slotPrint()
*/
void exportSkyImage( QPaintDevice *pd );
+
+/**@short Draw a clipped line from p1 to p2
+ */
+ void SkyMap::drawClippedLine( SkyPoint *p1, SkyPoint *p2, QPainter& psky, double scale );
+/**ASSUMES *p1 did not clip but *p2 did. Returns the QPointF on the line
+ * between *p1 and *p2 that just clips.
+ **/
+ QPointF SkyMap::clipLine( SkyPoint *p1, SkyPoint *p2, double scale);
+
/**Given the coordinates of the SkyPoint argument, determine the
*pixel coordinates in the SkyMap.
*@return QPoint containing screen pixel x, y coordinates of SkyPoint.
@@ -371,8 +380,9 @@
*@param useRefraction true = use Options::useRefraction() value.
*false = do not use refraction. This argument is only needed
*for the Horizon, which should never be refracted.
- */
- QPointF toScreen( SkyPoint *o, double scale=1.0, bool useRefraction=true );
+ *@param clipped pointer to a bool indicating point is past horizon
+ **/
+ QPointF toScreen( SkyPoint *o, double scale=1.0, bool useRefraction=true, bool *clipped=NULL);
/**Determine RA, Dec coordinates of the pixel at (dx, dy), which are the
*screen pixel coordinate offsets from the center of the Sky pixmap.
--- trunk/KDE/kdeedu/kstars/kstars/skymapdraw.cpp #550893:550894
@@ -47,6 +47,100 @@
#include "indidevice.h"
#include "observinglist.h"
+void toXYZ(SkyPoint* p, double *x, double *y, double *z) {
+ double sinRa, sinDec, cosRa, cosDec;
+
+ p->ra()->SinCos( sinRa, cosRa );
+ p->dec()->SinCos( sinDec, cosDec );
+ *x = cosDec * cosRa;
+ *y = cosDec * sinRa;
+ *z = sinDec;
+}
+
+void SkyMap::drawClippedLine( SkyPoint *p1, SkyPoint *p2, QPainter& psky, double scale )
+{
+/**
+ if both points are clipped: do nothing
+ if no points are clipped: draw the line
+ if one point is clipped: find approx point on edge and draw to it.
+
+We do the interpolation in x-y-z space because interpolation in [ra, dec] gives
+weird results, especially around the poles.
+**/
+ bool clipped1, clipped2;
+ QPointF o1, o2, oMid;
+ o1 = toScreen( p1, scale, Options::useRefraction(), &clipped1 );
+ o2 = toScreen( p2, scale, Options::useRefraction(), &clipped2 );
+
+ if (clipped1 && clipped2 ) {
+ return;
+ }
+ else if (! clipped1 && ! clipped2 ) {
+ psky.drawLine( o1, o2 );
+ }
+ else if (clipped2) {
+ oMid = clipLine( p1, p2, scale );
+ psky.drawLine( o1, oMid );
+ }
+ else {
+ oMid = clipLine( p2, p1, scale );
+ psky.drawLine ( o2, oMid );
+ }
+}
+
+QPointF SkyMap::clipLine( SkyPoint *p1, SkyPoint *p2, double scale )
+{
+/* ASSUMES p1 was not clipped but p2 was.
+ * Return the QPoint that barely clips in the line twixt p1 and p2.
+ */
+ int iteration = 15; // For "perfect" clipping:
+ // 2^interations should be >= max pixels/line
+ bool clipped = false; // so we start at midpoint
+ SkyPoint mid;
+ QPointF oMid;
+ double x, y, z, dx, dy, dz, ra, dec;
+ int newx, newy, oldx, oldy;
+ oldx = oldy = -10000; // any old value that is not the first omid
+
+ toXYZ( p1, &x, &y, &z );
+ toXYZ( p2, &dx, &dy, &dz );
+ dx -= x;
+ dy -= y;
+ dz -= z;
+ // Successive approximation to point on line that just clips.
+ while(iteration-- > 0) {
+ dx *= .5;
+ dy *= .5;
+ dz *= .5;
+ if ( clipped ) { // move back toward visible p1
+ x -= dx;
+ y -= dy;
+ z -= dz;
+ }
+ else { // move out toward clipped p2
+ x += dx;
+ y += dy;
+ z += dz;
+ }
+ // [x, y, z] => [ra, dec]
+ ra = atan2( y, x );
+ dec = asin( z / sqrt(x*x + y*y + z*z) );
+
+ mid = SkyPoint( ra * 12. / dms::PI, dec * 180. / dms::PI );
+ mid.EquatorialToHorizontal( data->LST, data->geo()->lat() );
+
+ oMid = toScreen( &mid, scale, Options::useRefraction(), &clipped );
+ newx = (int) oMid.x();
+ newy = (int) oMid.y();
+ if ( (oldx == newx) && (oldy == newy) ) {
+ break;
+ }
+ oldx = newx;
+ oldy = newy;
+ }
+ return oMid;
+}
+
void SkyMap::drawOverlays( QPixmap *pm ) {
if ( ks ) { //only if we are drawing in the GUI window
QPainter p;
More information about the Kstars-devel
mailing list