📄 maplist.cpp
字号:
#include "gpslib.h"
#include <dstring.h>
#include <ctype.h>
#include <math.h>
#include <stdio.h>
#include <qpixmap.h>
class maplist: public list_of<mapinfo>{
public:
maplist():mrp(0){}
~maplist();
const char *readmapdata(const char *mapname);
// Messy iterator-like function. Returns pointer to
// maps which match
mapinfo * locatemap(double lat, double longit);
const mapinfo * locatemap(const char *cp);
// If a map was located, here's the gen
const mapinfo *mp() { return mrp; }
void clear(){list_of<mapinfo>::clear(); mrp = 0;}
private:
// last item found by locatemap (if any)
mapinfo *mrp;
} mapinfolist;
int initmaplist(const char *mapname){
mapinfolist.clear();
const char *cp = mapinfolist.readmapdata(mapname);
if(cp){
printwhinge("Error Reading Map Data: %s", cp);
return 0;
}
return 1;
}
double requestedscale = 0;
void locatescale(double pixperdegn){
requestedscale = pixperdegn;
}
int enumeratemaps(double lat, double longit, char *namep, int *namelen, double *nscalep, double *escalep){
const mapinfo *mp = mapinfolist.locatemap(lat, longit);
if(mp){
if(namep) strcpy(namep, mp->name.cstring());
if(namelen) *namelen = mp->name.nchars();
if(nscalep) *nscalep = mp->pixperdegheight;
if(escalep) *escalep = mp->pixperdegwidth;
return 1;
}
return 0;
}
// locatemap scans for candidate maps, returning a "best" fit. Here
// we remember the scales found so that other options can be shown
sortable_list_of<double>nscalesfound;
// Call enumeratescales if locatemap has returned true. Returns
// available scales (pix per deg N)
void enumeratescales(list_of<double> &lodr){
lodr.clear();
const ne = nscalesfound.element_count();
// return in reverse order
for(int i = ne-1; i >= 0; i--){
lodr += nscalesfound[i];
}
}
int locatemap(double lat, double longit, String &name, double &nscale, double &escale){
if(requestedscale == 0){
const mapinfo *mp = mapinfolist.locatemap(lat, longit);
if(mp){
name = mp->name;
nscale = mp->pixperdegheight;
escale = mp->pixperdegwidth;
return 1;
}
return 0;
}
const mapinfo *mp = locatemapinfo(lat, longit);
if(mp == 0)
return 0;
name = mp->name;
nscale = mp->pixperdegheight;
escale = mp->pixperdegwidth;
return 1;
}
const mapinfo * locatemapinfo(double lat, double longit){
if(requestedscale == 0)
return mapinfolist.locatemap(lat, longit);
// Requestedscale isn't zero - first find 'best' scale, then of all maps
// within 5%, return the one with the nearest centre point
nscalesfound.clear();
// char buff[512];
mapinfo *mip;
if(verbose)printf("locatemapinfo, requested scale is %f\n", requestedscale);
double bestdiff = -100;
// For each map that contains the desired point
while((mip = mapinfolist.locatemap(lat, longit)) != 0){
double thisdiff = fabs(requestedscale-mip->pixperdegheight);
if(bestdiff < 0 || thisdiff < bestdiff)
bestdiff = thisdiff;
// gotalready tells us if we have this approximately this scale in the list
int gotalready = 0;
for(int i = 0; i < nscalesfound.element_count(); i++){
if(fabs(nscalesfound[i]-mip->pixperdegheight) < mip->pixperdegheight/20){
mip->scalefamily = nscalesfound[i];
gotalready++;
break;
}
}
if(!gotalready){
nscalesfound += mip->pixperdegheight;
mip->scalefamily = mip->pixperdegheight;
if(verbose)printf("Adding %f to scale list\n", mip->pixperdegheight);
}
}
nscalesfound.sort();
if(verbose)printf("Located maps with %d different scales\n", nscalesfound.element_count());
const mapinfo *mp = 0;
double bestmiddiff = -100;
while((mip = mapinfolist.locatemap(lat, longit)) != 0){
double thisdiff = fabs(requestedscale-mip->pixperdegheight);
// printf("map scale %f bestdiff %f, thisdiff %f\n", mip->pixperdegheight, bestdiff, thisdiff);
if(fabs(thisdiff-bestdiff) <= bestdiff/20){
// prepared to use this one
// printf("%f within range, family %f\n", thisdiff-bestdiff, mip->scalefamily);
double latdiff = lat-(mip->latmin+(mip->latmax-mip->latmin)/2);
double longdiff = longit-(mip->longmin+(mip->longmax-mip->longmin)/2);
double distance = sqrt(latdiff*latdiff+(longdiff*longdiff));
if(bestmiddiff < 0 || distance < bestmiddiff){
// mip->requestedscale = requestedscale;
mp = mip;
bestmiddiff = distance;
// strcpy(buff, mip->name.cstring());
}
}
}
return mp;
}
#ifdef BITMAP
class bitmap{
public:
enum howget{full, justinfo};
bitmap(const char *fname, howget get=justinfo);
bitmap();
~bitmap();
int reload(const string &fname);
int isvalid()const { return vf; }
long height()const { return vf ? dibpixheight : 0;}
long width()const { return vf ? dibpixwidth : 0;}
// drawon a window
int drawon(int hwnd, int bmx, int bmy, int windx, int windy, int width, int height);
private:
int vf; // validflag
char huge *bmdp; // the data pointer whilst reading from file
long dibpixwidth, dibpixheight; // pixels w/h
unsigned long bits; // offset into bmdp where the bits live
int hbitmap;
// we can't copy these things around, sorry
bitmap(const bitmap&);
void operator =(const bitmap&);
void doload(const char *fname, howget);
};
inline int bitmap::reload(const string &fname){
doload(fname.cstring(), full);
return vf;
}
int showmap(const char *name, double midlat, double midlong, int hwnd){
const mapinfo *mip = mapinfolist.locatemap(name);
if(mip == 0){
MessageBox(0, "Requested map name not found in showmap", name, MB_ICONSTOP);
return 0;
}
// Bitmap cache
static string mapfilename;
static bitmap bm;
if(mapfilename != name){
mapfilename = name;
bm.reload(mapfilename);
}
if(!bm.isvalid()){
MessageBox(0, "Requested bitmap invalid in showmap", name, MB_ICONSTOP);
return 0;
}
if(midlat < mip->latmin || midlat > mip->latmax || midlong < mip->longmin || midlong > mip->longmax){
MessageBox(0, "midlat/long out of range!", "showmap", MB_ICONSTOP);
return 0;
}
RECT r;
GetClientRect(hwnd, &r);
// Locate the pixel within the bitmap which corresponds to midlat/long
// This was originally done by extrapolating lat/long figures, but that
// doesn't work too well because of projection errors (NGR grid does not
// follow lat/long very well).
int midlatpix, midlongpix;
if(mip->osproj){
double east=0, north=0;
cvtongr(midlat, midlong, 0, &east, &north);
midlatpix = (mip->northmax-north)*mip->pixpermetreheight;
midlongpix = (east-mip->eastmin)*mip->pixpermetrewidth;
}else{
midlatpix = (mip->latmax-midlat)*mip->pixperdegheight;
midlongpix = (midlong-mip->longmin)*mip->pixperdegwidth;
}
// Adjust offsets within pixel regions
int wndstartx, wndstarty, mapstartx, mapstarty;
// work out where on the window the left and top map edges lie - adjust
// if outside
wndstartx = r.right/2-midlongpix;
wndstarty = r.bottom/2-midlatpix;
mapstartx = 0; mapstarty = 0;
if(wndstartx < 0){
mapstartx -= wndstartx;
wndstartx = 0;
}
if(wndstarty < 0){
mapstarty -= wndstarty;
wndstarty = 0;
}
// and now the drawing width and height
int dwidth, dheight;
dwidth = r.right - wndstartx;
dheight = r.bottom - wndstarty;
if(dwidth > mip->pixwidth-mapstartx)
dwidth = int(mip->pixwidth-mapstartx);
if(dheight > mip->pixheight-mapstarty)
dheight = int(mip->pixheight-mapstarty);
#if REPORTMAP
char msgbuff[512];
sprintf(msgbuff, "mapstartx %d, mapstarty %d, wndstartx %d, wndstarty %d, width %d, height %d",
mapstartx, mapstarty, wndstartx, wndstarty, dwidth, dheight);
MessageBox(0, msgbuff, "showmap", MB_ICONSTOP);
#endif
return bm.drawon(hwnd, mapstartx, mapstarty, wndstartx, wndstarty, dwidth, dheight);
}
#endif
void mapinfo::print()const{
printf("mapinfo: map %s, longmin %f longmax %g latmin %g latmax %g\n",
name.cstring(), longmin, longmax, latmin, latmax);
printf("eastmin %g, eastmax %g, northmin %g, northmax %g\n", eastmin, eastmax, northmin, northmax);
printf("pixwidth %ld, pixheight %ld, pixperdegwidth %g, pixperdegheight %g\n", pixwidth, pixheight, pixperdegwidth, pixperdegheight);
printf("pixpermetrewidth %g, pixpermetreheight %g\n",pixpermetrewidth, pixpermetreheight);
}
mapinfo * maplist::locatemap(double lat, double longit){
static counter;
while(counter < element_count()){
mapinfo &mr = operator[](counter);
counter++;
if(lat < mr.latmax && lat > mr.latmin && longit < mr.longmax && longit > mr.longmin){
mrp = &mr;
return mrp;
}
}
counter = 0;
mrp = 0;
return 0;
}
const mapinfo * maplist::locatemap(const char *cp){
for (int counter = 0; counter < element_count(); counter++){
mapinfo &mr = operator[](counter);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -