Пример #1
0
    def read_header(self):
        self.dheader = self.fhlay.read(0x80)

        [self.category] = self.unpack("i", self.dheader[4:])
        [self.fileidentifier] = self.unpack("H", self.dheader[8:])

        tmp = self.unpack("4f", self.dheader[0xa:])
        self._bbox = Rec(N.array([tmp[0], tmp[2]]), N.array([tmp[1], tmp[3]]))

        [self.nlevels] = self.unpack("h", self.dheader[0x1a:])
        [self.nobjects] = self.unpack("i", self.dheader[0x1c:])

        [xscale] = self.unpack("d", self.dheader[0x20:])
        [yscale] = self.unpack("d", self.dheader[0x28:])

        self._scale = N.array([xscale, yscale])

        self._refpoint = N.array(self.unpack("2f", self.dheader[0x30:]))

        tmp = self.unpack("4i", self.dheader[0x38:])
        self._dbbox = Rec(N.array([tmp[0], tmp[1]]), N.array([tmp[2], tmp[3]]))

        [self.layertype] = self.unpack("b", self.dheader[0x48:])
        [unknown49] = self.unpack("b", self.dheader[0x49:])
        [self.largestcellsize] = self.unpack("i", self.dheader[0x4a:])
        [self.firstcell] = self.unpack("i", self.dheader[0x4e:])
        [self.lastcell] = self.unpack("i", self.dheader[0x52:])

        assert (unknown49, 0)
Пример #2
0
    def set_dbboxrec(self, drec):
        first_time = self._dbbox == None

        if not first_time and self.mode == 'r':
            raise ValueError(
                "Can't change boundary rectangle in read-only mode")

        self._dbbox = drec.negY()
        self._bbox = self._dbbox.tocontinous(self._refpoint, self._scale)

        if self._dbbox.width % (2**self.nlevels) != 0 or self._dbbox.height % (
                2**self.nlevels) != 0:
            logging.warn(
                "bbox should be a multiple of minimum cell size, adjusting bbox borders"
            )
            n = 2**(self.nlevels + 1)
            width = self._dbbox.width
            height = self._dbbox.height

            width += -width % n
            height += -height % n

            self._dbbox = Rec(self._dbbox.c1,
                              self._dbbox.c1 + N.array(width, height))

        # If in append mode all cell elements must be re-added to fit the new
        # cell boundaries
        if not first_time and self.mode == 'a':
            cellelements = [e for e in self.getCellElements()]

            self.clearCells()

            for e in cellelements:
                self.addCellElement(e)
Пример #3
0
    def calculateDBBox(self):
        """Calculate estimated bounding box of layer in discrete coordinates"""
        if N.alltrue(self.dbboxmin == self.layer.float2discrete((
                N.array([180.0, 90.0]), ))):
            return None

        if N.all(self.dbboxmin != self.dbboxmax):
            dbbox = Rec(self.dbboxmin, self.dbboxmax)
        else:
            # Magellan Software cannot handle zero-area bounding boxes
            dbbox = Rec(self.dbboxmin, self.dbboxmax + N.array([1, 1]))

        if self.verbose:
            print "Estimated discretebbox", dbbox

        return dbbox
Пример #4
0
    def calc_cell_extents(self, cellnum):
        """
        Calculate discrete bounding box of a cell

        Note, the extents return is in the internal coordinates with negated Y-values
        """
        ## Calculate cell level
        level = 0
        while cellnum > totcells_at_level(level):
            level = level + 1

        n = 2**level  # Number of rows/cols

        lbb = self._dbbox
        layerwidth = lbb.width
        layerheight = lbb.height
        layersize = N.array([layerwidth, layerheight])

        relcnum = cellnum - (totcells_at_level(level - 1) + 1)

        cellsize = layersize / n

        if relcnum < n * n:
            mincorner = N.array([relcnum % n, relcnum / n]) * cellsize
            maxcorner = mincorner + cellsize
        else:
            relcnum = relcnum - n * n
            mincorner = N.array([relcnum % (n + 1), relcnum /
                                 (n + 1)]) * cellsize - cellsize / 2
            maxcorner = mincorner + layersize / n

            mincorner[N.where(mincorner < 0)] = 0
            maxcorner[0] = min(maxcorner[0], layerwidth)
            maxcorner[1] = min(maxcorner[1], layerheight)

        return Rec(mincorner + lbb.c1, maxcorner + lbb.c1)
Пример #5
0
def get_best_cell(bounds, r, max_cell_level):
    max_cell_level += 1  # To take account of the "shifted" level
    i = 1 << max_cell_level

    # Normalise rectangle's coordinates to within 0 to i-1
    v = (bounds.s - bounds.n) / i  # vertical normalisation factor
    h = (bounds.e - bounds.w) / i  # horizontal normalisation factor
    n = (r.n - bounds.n) / v
    s = (r.s - bounds.n) / v
    w = (r.w - bounds.w) / h
    e = (r.e - bounds.w) / h

    # Find the best "direct" cell (without half cell shifting)
    m = (n ^ s) | (w ^ e)
    # The most significant 1 (as a bit) in m indicates cell level
    # Now compute cell number
    l = 1 << (max_cell_level - 1)
    cell = 1
    shift = max_cell_level
    stride = 1
    i = -3  # compensation for the lack of Level 0' (shifted)
    while l > 1 and (l & m) == 0:
        cell = i + stride * stride + (stride + 1)**2
        i = cell
        stride <<= 1
        l >>= 1
        shift -= 1

    # Now l equals 1 << (level - 1) for unshifted cells
    # Compute the number of the best unshifted cell
    best_cell = cell + (n >> shift) * stride + (w >> shift)
    cell_size = 1 << shift
    cell_offset = 0
    cell_level = max_cell_level - shift

    # Check if a shifted cell of the same or more detailed level
    # can be used
    if cell == 1:  # Skip Level 0'
        l >>= 1
        shift -= 1
        stride <<= 1
        cell = 2

    while l > 0:
        cell += stride * stride
        m = ((n + l) ^ (s + l)) | ((w + l) ^ (e + l))
        if m < 2 * l:  # found a better cell
            best_cell = cell + ((n + l) >> shift) * (stride + 1) \
                             + ((w + l) >> shift)
            cell_size = 1 << shift
            cell_offset = l
            cell_level = max_cell_level - shift
        l >>= 1
        cell += (stride + 1)**2
        stride <<= 1
        shift -= 1

    # layer's bounding rectangle
    normn = ((n + cell_offset) & -cell_size) - cell_offset
    normw = ((w + cell_offset) & -cell_size) - cell_offset

    n = max(normn * v, 0)
    w = max(normw * h, 0)
    s = min((normn + cell_size) * v, bounds.s - bounds.n) - 1
    e = min((normw + cell_size) * h, bounds.e - bounds.w) - 1
    border = Rec((s, w), (n, e))

    # Return cell number, level, and border
    return int(best_cell), cell_level, border
Пример #6
0
    def __init__(self, mapdirobj = None, gpsimage = True, maptype = MapTypeNormal,
                 mapnumber=0, bigendian = False, inifile = None, hasmultiplemaps=True):
        self.gpsimage = gpsimage
        self.maptype = maptype
        self._mapnumber = mapnumber

        if mapdirobj == None:
            self.mapdir = mapdir.MapDirectory()
        else:
            if not isinstance(mapdirobj, mapdir.MapDirectory):
                raise ValueError("mapdirobj should be a MapDirectory object")
            self.mapdir = mapdirobj

        self.name = "Map"

        self.mode = None      # Open mode ['r','w','a']

        self.debug=False

        self.has_zip = True

        self.has_marine = (maptype == MapTypeStreetRoute)

        self._inifile = inifile

        self.inmemory = False ## If true all processing will be done in memory

        if maptype == MapTypeStreetRoute:
            self.routingcfg = routing.RoutingConfig()
        else:
            self.routingcfg = None

        ## Set endian
        self.bigendian = bigendian

        # Groups
        self._poigroup=None
        self.groups=[]
        self._searchgroups = [] ## Searchable group indices

        # Tables
        if maptype == MapTypeStreetRoute:
            self._ziptables = (0,1,0,0)
        else:
            self._ziptables = (0,0)
        self._marinetables = (0,1,0,1)

        ## Bounding box and bounding rect
        self._bboxrec = None
        self._boundrec = Rec((-198.316818, -99.475197), (198.316818,  99.475197))

        ## Resolution and reference point
        self._scale = self.defaultscale
        self._refpoint = N.array([0.0, 0.0])

        ## Config file
        self._cfg = ConfigParserUpper()
        self._initcfg()

        ## Layer and POI config
        self._laycfg = LayerConfig()
        self._poiconfig = POILayerConfig()
        
        ## Database
        self._db = None

        ## Other parameters
        otherparameters = (
            ## Name, default value, description
            ('startscale', 4500.0, 'Start scale'),
            ('laycolor', 0, 'Unknown'),
            ('copyrightholders', ['Unknown'], 'Copyright holders'),
            )

        ## Create properties for these parameters
        for param in otherparameters:
            setattr(self, '_' + param[0], param[1])
            getfunc = lambda self, val: self.set_parameter('_'+param[0])
            setfunc = lambda self, val: self.set_parameter('_'+param[0], val)
            setattr(self.__class__, param[0], property(getfunc, setfunc, doc=param[2]))

        ## Update config
        self._updatecfg()

        ## hasmultiplemaps is True if mapdir can have multiple maps with prefixes before their files
        self.hasmultiplemaps = hasmultiplemaps
Пример #7
0
    def open(self, mode='r'):
        if self.mode != None:
            return None

        self.mode = mode

        if mode == 'w':
            if self.gpsimage:
                if self._inifile == None:
                    self._inifile = self.mapnumstr + 'map.ini'

                ## Create database
                self._db = Database(self.mapdir, 'db' + self.mapnumstr, mode, self.bigendian)

                ## Create zip table
                if self.has_zip:
                    buildziprecord(self._db,
                                   zipfilename = self.mapnumstr + 'z.dat',
                                   auxfilename = self.mapnumstr + 'cn.dat',
                                   extended = self.maptype == MapTypeStreetRoute)

                ## Create marine table
                if self.has_marine:
                    buildmarinerecord(self._db,
                                   filenameprefix = self.mapnumstr)

                ## Create basic groups
                if self.maptype == MapTypeStreetRoute:
                    roads = GroupStreet(self, name=self.mapnumstr + "_Roads")
                else:
                    roads = GroupNormal(self, name=self.mapnumstr + "_Roads")
                roads.searchable = True
                self.addGroup(roads)
                self.addGroup(GroupNormal(self, name=self.mapnumstr + "_Railroads"))
                self.addGroup(GroupNormal(self, name=self.mapnumstr + "_Hydrography"))
                self.addGroup(GroupNormal(self, name=self.mapnumstr + "_Parks"))

            else:
                if self._inifile == None:
                    self._inifile = 'map.ini'
        elif mode in ('r','a'):
            ## Find ini file
            if self._inifile == None:
                filelist = self.mapdir.listdir()
                possibleinifiles = ('map.ini', self.mapnumstr + 'map.ini', 'lay_info.ini')
                found = False
                for filename in possibleinifiles:
                    if filename in filelist:
                        self._inifile = filename
                        found = True
                        break
                if not found:
                    raise ValueError('Could not find ini-file')

            self._cfg.readfp(IniFileFilter(self.mapdir.open(self._inifile)))

            # Get map type
            if self._cfg.has_option('MAP_INFO', 'MAPTYPE'):
                self.maptype = self._cfg.get("MAP_INFO", "MAPTYPE")

            # Get bounding box
            if self._cfg.has_option('MAP_INFO', 'BND_BOX'):
                bbox = map(float, self._cfg.get("MAP_INFO", "BND_BOX").split(" "))
                self._bboxrec = Rec([bbox[0],bbox[2]], [bbox[1], bbox[3]])

            # Get map name
            self.name = self._cfg.get('MAP_INFO', 'MAP_NAME')
#            self.date = self._cfg.get('MAP_INFO', 'MAP_DATE')

            self._laycfg.setupfromcfg(self._cfg, self)
            
            # Find database path
            dbname = self._cfg.get("LAYERS","DB_NAME")
            dbname = re.sub('\\\\', os.sep, dbname)

            # Since Windows is case insensitive, try to match the path case insensitive
            plist=dbname.split(os.sep)
            for i in range(0,len(plist)-2):
                path=os.sep.join(plist[0:i+1])
                if len(path)>0:
                    hits=[d for d in self.mapdir.listdir(path) if d.lower() == plist[i+1].lower()]
                    if len(hits)==0:
                        raise ValueError("Couldnt find database")
                    plist[i+1]=hits[0]
            dbname = os.sep.join(plist)

            if dbname:
                self._db = Database(self.mapdir, dbname, self.mode, self.bigendian)

            # Read groups
            if self.debug:
                print "Groups:"
            for i in range(0,self._cfg.getint("GROUPS","NUMBER")):
                thegroup = groupFactory(self, i, self._cfg, self._db)
                self.groups.append(thegroup)
                thegroup.initFromIni(self._cfg)

            # Read POI file and POI layers
            if self._cfg.has_section("POI"):
                poi_ini = self._cfg.get("POI","POI_CONFIG")
                self.poicfg = ConfigParserUpper()
                if self.mapdir.isfile(poi_ini):
                    self.poicfg.readfp(IniFileFilter(self.mapdir.open(poi_ini)))

                    if self.poicfg.has_section("LAYERS"):
                        self._poigroup = POIGroup(self)

                    self._poiconfig.setupfromcfg(self.poicfg, self)

            # Read routing info
            if self.maptype == MapTypeStreetRoute:
                self.routingcfg = routing.RoutingConfig()
                self.routingcfg.setupfromcfg(self._cfg, self)

            # Read unpack tables
            if self._cfg.has_section('PACK_LAYS'):
                i = 0

                while self._cfg.has_option('PACK_LAYS', str(i)):
                    fields = self._cfg.get('PACK_LAYS', str(i)).split(' ')

                    filename = fields[0]
                    n = int(fields[1])

                    layernumbers = map(int, fields[2:])

                    assert len(layernumbers) == n

                    for layernumber in layernumbers:
                        self.getLayerByIndex(layernumber).setUnpackTable(filename)
                    
                    i += 1
Пример #8
0
 def set_bbox(self, points):
     self.bboxrec = Rec(tuple(points[0]), tuple(points[1]))