-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added the files used for testing new erase code
- Loading branch information
Andrew Brooks
committed
Oct 22, 2018
1 parent
7c9cb93
commit 2327651
Showing
3 changed files
with
1,182 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,389 @@ | ||
/* > qctimage.cpp | ||
* 1.00 arb Thu May 27 09:18:38 BST 2010 | ||
*/ | ||
|
||
static const char SCCSid[] = "@(#)qctimage.cpp 1.00 (C) 2010 arb QCT image scrollview"; | ||
|
||
/* | ||
* QCTImage is a class to display a QCT (QuickChart) image. | ||
* It is a subclass of QScrollView so it can be used like a widget | ||
* that displays an image with scrollbars. | ||
*/ | ||
|
||
/* | ||
* Configuration: | ||
* Define STOP_MAP_MOVING_AFTER_MSEC as number of milliseconds to wait | ||
* after a mouseMove event to get a mouseButtonReleased event. If moving | ||
* within MSEC period then assume user wants map to continue moving, | ||
* otherwise user paused the mouse before releasing the button so wants | ||
* it to remain stationary. | ||
*/ | ||
#define STOP_MAP_MOVING_AFTER_MSEC 50 | ||
|
||
|
||
#include <qapplication.h> // for OverrideCursor | ||
#include <qcursor.h> // for QCursor::pos | ||
#include <qpainter.h> | ||
#include <qtimer.h> | ||
|
||
#include "satlib/dundee.h" | ||
#include "osmap/qct.h" | ||
#include "qctimage.h" | ||
|
||
|
||
/* --------------------------------------------------------------------------- | ||
* | ||
*/ | ||
ArrowPlot::ArrowPlot(int x, int y, float bearing, float length) | ||
{ | ||
stemwidth = 8; | ||
filled = true; | ||
|
||
QPointArray prepoints(8); | ||
prepoints[0] = QPoint(-stemwidth, 0); | ||
prepoints[1] = QPoint(-stemwidth, -length); | ||
prepoints[2] = QPoint(-stemwidth*2, -length); | ||
prepoints[3] = QPoint(0, -length-stemwidth*2); | ||
prepoints[4] = QPoint(stemwidth*2, -length); | ||
prepoints[5] = QPoint(stemwidth, -length); | ||
prepoints[6] = QPoint(stemwidth, 0); | ||
prepoints[7] = QPoint(-stemwidth, 0); | ||
|
||
// Translate origin THEN rotate all the points | ||
QWMatrix wm; | ||
wm.translate(x, y); | ||
wm.rotate(bearing); | ||
points = wm.map(prepoints); | ||
|
||
// For speed extract the bounding box and keep it | ||
boundingBox = points.boundingRect(); | ||
} | ||
|
||
ArrowPlot::~ArrowPlot() | ||
{ | ||
} | ||
|
||
QRect | ||
ArrowPlot::rect() const | ||
{ | ||
return boundingBox; | ||
} | ||
|
||
void | ||
ArrowPlot::plot(QPainter *painter) | ||
{ | ||
if (filled) | ||
painter->drawPolygon(points); | ||
else | ||
painter->drawPolyline(points); | ||
} | ||
|
||
|
||
|
||
/* --------------------------------------------------------------------------- | ||
* | ||
*/ | ||
QCTImage::QCTImage(QWidget *parent) : QScrollView(parent, "qcti", WNoAutoErase|WStaticContents) | ||
{ | ||
qct = 0; | ||
dragging = floating = false; | ||
|
||
arrowList.setAutoDelete(true); | ||
|
||
// Allow mouse move events through to contentsMouseMoveEvent | ||
viewport()->setMouseTracking(true); | ||
|
||
// Enable panning -- this only works if you try to drag an item | ||
// from outside the window (eg. from the Desktop) into the window | ||
// and hold it near the edge. It's a nice effect though. | ||
//setDragAutoScroll(true); | ||
//viewport()->setAcceptDrops(true); | ||
} | ||
|
||
|
||
QCTImage::~QCTImage() | ||
{ | ||
unload(); | ||
} | ||
|
||
|
||
void | ||
QCTImage::unload() | ||
{ | ||
if (qct) | ||
{ | ||
delete qct; | ||
qct = 0; | ||
} | ||
arrowList.clear(); | ||
} | ||
|
||
|
||
/* | ||
* Load a QCT, create a QImage, copy the image data from the QCT, | ||
* resize the internal dimensions of the scrollview, scroll to middle. | ||
*/ | ||
bool | ||
QCTImage::load(QString filename, int scalefactor) | ||
{ | ||
int ii, yy, width, height; | ||
|
||
qct = new QCT(); | ||
QApplication::setOverrideCursor(waitCursor); | ||
if (!qct->openFilename((const char*)filename, false, scalefactor)) | ||
{ | ||
log_error_message("cannot read %s", (const char*)filename); | ||
return false; | ||
} | ||
QApplication::restoreOverrideCursor(); | ||
|
||
// Create the internal image with the correct dimensions | ||
width = qct->getImageWidth(); | ||
height = qct->getImageHeight(); | ||
image.reset(); | ||
image.create(width, height, 8, 256); | ||
debugf(1, "loaded QCT %d x %d from %s\n",width,height,(const char*)filename); | ||
|
||
// Fill in the colourmap by querying the QCT colourmap | ||
for (ii=0; ii<256; ii++) | ||
{ | ||
int R, G, B; | ||
qct->getColour(ii, &R, &G, &B); | ||
image.setColor(ii, qRgb(R, G, B)); | ||
} | ||
|
||
// Fill in the image data by reading the QCT image data | ||
for (yy=0; yy<height; yy++) | ||
{ | ||
memcpy(image.scanLine(yy), qct->getImage()+yy*width*sizeof(unsigned char), width*sizeof(unsigned char)); | ||
} | ||
|
||
// Free the image memory from within the QCT object now we've copied it | ||
qct->unloadImage(); | ||
|
||
// Tell the scrollview how big its image is | ||
resizeContents(width, height); | ||
|
||
// Scroll to the middle | ||
center(width/2, height/2); | ||
|
||
return true; | ||
} | ||
|
||
|
||
/* | ||
* Save the image to a file | ||
*/ | ||
bool | ||
QCTImage::save(QString filename, const char *fmt) | ||
{ | ||
return image.save(filename, fmt); | ||
} | ||
|
||
|
||
/* -------------------------------------------------------------------------- | ||
* Paint the portion of the image onto the screen. | ||
*/ | ||
void | ||
QCTImage::drawContents(QPainter *painter, int cx, int cy, int cw, int ch) | ||
{ | ||
if (image.isNull()) | ||
{ | ||
//painter->eraseRect(area); | ||
return; | ||
} | ||
|
||
// Plot the visible part of the image | ||
QRect area(cx, cy, cw, ch); | ||
painter->drawImage(area.topLeft(), image, area); | ||
|
||
// Border and fill colour of arrows | ||
painter->setPen(QPen(black, 1, SolidLine)); // ! use no thicker than 1 | ||
painter->setBrush(QBrush(red, SolidPattern)); | ||
|
||
// Get all the arrows to draw themselves | ||
for (ArrowPlot *arrow = arrowList.first(); arrow; arrow = arrowList.next()) | ||
{ | ||
debugf(1, "ARROW %d %d %d %d ",arrow->rect().x(), arrow->rect().y(), | ||
arrow->rect().width(), arrow->rect().height()); | ||
if (arrow->rect().intersects(area)) | ||
{ | ||
debugf(1, "plot\n"); | ||
arrow->plot(painter); | ||
} | ||
else | ||
{ | ||
debugf(1, "invisible\n"); | ||
} | ||
} | ||
} | ||
|
||
|
||
/* -------------------------------------------------------------------------- | ||
* Mouse is moving over the map | ||
* convert mouse position into latitude and longitude, | ||
* if button was pressed then dragging is true so scroll the map | ||
* (could test for button by looking at event->state instead?) | ||
* [NB. Only called if mouse tracking has been enabled.] | ||
*/ | ||
void | ||
QCTImage::contentsMouseMoveEvent(QMouseEvent *event) | ||
{ | ||
// Do nothing if no image has been loaded | ||
if (image.isNull() || qct == 0) | ||
return; | ||
|
||
// Do nothing if point is not within image | ||
int mx = event->pos().x(); | ||
int my = event->pos().y(); | ||
int imagewidth = image.width(); | ||
int imageheight = image.height(); | ||
if (mx < 0 || my < 0 || mx > imagewidth || my > imageheight) | ||
return; | ||
|
||
double lat, lon; | ||
qct->xy_to_latlon(mx,my, &lat, &lon); | ||
//debugf(1,"QCTImage::contentsMouseMoveEvent %d, %d = %f, %f", mx, my, lat, lon); | ||
|
||
// Could set val as colour of pixel at mx,my | ||
emit location(lat, lon, 0); | ||
|
||
// Panning | ||
if (dragging) | ||
{ | ||
dragDelta = QPoint(dragStartMousePos - contentsToViewport(event->pos())); | ||
QPoint newpos = dragStartContentsPos + dragDelta; | ||
setContentsPos(newpos.x(), newpos.y()); | ||
lastMoveTime.start(); | ||
//debugf(1,"Mouse started at %5d %5d\n", dragStartMousePos.x(), dragStartMousePos.y()); | ||
//debugf(1,"contents were at %5d %5d\n", dragStartContentsPos.y(), dragStartContentsPos.y()); | ||
//debugf(1,"mouse now %5d %5d\n", event->pos().x(), event->pos().y()); | ||
//debugf(1,"delta %5d %5d\n", delta.x(), delta.y()); | ||
//debugf(1,"contents now at %5d %5d\n", newpos.x(), newpos.y()); | ||
} | ||
} | ||
|
||
void | ||
QCTImage::contentsMousePressEvent(QMouseEvent *event) | ||
{ | ||
dragging = true; | ||
floating = false; | ||
dragStartMousePos = contentsToViewport(event->pos()); | ||
dragStartContentsPos = QPoint(contentsX(), contentsY()); | ||
} | ||
|
||
|
||
void | ||
QCTImage::contentsMouseReleaseEvent(QMouseEvent *event) | ||
{ | ||
// Prevent any future mouseMoveEvents from continuing to drag the map | ||
dragging = false; | ||
|
||
// If mouse was moving recently (not paused over one spot) then assume the | ||
// user wants the map to continue moving in the same direction, ie floating | ||
if (lastMoveTime.elapsed() < STOP_MAP_MOVING_AFTER_MSEC) | ||
{ | ||
floating = true; | ||
keepFloating(); | ||
} | ||
else | ||
{ | ||
floating = false; | ||
} | ||
} | ||
|
||
|
||
void | ||
QCTImage::keepFloating() | ||
{ | ||
// Keep moving smoothly in the same direction | ||
scrollBy(dragDelta.x() / 4, dragDelta.y() / 4); | ||
|
||
// Come back later and move further | ||
if (floating) | ||
QTimer::singleShot(100, this, SLOT(keepFloating())); | ||
} | ||
|
||
|
||
/* -------------------------------------------------------------------------- | ||
* Delete all info about plotted items ready to have new items plotted | ||
* (so doesn't bother to update the screen) | ||
*/ | ||
void | ||
QCTImage::unplotArrows() | ||
{ | ||
// Only erase the visible bits | ||
QRect vis(contentsX(), contentsY(), contentsWidth(), contentsHeight()); | ||
|
||
// Empty the list of regions to refresh | ||
refreshList.clear(); | ||
refreshList.setAutoDelete(true); | ||
|
||
// Erase all the old arrows before their shape changes to new bbox | ||
for (ArrowPlot *arrow = arrowList.first(); arrow; arrow = arrowList.next()) | ||
{ | ||
QRect arrect = arrow->rect(); | ||
if (arrect.intersects(vis)) | ||
{ | ||
//updateContents(arrect); | ||
refreshList.append(new QRect(arrect)); | ||
} | ||
} | ||
// Empty the list | ||
arrowList.clear(); | ||
} | ||
|
||
|
||
/* -------------------------------------------------------------------------- | ||
* Convert latitude and longitude into pixel coordinate | ||
* and plot. | ||
*/ | ||
void | ||
QCTImage::plotArrow(float lat, float lon, float bearing, float length) | ||
{ | ||
if (!qct) | ||
return; | ||
int x, y; | ||
qct->latlon_to_xy(lat, lon, &x, &y); | ||
ArrowPlot *arrow = new ArrowPlot(x, y, bearing, length); | ||
arrowList.append(arrow); | ||
|
||
debugf(1,"plot at %f %f = %d %d bearing %f length %f\n",lat,lon, x,y, bearing,length); | ||
|
||
//updateContents(arrow->rect()); | ||
} | ||
|
||
|
||
/* -------------------------------------------------------------------------- | ||
*/ | ||
void | ||
QCTImage::updateAfterPlot() | ||
{ | ||
// Unplot all the old arrows | ||
for (QRect *rectp = refreshList.first(); rectp; rectp = refreshList.next()) | ||
updateContents(*rectp); | ||
refreshList.clear(); | ||
// Plot all the arrows | ||
for (ArrowPlot *arrowp = arrowList.first(); arrowp; arrowp = arrowList.next()) | ||
updateContents(arrowp->rect()); | ||
} | ||
|
||
|
||
/* -------------------------------------------------------------------------- | ||
* Scroll so the given location is in the middle of the screen | ||
*/ | ||
bool | ||
QCTImage::scrollToLatLon(double lat, double lon) | ||
{ | ||
if (!qct) | ||
return false; | ||
|
||
int x, y; | ||
qct->latlon_to_xy(lat, lon, &x, &y); | ||
if (x<0 || y<0 || x>image.width()-1 || y>image.height()-1) | ||
return false; | ||
|
||
center(x, y); | ||
|
||
return true; | ||
} |
Oops, something went wrong.