Exemple #1
0
def map_history(request, level, mode, filetype):
    if not request.user.is_superuser:
        raise PermissionDenied
    level = get_object_or_404(Level, pk=level)

    if mode == 'composite' and level.on_top_of_id is not None:
        raise Http404

    history = MapHistory.open_level(level.pk, mode)
    if filetype == 'png':
        response = HttpResponse(content_type='image/png')
        history.to_image().save(response, format='PNG')
    elif filetype == 'data':
        response = HttpResponse(content_type='application/octet-stream')
        history.write(response)
    else:
        raise ValueError
    response['Cache-Control'] = 'no-cache'
    return response
Exemple #2
0
def map_history(request, level, mode, filetype):
    if not request.user.is_superuser:
        raise PermissionDenied
    level = get_object_or_404(Level, pk=level)

    if mode == 'composite' and level.on_top_of_id is not None:
        raise Http404

    history = MapHistory.open_level(level.pk, mode)
    if filetype == 'png':
        response = HttpResponse(content_type='image/png')
        history.to_image().save(response, format='PNG')
    elif filetype == 'data':
        response = HttpResponse(content_type='application/octet-stream')
        history.write(response)
    else:
        raise ValueError
    response['Cache-Control'] = 'no-cache'
    return response
Exemple #3
0
    def read(cls, f):
        f = TarFile.open(fileobj=f)
        files = {info.name: info for info in f.getmembers()}

        bounds = tuple(
            i / 100
            for i in struct.unpack('<IIII',
                                   f.extractfile(files['bounds']).read()))

        levels = {}
        for filename in files:
            if not filename.startswith('history_'):
                continue
            level_id = int(filename[8:])
            levels[level_id] = CachePackageLevel(
                history=MapHistory.read(
                    f.extractfile(files['history_%d' % level_id])),
                restrictions=AccessRestrictionAffected.read(
                    f.extractfile(files['restrictions_%d' % level_id])))

        return cls(bounds, levels)
Exemple #4
0
    def rebuild():
        levels = tuple(Level.objects.prefetch_related('altitudeareas', 'buildings', 'doors', 'spaces',
                                                      'spaces__holes', 'spaces__areas', 'spaces__columns',
                                                      'spaces__obstacles', 'spaces__lineobstacles',
                                                      'spaces__groups', 'spaces__ramps'))

        package = CachePackage(bounds=tuple(chain(*Source.max_bounds())))

        # first pass in reverse to collect some data that we need later
        single_level_geoms = {}
        interpolators = {}
        last_interpolator = None
        altitudeareas_above = []
        for level in reversed(levels):
            single_level_geoms[level.pk] = LevelGeometries.build_for_level(level, altitudeareas_above)

            # ignore intermediate levels in this pass
            if level.on_top_of_id is not None:
                altitudeareas_above.extend(single_level_geoms[level.pk].altitudeareas)
                altitudeareas_above.sort(key=operator.attrgetter('altitude'))
                continue

            # create interpolator to create the pieces that fit multiple layers together
            if last_interpolator is not None:
                interpolators[level.pk] = last_interpolator

            coords = deque()
            values = deque()
            for area in single_level_geoms[level.pk].altitudeareas:
                new_coords = np.vstack(tuple(np.array(ring.coords) for ring in get_rings(area.geometry)))
                coords.append(new_coords)
                values.append(np.full((new_coords.shape[0], 1), fill_value=area.altitude))

            if coords:
                last_interpolator = NearestNDInterpolator(np.vstack(coords), np.vstack(values))
            else:
                last_interpolator = NearestNDInterpolator(np.array([[0, 0]]), np.array([float(level.base_altitude)]))

        for i, level in enumerate(levels):
            print("we are at level_id:" +  str(level.id) + " level slug: "+level.slug)
            print("on top of:" +  str(level.on_top_of_id))
            if level.on_top_of_id is not None:
                continue
            print("we continue")
            map_history = MapHistory.open_level(level.pk, 'base')

            sublevels = tuple(sublevel for sublevel in levels
                              if sublevel.on_top_of_id == level.pk or sublevel.base_altitude <= level.base_altitude)
            print("sublevels" + str([l.slug for l in sublevels]))
            level_crop_to = {}

            # choose a crop area for each level. non-intermediate levels (not on_top_of) below the one that we are
            # currently rendering will be cropped to only render content that is visible through holes indoors in the
            # levels above them.
            crop_to = None
            primary_level_count = 0
            main_level_passed = 0
            lowest_important_level = None
            last_lower_bound = None
            for sublevel in reversed(sublevels):
                geoms = single_level_geoms[sublevel.pk]

                if geoms.holes is not None:
                    primary_level_count += 1

                # get lowest intermediate level directly below main level

                if not main_level_passed:
                    if geoms.pk == level.pk:
                        main_level_passed = 1
                else:
                    if not sublevel.on_top_of_id:
                        main_level_passed += 1
                if main_level_passed < 2:
                    lowest_important_level = sublevel

                # make upper bounds
                if geoms.on_top_of_id is None:
                    if last_lower_bound is None:
                        geoms.upper_bound = geoms.max_altitude+geoms.max_height
                    else:
                        geoms.upper_bound = last_lower_bound
                    last_lower_bound = geoms.lower_bound

                # set crop area if we area on the second primary layer from top or below
                level_crop_to[sublevel.pk] = Cropper(crop_to if primary_level_count > 1 else None)

                if geoms.holes is not None:
                    if crop_to is None:
                        crop_to = geoms.holes
                    else:
                        crop_to = crop_to.intersection(geoms.holes)

                    if crop_to.is_empty:
                        break

            render_data = LevelRenderData()
            render_data.base_altitude = level.base_altitude
            render_data.lowest_important_level = lowest_important_level.pk
            access_restriction_affected = {}

            # go through sublevels, get their level geometries and crop them
            lowest_important_level_passed = False
            for sublevel in reversed(sublevels):
                try:
                    crop_to = level_crop_to[sublevel.pk]
                except KeyError:
                    print ("in except, sublevel_pk: " + str(sublevel.pk))
                    break;

                old_geoms = single_level_geoms[sublevel.pk]

                if render_data.lowest_important_level == sublevel.pk:
                    lowest_important_level_passed = True

                if old_geoms.holes and render_data.darken_area is None and lowest_important_level_passed:
                    render_data.darken_area = old_geoms.holes

                if crop_to.geometry is not None:
                    map_history.composite(MapHistory.open_level(sublevel.pk, 'base'), crop_to.geometry)
                elif level.pk != sublevel.pk:
                    map_history.composite(MapHistory.open_level(sublevel.pk, 'base'), None)

                new_geoms = LevelGeometries()
                new_geoms.buildings = crop_to.intersection(old_geoms.buildings)
                if old_geoms.on_top_of_id is None:
                    new_geoms.holes = crop_to.intersection(old_geoms.holes)
                new_geoms.doors = crop_to.intersection(old_geoms.doors)
                new_geoms.walls = crop_to.intersection(old_geoms.walls)
                new_geoms.all_walls = crop_to.intersection(old_geoms.all_walls)
                new_geoms.short_walls = tuple((altitude, geom) for altitude, geom in tuple(
                    (altitude, crop_to.intersection(geom))
                    for altitude, geom in old_geoms.short_walls
                ) if not geom.is_empty)

                for altitudearea in old_geoms.altitudeareas:
                    new_geometry = crop_to.intersection(altitudearea.geometry)
                    if new_geometry.is_empty:
                        continue
                    new_geometry_prep = prepared.prep(new_geometry)

                    new_altitudearea = AltitudeAreaGeometries()
                    new_altitudearea.geometry = new_geometry
                    new_altitudearea.altitude = altitudearea.altitude
                    new_altitudearea.altitude2 = altitudearea.altitude2
                    new_altitudearea.point1 = altitudearea.point1
                    new_altitudearea.point2 = altitudearea.point2

                    new_colors = {}
                    for color, areas in altitudearea.colors.items():
                        new_areas = {}
                        for access_restriction, area in areas.items():
                            if not new_geometry_prep.intersects(area):
                                continue
                            new_area = new_geometry.intersection(area)
                            if not new_area.is_empty:
                                new_areas[access_restriction] = new_area
                        if new_areas:
                            new_colors[color] = new_areas
                    new_altitudearea.colors = new_colors

                    new_altitudearea_obstacles = {}
                    for height, height_obstacles in altitudearea.obstacles.items():
                        new_height_obstacles = {}
                        for color, color_obstacles in height_obstacles.items():
                            new_color_obstacles = []
                            for obstacle in color_obstacles:
                                if new_geometry_prep.intersects(obstacle):
                                    new_color_obstacles.append(obstacle.intersection(altitudearea.geometry))
                            if new_color_obstacles:
                                new_height_obstacles[color] = new_color_obstacles
                        if new_height_obstacles:
                            new_altitudearea_obstacles[height] = new_height_obstacles
                    new_altitudearea.obstacles = new_altitudearea_obstacles

                    new_geoms.altitudeareas.append(new_altitudearea)

                if new_geoms.walls.is_empty and not new_geoms.altitudeareas:
                    continue

                new_geoms.ramps = tuple(
                    ramp for ramp in (crop_to.intersection(ramp) for ramp in old_geoms.ramps)
                    if not ramp.is_empty
                )

                new_geoms.heightareas = tuple(
                    (area, height) for area, height in ((crop_to.intersection(area), height)
                                                        for area, height in old_geoms.heightareas)
                    if not area.is_empty
                )

                new_geoms.affected_area = unary_union((
                    *(altitudearea.geometry for altitudearea in new_geoms.altitudeareas),
                    crop_to.intersection(new_geoms.walls.buffer(1))
                ))

                for access_restriction, area in old_geoms.access_restriction_affected.items():
                    new_area = crop_to.intersection(area)
                    if not new_area.is_empty:
                        access_restriction_affected.setdefault(access_restriction, []).append(new_area)

                new_geoms.restricted_spaces_indoors = {}
                for access_restriction, area in old_geoms.restricted_spaces_indoors.items():
                    new_area = crop_to.intersection(area)
                    if not new_area.is_empty:
                        new_geoms.restricted_spaces_indoors[access_restriction] = new_area

                new_geoms.restricted_spaces_outdoors = {}
                for access_restriction, area in old_geoms.restricted_spaces_outdoors.items():
                    new_area = crop_to.intersection(area)
                    if not new_area.is_empty:
                        new_geoms.restricted_spaces_outdoors[access_restriction] = new_area

                new_geoms.pk = old_geoms.pk
                new_geoms.on_top_of_id = old_geoms.on_top_of_id
                new_geoms.short_label = old_geoms.short_label
                new_geoms.base_altitude = old_geoms.base_altitude
                new_geoms.default_height = old_geoms.default_height
                new_geoms.door_height = old_geoms.door_height
                new_geoms.min_altitude = (min(area.altitude for area in new_geoms.altitudeareas)
                                          if new_geoms.altitudeareas else new_geoms.base_altitude)
                new_geoms.max_altitude = (max(area.altitude for area in new_geoms.altitudeareas)
                                          if new_geoms.altitudeareas else new_geoms.base_altitude)
                new_geoms.max_height = (min(height for area, height in new_geoms.heightareas)
                                        if new_geoms.heightareas else new_geoms.default_height)
                new_geoms.lower_bound = old_geoms.lower_bound
                new_geoms.upper_bound = old_geoms.upper_bound

                new_geoms.build_mesh(interpolators.get(level.pk) if sublevel.pk == level.pk else None)

                render_data.levels.append(new_geoms)

            access_restriction_affected = {
                access_restriction: unary_union(areas)
                for access_restriction, areas in access_restriction_affected.items()
            }

            access_restriction_affected = AccessRestrictionAffected.build(access_restriction_affected)
            access_restriction_affected.save_level(level.pk, 'composite')

            map_history.save_level(level.pk, 'composite')

            package.add_level(level.pk, map_history, access_restriction_affected)

            render_data.save(level.pk)

        package.save_all()
Exemple #5
0
    def rebuild():
        levels = tuple(Level.objects.prefetch_related('altitudeareas', 'buildings', 'doors', 'spaces',
                                                      'spaces__holes', 'spaces__areas', 'spaces__columns',
                                                      'spaces__obstacles', 'spaces__lineobstacles',
                                                      'spaces__groups', 'spaces__ramps'))

        package = CachePackage(bounds=tuple(chain(*Source.max_bounds())))

        # first pass in reverse to collect some data that we need later
        single_level_geoms = {}
        interpolators = {}
        last_interpolator = None
        altitudeareas_above = []
        for level in reversed(levels):
            single_level_geoms[level.pk] = LevelGeometries.build_for_level(level, altitudeareas_above)

            # ignore intermediate levels in this pass
            if level.on_top_of_id is not None:
                altitudeareas_above.extend(single_level_geoms[level.pk].altitudeareas)
                altitudeareas_above.sort(key=operator.attrgetter('altitude'))
                continue

            # create interpolator to create the pieces that fit multiple layers together
            if last_interpolator is not None:
                interpolators[level.pk] = last_interpolator

            coords = deque()
            values = deque()
            for area in single_level_geoms[level.pk].altitudeareas:
                new_coords = np.vstack(tuple(np.array(ring.coords) for ring in get_rings(area.geometry)))
                coords.append(new_coords)
                values.append(np.full((new_coords.shape[0], 1), fill_value=area.altitude))

            if coords:
                last_interpolator = NearestNDInterpolator(np.vstack(coords), np.vstack(values))
            else:
                last_interpolator = NearestNDInterpolator(np.array([[0, 0]]), np.array([float(level.base_altitude)]))

        for i, level in enumerate(levels):
            if level.on_top_of_id is not None:
                continue

            map_history = MapHistory.open_level(level.pk, 'base')

            sublevels = tuple(sublevel for sublevel in levels
                              if sublevel.on_top_of_id == level.pk or sublevel.base_altitude <= level.base_altitude)

            level_crop_to = {}

            # choose a crop area for each level. non-intermediate levels (not on_top_of) below the one that we are
            # currently rendering will be cropped to only render content that is visible through holes indoors in the
            # levels above them.
            crop_to = None
            primary_level_count = 0
            main_level_passed = 0
            lowest_important_level = None
            last_lower_bound = None
            for sublevel in reversed(sublevels):
                geoms = single_level_geoms[sublevel.pk]

                if geoms.holes is not None:
                    primary_level_count += 1

                # get lowest intermediate level directly below main level

                if not main_level_passed:
                    if geoms.pk == level.pk:
                        main_level_passed = 1
                else:
                    if not sublevel.on_top_of_id:
                        main_level_passed += 1
                if main_level_passed < 2:
                    lowest_important_level = sublevel

                # make upper bounds
                if geoms.on_top_of_id is None:
                    if last_lower_bound is None:
                        geoms.upper_bound = geoms.max_altitude+geoms.max_height
                    else:
                        geoms.upper_bound = last_lower_bound
                    last_lower_bound = geoms.lower_bound

                # set crop area if we area on the second primary layer from top or below
                level_crop_to[sublevel.pk] = Cropper(crop_to if primary_level_count > 1 else None)

                if geoms.holes is not None:
                    if crop_to is None:
                        crop_to = geoms.holes
                    else:
                        crop_to = crop_to.intersection(geoms.holes)

                    if crop_to.is_empty:
                        break

            render_data = LevelRenderData()
            render_data.base_altitude = level.base_altitude
            render_data.lowest_important_level = lowest_important_level.pk
            access_restriction_affected = {}

            # go through sublevels, get their level geometries and crop them
            lowest_important_level_passed = False
            for sublevel in sublevels:
                try:
                    crop_to = level_crop_to[sublevel.pk]
                except KeyError:
                    break

                old_geoms = single_level_geoms[sublevel.pk]

                if render_data.lowest_important_level == sublevel.pk:
                    lowest_important_level_passed = True

                if old_geoms.holes and render_data.darken_area is None and lowest_important_level_passed:
                    render_data.darken_area = old_geoms.holes

                if crop_to.geometry is not None:
                    map_history.composite(MapHistory.open_level(sublevel.pk, 'base'), crop_to.geometry)
                elif level.pk != sublevel.pk:
                    map_history.composite(MapHistory.open_level(sublevel.pk, 'base'), None)

                new_geoms = LevelGeometries()
                new_geoms.buildings = crop_to.intersection(old_geoms.buildings)
                if old_geoms.on_top_of_id is None:
                    new_geoms.holes = crop_to.intersection(old_geoms.holes)
                new_geoms.doors = crop_to.intersection(old_geoms.doors)
                new_geoms.walls = crop_to.intersection(old_geoms.walls)
                new_geoms.all_walls = crop_to.intersection(old_geoms.all_walls)
                new_geoms.short_walls = tuple((altitude, geom) for altitude, geom in tuple(
                    (altitude, crop_to.intersection(geom))
                    for altitude, geom in old_geoms.short_walls
                ) if not geom.is_empty)

                for altitudearea in old_geoms.altitudeareas:
                    new_geometry = crop_to.intersection(altitudearea.geometry)
                    if new_geometry.is_empty:
                        continue
                    new_geometry_prep = prepared.prep(new_geometry)

                    new_altitudearea = AltitudeAreaGeometries()
                    new_altitudearea.geometry = new_geometry
                    new_altitudearea.altitude = altitudearea.altitude
                    new_altitudearea.altitude2 = altitudearea.altitude2
                    new_altitudearea.point1 = altitudearea.point1
                    new_altitudearea.point2 = altitudearea.point2

                    new_colors = {}
                    for color, areas in altitudearea.colors.items():
                        new_areas = {}
                        for access_restriction, area in areas.items():
                            if not new_geometry_prep.intersects(area):
                                continue
                            new_area = new_geometry.intersection(area)
                            if not new_area.is_empty:
                                new_areas[access_restriction] = new_area
                        if new_areas:
                            new_colors[color] = new_areas
                    new_altitudearea.colors = new_colors

                    new_altitudearea.obstacles = {key: tuple(new_geometry.intersection(obstacle)
                                                             for obstacle in height_obstacles
                                                             if new_geometry_prep.intersects(obstacle))
                                                  for key, height_obstacles in altitudearea.obstacles.items()}
                    new_altitudearea.obstacles = {height: height_obstacles
                                                  for height, height_obstacles in new_altitudearea.obstacles.items()
                                                  if height_obstacles}

                    new_geoms.altitudeareas.append(new_altitudearea)

                if new_geoms.walls.is_empty and not new_geoms.altitudeareas:
                    continue

                new_geoms.ramps = tuple(
                    ramp for ramp in (crop_to.intersection(ramp) for ramp in old_geoms.ramps)
                    if not ramp.is_empty
                )

                new_geoms.heightareas = tuple(
                    (area, height) for area, height in ((crop_to.intersection(area), height)
                                                        for area, height in old_geoms.heightareas)
                    if not area.is_empty
                )

                new_geoms.affected_area = unary_union((
                    *(altitudearea.geometry for altitudearea in new_geoms.altitudeareas),
                    crop_to.intersection(new_geoms.walls.buffer(1))
                ))

                for access_restriction, area in old_geoms.access_restriction_affected.items():
                    new_area = crop_to.intersection(area)
                    if not new_area.is_empty:
                        access_restriction_affected.setdefault(access_restriction, []).append(new_area)

                new_geoms.restricted_spaces_indoors = {}
                for access_restriction, area in old_geoms.restricted_spaces_indoors.items():
                    new_area = crop_to.intersection(area)
                    if not new_area.is_empty:
                        new_geoms.restricted_spaces_indoors[access_restriction] = new_area

                new_geoms.restricted_spaces_outdoors = {}
                for access_restriction, area in old_geoms.restricted_spaces_outdoors.items():
                    new_area = crop_to.intersection(area)
                    if not new_area.is_empty:
                        new_geoms.restricted_spaces_outdoors[access_restriction] = new_area

                new_geoms.pk = old_geoms.pk
                new_geoms.on_top_of_id = old_geoms.on_top_of_id
                new_geoms.short_label = old_geoms.short_label
                new_geoms.base_altitude = old_geoms.base_altitude
                new_geoms.default_height = old_geoms.default_height
                new_geoms.door_height = old_geoms.door_height
                new_geoms.min_altitude = (min(area.altitude for area in new_geoms.altitudeareas)
                                          if new_geoms.altitudeareas else new_geoms.base_altitude)
                new_geoms.max_altitude = (max(area.altitude for area in new_geoms.altitudeareas)
                                          if new_geoms.altitudeareas else new_geoms.base_altitude)
                new_geoms.max_height = (min(height for area, height in new_geoms.heightareas)
                                        if new_geoms.heightareas else new_geoms.default_height)
                new_geoms.lower_bound = old_geoms.lower_bound
                new_geoms.upper_bound = old_geoms.upper_bound

                new_geoms.build_mesh(interpolators.get(level.pk) if sublevel.pk == level.pk else None)

                render_data.levels.append(new_geoms)

            access_restriction_affected = {
                access_restriction: unary_union(areas)
                for access_restriction, areas in access_restriction_affected.items()
            }

            access_restriction_affected = AccessRestrictionAffected.build(access_restriction_affected)
            access_restriction_affected.save_level(level.pk, 'composite')

            map_history.save_level(level.pk, 'composite')

            package.add_level(level.pk, map_history, access_restriction_affected)

            render_data.save(level.pk)

        package.save_all()