Ejemplo n.º 1
0
 def move(self, direction: int):
     status = self.program.enter_input(direction)[0][0]
     delta = {
         1: Coords(0, 1),
         2: Coords(0, -1),
         3: Coords(-1, 0),
         4: Coords(1, 0),
     }[direction]
     signs = {
         1: '^',
         2: 'v',
         3: '<',
         4: '>',
     }
     if status == 0:
         self.map[self.pos + delta] = '\u2588'
     elif status == 1:
         self.mark(delta, signs[direction])
         self.pos += delta
     else:
         self.mark(delta, signs[direction])
         self.pos += delta
         self.map[self.pos] = 'O'
     self.min_x = min(self.pos.x, self.min_x)
     self.max_x = max(self.pos.x, self.max_x)
     self.min_y = min(self.pos.y, self.min_y)
     self.max_y = max(self.pos.y, self.max_y)
     return status
Ejemplo n.º 2
0
    def mouse_draw(self,x,y,action):
        """Process mouse events during interactive drawing.

        On PRESS, do nothing.
        On MOVE, do nothing.
        On RELEASE, add the point to the point list.
        """
        if action == PRESS:
            self.makeCurrent()
            self.update()
            if self.trackfunc:
                print "ENABLE TRACKING"
                pf.canvas.camera.setTracking(True)

        elif action == MOVE:
            if pf.app.hasPendingEvents():
                return
            if self.trackfunc:
                self.trackfunc(x,y,self.zplane)
                #pf.app.processEvents()
            if self.previewfunc:
                self.swapBuffers()
                self.drawn = self.unProject(x,y,self.zplane)
                self.drawn = Coords(self.drawn).reshape(-1,3)
                self.previewfunc(Coords.concatenate([self.drawing,self.drawn]),self.drawmode)
                self.swapBuffers()
            
        elif action == RELEASE:
            self.drawn = self.unProject(x,y,self.zplane)
            self.selection_busy = False
Ejemplo n.º 3
0
 def __init__(self, program: StatefulIntcode):
     self.program = program
     self.pos = Coords(0, 0)
     self.map = {Coords(0, 0): 'S'}
     self.min_x = 0
     self.max_x = 0
     self.min_y = 0
     self.max_y = 0
     self.mode = 'map'
     self.counter = 0
     self.max = 0
Ejemplo n.º 4
0
 def _set_ally_fountain_loc(self):
     if ColorLib.match_color_screen(
             self.img,
         (GameCoords.bottom_left_base.x, GameCoords.bottom_left_base.y),
             GameCoords.bottom_left_base.colors[0], 15, -15):
         self._my_fountain_coords = GameCoords.bottom_fountain
         self._my_team_side = 'bot'
         self._general_enemy_dir_coords = Coords(x=870, y=180)
     else:
         self._my_fountain_coords = GameCoords.top_fountain
         self._my_team_side = 'top'
         self._general_enemy_dir_coords = Coords(x=380, y=470)
Ejemplo n.º 5
0
 def __init__(self):
     self.length = 0.0
     self.lines = []
     self.current_pos = 0.0
     self.current_point = Point(0, 0, 0)
     self.current_line_index = 0
     self.tools = {}  # dictionary, tool id to Tool object
     self.current_tool = 1
     self.rapid = True
     self.mm_per_sec = 50.0
     self.running = False
     self.coords = Coords(0, 0, 0, 0, 0, 0)
     self.in_cut_to_position = False
Ejemplo n.º 6
0
    def idraw(self,mode='point',npoints=-1,zplane=0.,func=None,coords=None,preview=False):
        """Interactively draw on the canvas.

        This function allows the user to interactively create points in 3D
        space and collects the subsequent points in a Coords object. The
        interpretation of these points is left to the caller.
        
        - `mode`: one of the drawing modes, specifying the kind of objects you
          want to draw. This is passed to the specified `func`.
        - `npoints`: If -1, the user can create any number of points. When >=0,
          the function will return when the total number of points in the
          collection reaches the specified value.
        - `zplane`: the depth of the z-plane on which the 2D drawing is done.
        - `func`: a function that is called after each atomic drawing
          operation. It is typically used to draw a preview using the current
          set of points. The function is passed the current Coords and the
          `mode` as arguments.
        - `coords`: an initial set of coordinates to which the newly created
          points should be added. If specified, `npoints` also counts these
          initial points.
        - `preview`: **Experimental** If True, the preview funcion will also
          be called during mouse movement with a pressed button, allowing to
          preview the result before a point is created.
        
        The drawing operation is finished when the number of requested points
        has been reached, or when the user clicks the right mouse button or
        hits 'ENTER'.
        The return value is a (n,3) shaped Coords array.
        """
        self.draw_canceled = False
        self.start_draw(mode,zplane,coords)
        try:
            if preview:
                self.previewfunc = func
            else:
                self.previewfunc = None

            while not self.draw_canceled:
                self.wait_selection()
                if not self.draw_canceled:
                    self.drawn = Coords(self.drawn).reshape(-1,3)
                    self.drawing = Coords.concatenate([self.drawing,self.drawn])
                    if func:
                        func(self.drawing,self.drawmode)
                if npoints > 0 and len(self.drawing) >= npoints:
                    self.accept_draw()                
            if func and not self.draw_accepted:
                func(self.drawing,self.drawmode)
        finally:
            self.finish_draw()
        return self.drawing
Ejemplo n.º 7
0
    def regerateLevel(self, depth):
        ls = self.getLevelSize(depth)
        w = ls + randint(-depth - 1, depth + 1) * 1
        h = ls + randint(-depth - 1, depth + 1) * 1
        self.size = ls

        self.grid = self.genLevel(depth, depth)
        self.widthHeight = Coords(w, h)
        self.depth = depth

        self.visibilityGrid = list(self.genVisibilityGrid(ls))

        self.rooms, self.junctions = self.generateDungeonRooms(
            w, h, 0.06, 0.025)

        self.assignTerrain(w, h)
        self.stairs = self.placeStairs()
        self.itemsOnFloor = []

        self.avalibleSpecies = getFilteredSpecies(depth)

        self.itemsAvalibleForDepth = getListOfItemsSuitbleForDepth(depth)
        self.itemsByTypeAvalibleForDepth = {
            k: getSuitbleItemsByType(self.itemsAvalibleForDepth, k)
            for k in ALL_IMPORTANT_ITEM_TYPES
        }

        self.player = None
Ejemplo n.º 8
0
    def __ballEffect(self, gl, user, targetCo, runEffect):
        eList = gl.getEntitiesInLineOfFire(user,
                                           targetCo,
                                           maxRange=self.maxRange)
        #eList = gl.getEntitiesBetweenPoints(user.co, targetCo, maxEntities=10000, maxRange=self.maxRange)
        ip = (user.co - targetCo).normalize()
        impactPoint = Coords(round(ip[0] * self.maxRange),
                             round(ip[1] * self.maxRange))
        if len(eList) > 0:

            for e in eList:
                dist = user.co.distance(e.co)
                if rollAttack(2, 6) - dist > 0:  #to hit roll
                    impactPoint = e.co

                    break
            if self.radius > 0:
                # entitiesInBlastArea = list(filter(lambda x: not gl.checkForObstructionBetweenPoints(x.co, impactPoint, maxRange=self.radius) and x.co != impactPoint, gl.allEntities))
                entitiesInBlastArea = list(
                    (e for e in gl.allEntities if e.co != impactPoint
                     and not gl.checkForObstructionBetweenPoints(
                         e.co, impactPoint, maxRange=self.radius)))
                map(lambda x: runEffect(x, x.co.distance(impactPoint)),
                    entitiesInBlastArea)
        else:
            # entitiesInBlastArea = list(filter(lambda x: not gl.checkForObstructionBetweenPoints(x.co, impactPoint, maxRange=self.radius) and x.co != impactPoint, gl.allEntities))
            entitiesInBlastArea = list(
                (e for e in gl.allEntities if e.co != impactPoint
                 and not gl.checkForObstructionBetweenPoints(
                     e.co, impactPoint, maxRange=self.radius)))

            map(lambda x: runEffect(x, x.co.distance(impactPoint)),
                entitiesInBlastArea)
Ejemplo n.º 9
0
    def spawnForPlayer(cls, baseData, x, y, stack=-1):
        if baseData is None or baseData is DUMMY_ITEM:
            return cls(DUMMY_ITEM,
                       Coords(x, y),
                       E_NONE,
                       0,
                       False,
                       1,
                       identified=True)

        if stack == -1:
            stack = 1
        if baseData.typeOfItem == 'STAFF':
            stack = rollAttack(2, 1 + baseData.minLevel)

        return cls(baseData, Coords(x, y), E_NONE, 0, True, 1, identified=True)
Ejemplo n.º 10
0
    def __init__(self, x: int, y: int) -> None:
        self.coords = Coords(x=x, y=y)
        self.total_stars = 0

        self.planets_dict: Dict[Coords, Planet] = {}
        """This value refers to planets that are allied to the ship in question, and not nescaraly to the player
        """
        self.friendly_planets = 0
        """This value refers to planets that are neutral to the ship in question, and not nescaraly to the player
        """
        self.neutral_planets = 0
        """This value refers to planets that are hostile to the ship in question, and not nescaraly to the player
        """
        self.unfriendly_planets = 0
        self.barren_planets = 0

        self.objectives = 0
        """This value refers to ships that are hostile to the ship in question, and not nescaraly to the player
        """
        self.hostile_ships = 0
        """This value refers to ships that are allied to the ship in question, and not nescaraly to the player
        """
        self.allied_ships = 0

        self.derelicts = 0

        self.planet_count_needs_updating = True
        self.ship_count_needs_updating = True
Ejemplo n.º 11
0
    def __init__(self, gd: GameData, x: int, y: int):

        #self.astroObjects = [Sector.__buildSlice(gd.subsec_size_x) for s in gd.subsec_size_range_y]
        self.safe_spots = list(
            SubSector.__gen_safe_spot_list(gd.subsec_size_range_x,
                                           gd.subsec_size_range_y))
        self.coords = Coords(x=x, y=y)
        #self.x = x
        #self.y = y

        #print(stars)
        self.game_data = gd

        self.stars_dict: Dict[Coords, Star] = {}

        self.total_stars = 0

        #self.planets = []
        self.planets_dict: Dict[Coords, Planet] = {}
        self.friendly_planets = 0
        self.neutral_planets = 0
        self.unfriendly_planets = 0
        self.barren_planets = 0

        self.planets_friendly_to_player = 0
        self.planets_neutral_to_player = 0
        self.planets_hostile_to_player = 0

        self.planets_friendly_to_enemy = 0
        self.planets_neutral_to_enemy = 0
        self.planets_hostile_to_enemy = 0

        self.player_present = False
Ejemplo n.º 12
0
    def placeStairs(self):
        stairs = []
        startRoom = self.rooms[0]
        endRoom = self.rooms[-1]

        x, y = startRoom.randomPointWithinRoom

        stairs.append(Coords(x, y))

        self.grid[y][x] = choice([
            ALL_TILE_DICT['TERRAIN_DOWN_STAIR'], ALL_TILE_DICT['TERRAIN_STAIR']
        ])

        x, y = endRoom.randomPointWithinRoom

        stairs.append(Coords(x, y))

        self.grid[y][x] = choice([
            ALL_TILE_DICT['TERRAIN_UP_STAIR'], ALL_TILE_DICT['TERRAIN_STAIR']
        ])

        for r in self.rooms[1:-1]:
            if randFloat() < 1.0 / 3.0:
                x, y = r.randomPointWithinRoom
                self.grid[y][x] = choice([
                    ALL_TILE_DICT['TERRAIN_STAIR'],
                    ALL_TILE_DICT['TERRAIN_UP_STAIR'],
                    ALL_TILE_DICT['TERRAIN_DOWN_STAIR']
                ])
                stairs.append(Coords(x, y))

        for r in self.rooms:
            if randFloat() < 0.2:
                x, y = r.randomPointWithinRoom
                if self.grid[y][x] not in {
                        ALL_TILE_DICT['TERRAIN_STAIR'],
                        ALL_TILE_DICT['TERRAIN_UP_STAIR'],
                        ALL_TILE_DICT['TERRAIN_DOWN_STAIR']
                }:
                    self.grid[y][x] = choice([
                        ALL_TILE_DICT['TERRAIN_STAIR'],
                        ALL_TILE_DICT['TERRAIN_UP_STAIR'],
                        ALL_TILE_DICT['TERRAIN_DOWN_STAIR']
                    ])
                    stairs.append(Coords(x, y))
        return stairs
Ejemplo n.º 13
0
    def Reset(self):
        global toolpath
        toolpath = self

        # get the box of all the solids
        box = wx.GetApp().program.stocks.GetBox()
        if box.valid:
            c = box.Center()
            width = box.Width()
            height = box.Height()
            depth = box.Depth() + 10
            minz = box.MinZ() - 10
            if width < 100: width = 100
            if height < 100: height = 100
            box.InsertBox(
                geom.Box3D(c.x - width / 2, c.y - height / 2, minz,
                           c.x + width / 2, c.y + height / 2, minz + depth))
        else:
            box.InsertBox(geom.Box3D(-100, -100, -50, 100, 100, 50))

        self.coords = Coords(box.MinX(), box.MinY(), box.MinZ(), box.MaxX(),
                             box.MaxY(), box.MaxZ())

        self.coorfs.add_block(0, 0, -10, 100, 100, 10)
        # add each stock
        stocks = wx.GetApp().program.stocks.GetChildren()
        for stock in stocks:
            stock_box = stock.GetBox()
            sim.set_current_color(stock.GetColor().ref())
            c = box.Center()
            self.coords.add_block(c.x, c.y, box.MinZ(), box.Width(),
                                  box.Height(), box.Depth())

        tools = wx.GetApp().program.tools.GetChildren()
        for tool in tools:
            self.tools[tool.tool_number] = GetSimToolDefinition(tool)

        machine_module = __import__('nc.' + wx.GetApp().program.machine.reader,
                                    fromlist=['dummy'])
        parser = machine_module.Parser(self)
        parser.Parse(wx.GetApp().program.GetOutputFileName())
        self.rewind()

        self.timer = wx.Timer(wx.GetApp().frame, wx.ID_ANY)
        self.timer.Start(33)
        wx.GetApp().frame.Bind(wx.EVT_TIMER, OnTimer)
Ejemplo n.º 14
0
def get_game_map(intcode):
    out, done = intcode.run()
    if done:
        print("GAME OVER (WTF?)")
    game_map = dict()
    for i in range(0, len(out), 3):
        game_map[Coords(out[i], out[i + 1])] = out[i + 2]
    return game_map, done
Ejemplo n.º 15
0
 def draw(self, render=True):
     delta, done = get_game_map(self.intcode)
     self.active = not done
     self.game_map.update(delta)
     ball = list(filter(lambda it: it[1] == 4, self.game_map.items()))[0][0]
     paddle = list(filter(lambda it: it[1] == 3,
                          self.game_map.items()))[0][0]
     self.autoplay = np.sign(ball.x - paddle.x)
     score = self.game_map.get(Coords(-1, 0), 0)
     if render:
         system('clear')
         print("Score:", score)
         print()
         for y in range(30):
             for x in range(50):
                 tile = self.game_map.get(Coords(x, y), 0)
                 print(theme[tile], end='')
             print()
Ejemplo n.º 16
0
    def spawnItem(cls, baseData, x, y, depth, identified=False, stack=-1):
        if baseData is None or baseData is DUMMY_ITEM:
            return cls(DUMMY_ITEM,
                       Coords(x, y),
                       E_NONE,
                       0,
                       False,
                       1,
                       identified=True)

        ego = E_NONE

        egos = list(
            filter(lambda e: e.minLevel + baseData.minLevel < depth,
                   baseData.egosAllowed))

        if len(egos) == 1:
            ego = egos[0]
        elif len(egos) > 1:
            ego = choices(
                egos,
                [depth - (e.minLevel + baseData.minLevel) for e in egos])[0]

        egoPower = depth - (ego.minLevel + baseData.minLevel)

        if egoPower < 1:
            egoPower = 0
        else:

            minPower = -egoPower // 4

            egoPower = randrange(minPower, egoPower)

        if egoPower == 0:
            ego = E_NONE

        if stack == -1:
            stack = 1
        if baseData.typeOfItem == 'STAFF':
            stack = ego.extraCharges + baseData.magicEffect.max_charges

        return cls(baseData, Coords(x, y), ego, egoPower, False, stack,
                   identified)
Ejemplo n.º 17
0
def lookLOS(vDict):
    """A very simple and somewhat inefficiant LOS function. for defermining if a grid tile can be marked as 'seen'.
     May have bugs."""

    gameLevel = vDict['gameLevel']

    top = max(gameLevel.player.co.y - gameLevel.player.getSightRadius, 0)
    bottom = min(gameLevel.player.co.y + gameLevel.player.getSightRadius,
                 gameLevel.widthHeight.y)
    left = max(gameLevel.player.co.x - gameLevel.player.getSightRadius, 0)
    right = min(gameLevel.player.co.x + gameLevel.player.getSightRadius,
                gameLevel.widthHeight.x)

    for x in range(left + 1, right - 1):
        betterLOS(gameLevel, gameLevel.player, Coords(x, top))
        betterLOS(gameLevel, gameLevel.player, Coords(x, bottom))

    for y in range(top + 1, bottom - 1):
        betterLOS(gameLevel, gameLevel.player, Coords(left, y))
        betterLOS(gameLevel, gameLevel.player, Coords(right, y))
Ejemplo n.º 18
0
 def __setitem__(self,key,value):
     """
     This wraps dict's __setitem__, ensuring that the key is an instance of
     Coords. (You can pass in a regular 2-tuple and it will be converted.)
     It also ensures the coords are within the bounds of the board.
     """
     coords = Coords.make(key) # Make sure everything is a Coord
     if not self.checkWithinBounds(coords):
         raise Exception, "{0} out of bounds.".format(coords)
     else:
         dict.__setitem__(self,coords,value)
Ejemplo n.º 19
0
 def print(self):
     for y in range(self.max_y):
         for x in range(self.max_x):
             coords = Coords(x, y)
             if self.pos == coords:
                 print('@', end='')
             elif coords in self.trace:
                 print('.', end='')
             else:
                 print(self.world_map.get(coords, ' '), end='')
         print()
Ejemplo n.º 20
0
 def print_map(self):
     for y in reversed(range(self.min_y - 2, self.max_y + 2)):
         for x in range(self.min_x - 2, self.max_x + 2):
             coords = Coords(x, y)
             if coords in self.map.keys():
                 print(self.map[coords], end='')
             elif coords == self.pos:
                 print('D', end='')
             else:
                 print(' ', end='')
         print()
Ejemplo n.º 21
0
 def __new__(clas,coords=None,origins=None,vectors=None):
     """Initialize the BoundVectors."""
     if coords is None:
         coords = eye(2,3,-1)
         if vectors is not None:
             coords = resize(coords,vectors.shape[:-1]+(2,3))
             coords[...,1,:] = vectors
         if origins is not None:
             coords += origins[...,newaxis,:]
     elif coords.shape[-2:] != (2,3):
         raise ValueError,"Expected shape (2,3) for last two array axes."
     return Coords.__new__(clas,coords)
Ejemplo n.º 22
0
 def __new__(clas,coords=None,origin=None,axes=None):
     """Initialize the CoordinateSystem"""
     if coords is None:
         coords = np.eye(4,3)
         if axes is not None:
             coords[:3] = axes
         if origin is not None:
             coords += origin
     else:
         coords = at.checkArray(coords,(4,3),'f','i')
     coords = Coords.__new__(clas,coords)
     return coords
Ejemplo n.º 23
0
    def getEntitiesBetweenPoints(self,
                                 c1: Coords,
                                 c2: Coords,
                                 maxEntities=1000,
                                 maxRange=100000):

        diffrence = c2 - c1

        entity_list = [
            e for e in self.allEntities
            if e.co.distance(c1) <= maxRange and e.is_a_valid_target
        ]

        distance_between_points = c1.distance(c2)

        c_atan = atan2(diffrence.y, diffrence.x)

        entities = []

        for e in entity_list:

            dist = c1.distance(e.co)
            # the distacne between the entity and c1

            d: Coords = c1 + (diffrence *
                              (dist / distance_between_points)).round

            if d == e.co:
                entities.append(e)
            """

            local_e_co = e.co - c1

            local_atan = atan2(local_e_co.y, local_e_co.x)

            if c_atan == local_atan:
                entities.append(e)
            """

        return sorted(entities, key=lambda e: e.co.distance(c1), reverse=True)
Ejemplo n.º 24
0
 def __init__(self):
     self.length = 0.0
     self.lines = []
     self.current_pos = 0.0
     self.current_point = Point(0, 0, 0)
     self.current_line_index = 0
     self.tools = {} # dictionary, tool id to Tool object
     self.current_tool = 1
     self.rapid = True
     self.mm_per_sec = 50.0
     self.running = False
     self.coords = Coords(0, 0, 0, 0, 0, 0)
     self.in_cut_to_position = False
Ejemplo n.º 25
0
def unit_test2():

    from coords import Coords
    from level import Level, prep_level_for_unit_testing, BLOCKS_MOVEMENT
    from line_of_sight import find_end_point_alt

    gameLevel = Level(0)

    start_point = Coords(4, 4)

    targets = [
        Coords(4, 12),
        Coords(12, 12),
        Coords(12, 4),
        Coords(2, 2),
        Coords(2, 4),
        Coords(1, 7)
    ]

    set_up_level(gameLevel, start_point, targets)

    for t in targets:
        ep = find_end_point_alt(gameLevel, start_point, t, BLOCKS_MOVEMENT, max_range=20)
        print('Start point: {}, target: {}, end point: {}, end point tile symbol: {}'.format(
            start_point, t, ep, gameLevel.grid[ep.y][ep.x].symbol))
        print(start_point.distance(ep))

    print('Max Range of 3')

    for t in targets:
        ep = find_end_point_alt(gameLevel, start_point, t, BLOCKS_MOVEMENT, max_range=3)
        print('Start point: {}, target: {}, end point: {}, end point tile symbol: {}'.format(
            start_point, t, ep, gameLevel.grid[ep.y][ep.x].symbol))
        print(start_point.distance(ep))


    for y in range(gameLevel.widthHeight.y):
        print(''.join([x.symbol for x in gameLevel.grid[y]]))
Ejemplo n.º 26
0
    def create_tuple():

        old_x, old_y = new_coords_x, new_coords_y
        old_c = None
        for r in range(CONFIG_OBJECT.max_distance):

            c:Coords = Coords(round(old_x), round(old_y))

            if not no_dups or (not old_c or c != old_c):
                yield c
            
            old_c = c
            old_x += new_coords_x
            old_y += new_coords_y
def main():
    pygame.init()
 
    width = 800
    height = 600
    screen = pygame.display.set_mode([width,height])
    screen_center = Vec2d(width/2, height/2)
    coords = Coords(screen_center.copy(), 1, True)
    zoom = 100
    coords.zoom_at_coords(Vec2d(0,0), zoom) 
    
    # Used to manage how fast the screen updates
    clock = pygame.time.Clock()

    # Create initial objects to demonstrate
    objects = []
    points = (Vec2d(0,0),
              Vec2d(1,0),
              Vec2d(1,0.5),
              Vec2d(0.5,0.5),
              Vec2d(0.5,1),
              Vec2d(0,1),
              )
Ejemplo n.º 28
0
def analyse_scaffold(out):
    scaffold = dict()
    x = 0
    y = 0
    for i in out:
        if is_line_break(i):
            y += 1
            x = 0
        elif i != ord('.'):
            scaffold[Coords(x, y)] = i
            x += 1
        else:
            x += 1
    return scaffold
Ejemplo n.º 29
0
    def regenerate(self, baseData, x, y, depth, identified=False, stack=-1):
        if baseData is None or baseData is DUMMY_ITEM:
            self.baseData = DUMMY_ITEM
            self.co = Coords(x, y)
            self.identified = identified
            self.egoPower = 0
            self.ego = E_NONE
            self.__stack = 0
        else:
            self.__baseData = baseData

            ego = E_NONE

            egos = list(
                filter(lambda e: e.minLevel + baseData.minLevel < depth,
                       baseData.egosAllowed))

            if len(egos) == 1:
                ego = egos[0]
            elif len(egos) > 1:
                ego = choices(
                    egos,
                    [depth - (e.minLevel + baseData.minLevel)
                     for e in egos])[0]

            egoPower = depth - (ego.minLevel + baseData.minLevel)

            if egoPower < 1:
                egoPower = 0
            else:

                minPower = -egoPower // 4

                egoPower = randrange(minPower, egoPower)

            if egoPower == 0:
                ego = E_NONE

            if stack == -1:
                stack = 1
            if baseData.typeOfItem == 'STAFF':
                stack = ego.extraCharges + baseData.magicEffect.max_charges

            else:
                self.ego = ego
                self.egoPower = egoPower
                self.identified = identified
                self.seen = False
                self.stack = stack
                self.identify_item()
Ejemplo n.º 30
0
    def resized(self,size=1.,tol=1.e-5):
        """Return a copy of the Geometry scaled to the given size.

        size can be a single value or a list of three values for the
        three coordinate directions. If it is a single value, all directions
        are scaled to the same size.
        Directions for which the geometry has a size smaller than tol times
        the maximum size are not rescaled.
        """
        from numpy import resize
        s = self.sizes()
        size = Coords(resize(size,(3,)))
        ignore = s<tol*s.max()
        s[ignore] = size[ignore]
        return self.scale(size/s)
Ejemplo n.º 31
0
def quaterLOS(vDict):
    gameLevel = vDict['gameLevel']

    playerPos = gameLevel.player.co

    top = max(gameLevel.player.co.y - gameLevel.player.getSightRadius, 0)
    bottom = min(gameLevel.player.co.y + gameLevel.player.getSightRadius,
                 gameLevel.widthHeight.y)
    left = max(gameLevel.player.co.x - gameLevel.player.getSightRadius, 0)
    right = min(gameLevel.player.co.x + gameLevel.player.getSightRadius,
                gameLevel.widthHeight.x)

    hitBlockWhileScanningPrevousLine = False

    # scan top quarter
    t = 1
    for t in range(playerPos.y, top, -1):

        if not hitBlockWhileScanningPrevousLine:

            hitBlock = False

            for l_2_r in range(playerPos.x - t, playerPos.x + t):

                if not gameLevel.grid[t][l_2_r].seeThru:

                    hitBlock = True

                gameLevel.visibilityGrid[t][l_2_r] = True

            t += -1

            if hitBlock:
                hitBlockWhileScanningPrevousLine = True
        else:

            for l_2_r in range(-t, t):

                # this is a tuple, not a Coords object
                nX, nY = (Coords(l_2_r, t) -
                          playerPos).normalize(round_to=True)

                if not gameLevel.grid[t][l_2_r].seeThru:
                    pass
                elif not gameLevel.visibilityGrid[t + nY][l_2_r + nX]:
                    pass
                else:
                    gameLevel.visibilityGrid[t][l_2_r] = True
Ejemplo n.º 32
0
def select_ship_planet_star(game_data:GameData, event: "tcod.event.MouseButtonDown") -> Union[Planet, Star, Starship, bool]:
    """Attempts to select the ship, planet, or star that the player is clicking on. Otherwise, it returns a boolean value depending on weither the cursor was positioned over a system grid square.

    Args:
        game_data (GameData): The GameData object.
        event (tcod.event.MouseButtonDown): The event containing the location of the click.

    Returns:
        Union[Planet, Star, Starship, bool]: If the mouse cursor is over a ship, planet, or star, that object will be returned. If not, then True will be returned. If the mouse cursor was not over a grid square, False will be returned.
    """

    x,y = CONFIG_OBJECT.subsector_display_x, CONFIG_OBJECT.subsector_display_y

    width, height = CONFIG_OBJECT.subsector_width, CONFIG_OBJECT.subsector_height

    x_range = range(x+1, x+2+width*2, 2)
    y_range = range(y+1, y+1+height*2, 2)

    if event.tile.x in x_range and event.tile.y in y_range:
        x_ajusted = (event.tile.x - (x + 1)) // 2
        y_ajusted = (event.tile.y - (y + 1)) // 2

        subsector = game_data.player.get_sub_sector
        co = Coords(x_ajusted, y_ajusted)
        try:
            planet = subsector.planets_dict[co]

            return planet
        except KeyError:
            try:
                star = subsector.stars_dict[co]
                
                return star
            except KeyError:
                
                for ship in game_data.ships_in_same_sub_sector_as_player:
                    if (
                        ship.local_coords.x == x_ajusted and ship.local_coords.y == y_ajusted and 
                        ship.ship_status.is_visible
                    ):
                        return ship
                return True
    else:
        return False
Ejemplo n.º 33
0
    def __init__(self, depth=0, valueOfItemsToSpawn=50):
        ls = self.getLevelSize(depth)
        w = ls + randint(-depth - 1, depth + 1) * 5
        h = ls + randint(-depth - 1, depth + 1) * 5
        self.size = ls
        self.grid = self.genLevel(w, h)
        self.widthHeight = Coords(w, h)
        self.depth = depth

        self.visibilityGrid = list(self.genVisibilityGrid(w, h))

        self.rooms, self.junctions = self.generateDungeonRooms(
            w, h, 0.06, 0.025)

        self.assignTerrain(w, h)
        self.stairs = self.placeStairs()
        self.itemsOnFloor = []

        self.avalibleSpecies = getFilteredSpecies(depth)

        self.itemsAvalibleForDepth = getListOfItemsSuitbleForDepth(depth)
        self.itemsByTypeAvalibleForDepth = {
            k: getSuitbleItemsByType(self.itemsAvalibleForDepth, k)
            for k in ALL_IMPORTANT_ITEM_TYPES
        }
        self.player = None

        self.allEntities = []
        self.spawnInhabitants(depth)

        self.open_spaces = set()

        for r in self.rooms:
            for y in r.topToBottomRange:
                for x in r.leftToRightRange:
                    self.open_spaces.add(tuple([x, y]))

        for h in self.junctions:
            hw = h.generateList

            self.open_spaces = self.open_spaces | set(hw)

        self.number_of_open_spaces = len(self.open_spaces)
Ejemplo n.º 34
0
def getRADec(name):
    '''get a Coords object for the given object'''
    script = r'''format object "%COO(:s;A | D)"
    query id {0}'''.format(name)
    result = script_request(script)
    if ':error:' in result[0]:
        return None
    ra, dec = result[0].split('|')
    ra = RA_coord.fromStr(ra.strip())
    match = getRADec._min_re.match(dec.strip())
    if match:
        #we need to take care of the special case when we get fractional minutes instead of seconds
        d = int(match.group(1))
        mins = Decimal(match.group(2))
        m = int(mins)
        s = (mins - m) * 60
        dec = Dec_coord(d, m, s)
    else:
        dec = Dec_coord.fromStr(dec.strip())
    return Coords(ra, dec)
Ejemplo n.º 35
0
 def displaySize(self):
     return Coords.make(self.screen.rect.size)
Ejemplo n.º 36
0
class QtCanvas(QtOpenGL.QGLWidget,canvas.Canvas):
    """A canvas for OpenGL rendering.

    This class provides interactive functionality for the OpenGL canvas
    provided by the canvas.Canvas class.
    
    Interactivity is highly dependent on Qt4. Putting the interactive
    functions in a separate class makes it esier to use the Canvas class
    in non-interactive situations or combining it with other GUI toolsets.
    """
    cursor_shape = { 'default': QtCore.Qt.ArrowCursor,
                     'pick'   : QtCore.Qt.CrossCursor, 
                     'draw'   : QtCore.Qt.CrossCursor, 
                     'busy'   : QtCore.Qt.BusyCursor,
                     }
    
    def __init__(self,*args):
        """Initialize an empty canvas with default settings."""
        QtOpenGL.QGLWidget.__init__(self,*args)
        self.setMinimumSize(32,32)
        self.setSizePolicy(QtGui.QSizePolicy.MinimumExpanding,QtGui.QSizePolicy.MinimumExpanding)
        self.setFocusPolicy(QtCore.Qt.StrongFocus)
        canvas.Canvas.__init__(self)
        self.setCursorShape('default')
        self.button = None
        self.mod = NONE
        self.mousefnc = {}
        self.mousefncsaved = {}
        for mod in _modifiers:
            self.mousefnc[mod] = {}
            self.mousefncsaved[mod] = {}
            for button in _buttons:
                self.mousefnc[mod][button] = None
                self.mousefncsaved[mod][button] = []
        # Initial mouse funcs are dynamic handling
        # ALT is initially same as NONE and should never be changed
        for mod in (NONE,ALT):
            self.setMouse(LEFT,self.dynarot,mod) 
            self.setMouse(MIDDLE,self.dynapan,mod) 
            self.setMouse(RIGHT,self.dynazoom,mod)
        self.selection_mode = None
        self.selection = Collection()
        self.trackfunc = None
        self.pick_func = {
            'actor'  : self.pick_actors,
            'element': self.pick_elements,
            'point'  : self.pick_points,
            'edge'   : self.pick_edges,
            'number' : self.pick_numbers,
            }
        self.pickable = None
        self.drawmode = None
        self.drawing_mode = None
        self.drawing = None
        # Drawing options
        self.resetOptions()

    def resetOptions(self):
        """Reset the Drawing options to some defaults"""
        self.options = dict(
            view = None,       # Keep the current camera angles
            bbox = 'auto',     # Automatically zoom on the drawed object
            clear = False,     # Clear on each drawing action
            shrink = None,
            )

    def setOptions(self,d):
        """Set the Drawing options to some values"""
        self.options.update(d)
        

    def setCursorShape(self,shape):
        """Set the cursor shape to shape"""
        if shape not in QtCanvas.cursor_shape.keys():
            shape = 'default'
        self.setCursor(QtGui.QCursor(QtCanvas.cursor_shape[shape]))


    def setCursorShapeFromFunc(self,func):
        """Set the cursor shape to shape"""
        if func in [ self.mouse_rectangle_zoom,self.mouse_pick ]:
            shape = 'pick'
        elif func == self.mouse_draw:
            shape = 'draw'
        else:
            shape = 'default'
        self.setCursorShape(shape)


    def setMouse(self,button,func,mod=NONE):
        self.mousefncsaved[mod][button].append(self.mousefnc[mod][button])
        self.mousefnc[mod][button] = func
        if button == LEFT and mod == NONE:
            self.setCursorShapeFromFunc(func)


    def resetMouse(self,button,mod=NONE):
        try:
            func = self.mousefncsaved[mod][button].pop()
        except:
            func = None
        self.mousefnc[mod][button] = func
        if button == LEFT and mod == NONE:
            self.setCursorShapeFromFunc(func)
            

    def getMouseFunc(self):
        """Return the mouse function bound to self.button and self.mod"""
        return self.mousefnc.get(int(self.mod),{}).get(self.button,None)


    def start_rectangle_zoom(self):
        self.setMouse(LEFT,self.mouse_rectangle_zoom)

 
    def finish_rectangle_zoom(self):
        self.update()
        self.resetMouse(LEFT)


    def mouse_rectangle_zoom(self,x,y,action):
        """Process mouse events during interactive rectangle zooming.

        On PRESS, record the mouse position.
        On MOVE, create a rectangular zoom window.
        On RELEASE, zoom to the picked rectangle.
        """
        if action == PRESS:
            self.makeCurrent()
            self.update()
            if self.trackfunc:
                print "PRESS",self.trackfunc,pf.canvas.camera.ctr
                pf.canvas.camera.setTracking(True)
                x,y,z = pf.canvas.camera.ctr
                self.zplane = pf.canvas.project(x,y,z,True)[2]
                print 'ZPLANE',self.zplane
                self.trackfunc(x,y,self.zplane)
            self.begin_2D_drawing()
            GL.glEnable(GL.GL_COLOR_LOGIC_OP)
            # An alternative is GL_XOR #
            GL.glLogicOp(GL.GL_INVERT)        
            # Draw rectangle
            self.draw_state_rect(x,y)
            self.swapBuffers()

        elif action == MOVE:
            if self.trackfunc:
                print "MOVE",self.trackfunc
                print 'ZPLANE',self.zplane
                self.trackfunc(x,y,self.zplane)
            # Remove old rectangle
            self.swapBuffers()
            self.draw_state_rect(*self.state)
            # Draw new rectangle
            self.draw_state_rect(x,y)
            self.swapBuffers()

        elif action == RELEASE:
            GL.glDisable(GL.GL_COLOR_LOGIC_OP)
            self.end_2D_drawing()
            x0 = min(self.statex,x)
            y0 = min(self.statey,y)
            x1 = max(self.statex,x)
            y1 = max(self.statey,y)
            self.zoomRectangle(x0,y0,x1,y1)
            self.finish_rectangle_zoom()

####################### INTERACTIVE PICKING ############################

    def setPickable(self,nrs=None):
        """Set the list of pickable actors"""
        if nrs is None:
            self.pickable = None
        else:
            self.pickable = [ self.actors[i] for i in nrs if i in range(len(self.actors))]
        

    def start_selection(self,mode,filtr):
        """Start an interactive picking mode.

        If selection mode was already started, mode is disregarded and
        this can be used to change the filter method.
        """
        if self.selection_mode is None:
            self.setMouse(LEFT,self.mouse_pick)
            self.setMouse(LEFT,self.mouse_pick,SHIFT)
            self.setMouse(LEFT,self.mouse_pick,CTRL)
            self.setMouse(RIGHT,self.emit_done)
            self.setMouse(RIGHT,self.emit_cancel,SHIFT)
            self.connect(self,DONE,self.accept_selection)
            self.connect(self,CANCEL,self.cancel_selection)
            self.selection_mode = mode
            self.selection_front = None

        if filtr == 'none':
            filtr = None
        self.selection_filter = filtr
        if filtr is None:
            self.selection_front = None
        self.selection.clear()
        self.selection.setType(self.selection_mode)


    def wait_selection(self):
        """Wait for the user to interactively make a selection."""
        self.selection_timer = QtCore.QThread
        self.selection_busy = True
        while self.selection_busy:
            self.selection_timer.msleep(20)
            pf.app.processEvents()

    def finish_selection(self):
        """End an interactive picking mode."""
        self.resetMouse(LEFT)
        self.resetMouse(LEFT,SHIFT)
        self.resetMouse(LEFT,CTRL)
        self.resetMouse(RIGHT)
        self.resetMouse(RIGHT,SHIFT)
        self.disconnect(self,DONE,self.accept_selection)
        self.disconnect(self,CANCEL,self.cancel_selection)
        self.selection_mode = None

    def accept_selection(self,clear=False):
        """Accept or cancel an interactive picking mode.

        If clear == True, the current selection is cleared.
        """
        self.selection_accepted = True
        if clear:
            self.selection.clear()
            self.selection_accepted = False
        self.selection_canceled = True
        self.selection_busy = False

    def cancel_selection(self):
        """Cancel an interactive picking mode and clear the selection."""
        self.accept_selection(clear=True)

    
    def pick(self,mode='actor',single=False,func=None,filter=None):
        """Interactively pick objects from the viewport.

        - `mode`: defines what to pick : one of
          ``['actor','element','point','number','edge']``
        - `single`: if True, the function returns as soon as the user ends
          a picking operation. The default is to let the user
          modify his selection and only to return after an explicit
          cancel (ESC or right mouse button).
        - `func`: if specified, this function will be called after each
          atomic pick operation. The Collection with the currently selected
          objects is passed as an argument. This can e.g. be used to highlight
          the selected objects during picking.
        - `filter`: defines what elements to retain from the selection: one of
          ``[None,'closest,'connected']``.

          - None (default) will return the complete selection.
          - 'closest' will only keep the element closest to the user.
          - 'connected' will only keep elements connected to
            - the closest element (set picked)
            - what is already in the selection (add picked).

            Currently this only works when picking mode is 'element' and
            for Actors having a partitionByConnection method.

        When the picking operation is finished, the selection is returned.
        The return value is always a Collection object.
        """
        self.selection_canceled = False
        self.start_selection(mode,filter)
        while not self.selection_canceled:
            self.wait_selection()
            if not self.selection_canceled:
                # selection by mouse_picking
                self.pick_func[self.selection_mode]()
                if len(self.picked) != 0:
                    if self.selection_filter is None:
                        if self.mod == NONE:
                            self.selection.set(self.picked)
                        elif self.mod == SHIFT:
                            self.selection.add(self.picked)
                        elif self.mod == CTRL:
                            self.selection.remove(self.picked)
                    elif self.selection_filter == 'single':
                        if self.mod == NONE:
                            self.selection.set([self.closest_pick[0]])
                        elif self.mod == SHIFT:
                            self.selection.add([self.closest_pick[0]])
                        elif self.mod == CTRL:
                            self.selection.remove([self.closest_pick[0]])
                    elif self.selection_filter == 'closest':
                        if self.selection_front is None or self.mod == NONE or \
                               (self.mod == SHIFT and self.closest_pick[1] < self.selection_front[1]):
                            self.selection_front = self.closest_pick
                            self.selection.set([self.closest_pick[0]])
                    elif self.selection_filter == 'connected':
                        if self.selection_front is None or self.mod == NONE or len(self.selection.keys()) == 0:
                            self.selection_front = self.closest_pick
                            closest_actor,closest_elem = map(int,self.selection_front[0])
                        elif self.mod == SHIFT:
                            closest_elem = self.selection.get(closest_actor)[0]
                        if self.mod == NONE:
                            self.selection.set(self.picked)
                        elif self.mod == SHIFT:
                            self.selection.add(self.picked)
                        elif self.mod == CTRL:
                            self.selection.remove(self.picked)
                        if self.mod == NONE or self.mod == SHIFT:
                            conn_elems = self.actors[closest_actor].object.connectedElements(closest_elem,self.selection.get(closest_actor))
                            self.selection.set(conn_elems,closest_actor)
                    if func:
                        func(self.selection)
                self.update()
            if single:
                self.accept_selection()
        if func and not self.selection_accepted:
            func(self.selection)
        self.finish_selection()
        return self.selection
    

    def pickNumbers(self,*args,**kargs):
        """Go into number picking mode and return the selection."""
        return self.pick('numbers',*args,**kargs)

#################### Interactive drawing ####################################

    def idraw(self,mode='point',npoints=-1,zplane=0.,func=None,coords=None,preview=False):
        """Interactively draw on the canvas.

        This function allows the user to interactively create points in 3D
        space and collects the subsequent points in a Coords object. The
        interpretation of these points is left to the caller.
        
        - `mode`: one of the drawing modes, specifying the kind of objects you
          want to draw. This is passed to the specified `func`.
        - `npoints`: If -1, the user can create any number of points. When >=0,
          the function will return when the total number of points in the
          collection reaches the specified value.
        - `zplane`: the depth of the z-plane on which the 2D drawing is done.
        - `func`: a function that is called after each atomic drawing
          operation. It is typically used to draw a preview using the current
          set of points. The function is passed the current Coords and the
          `mode` as arguments.
        - `coords`: an initial set of coordinates to which the newly created
          points should be added. If specified, `npoints` also counts these
          initial points.
        - `preview`: **Experimental** If True, the preview funcion will also
          be called during mouse movement with a pressed button, allowing to
          preview the result before a point is created.
        
        The drawing operation is finished when the number of requested points
        has been reached, or when the user clicks the right mouse button or
        hits 'ENTER'.
        The return value is a (n,3) shaped Coords array.
        """
        self.draw_canceled = False
        self.start_draw(mode,zplane,coords)
        try:
            if preview:
                self.previewfunc = func
            else:
                self.previewfunc = None

            while not self.draw_canceled:
                self.wait_selection()
                if not self.draw_canceled:
                    self.drawn = Coords(self.drawn).reshape(-1,3)
                    self.drawing = Coords.concatenate([self.drawing,self.drawn])
                    if func:
                        func(self.drawing,self.drawmode)
                if npoints > 0 and len(self.drawing) >= npoints:
                    self.accept_draw()                
            if func and not self.draw_accepted:
                func(self.drawing,self.drawmode)
        finally:
            self.finish_draw()
        return self.drawing


    def start_draw(self,mode,zplane,coords):
        """Start an interactive drawing mode."""
        self.setMouse(LEFT,self.mouse_draw)
        self.setMouse(RIGHT,self.emit_done)
        self.setMouse(RIGHT,self.emit_cancel,SHIFT)
        self.connect(self,DONE,self.accept_draw)
        self.connect(self,CANCEL,self.cancel_draw)
        self.drawmode = mode
        self.zplane = zplane
        self.drawing = Coords(coords)

    def finish_draw(self):
        """End an interactive drawing mode."""
        self.resetMouse(LEFT)
        self.resetMouse(RIGHT)
        self.resetMouse(RIGHT,SHIFT)
        self.disconnect(self,DONE,self.accept_selection)
        self.disconnect(self,CANCEL,self.cancel_selection)
        self.drawmode = None

    def accept_draw(self,clear=False):
        """Cancel an interactive drawing mode.

        If clear == True, the current drawing is cleared.
        """
        self.draw_accepted = True
        if clear:
            self.drawing = Coords()
            self.draw_accepted = False
        self.draw_canceled = True
        self.selection_busy = False

    def cancel_draw(self):
        """Cancel an interactive drawing mode and clear the drawing."""
        self.accept_draw(clear=True)


    def mouse_draw(self,x,y,action):
        """Process mouse events during interactive drawing.

        On PRESS, do nothing.
        On MOVE, do nothing.
        On RELEASE, add the point to the point list.
        """
        if action == PRESS:
            self.makeCurrent()
            self.update()
            if self.trackfunc:
                print "ENABLE TRACKING"
                pf.canvas.camera.setTracking(True)

        elif action == MOVE:
            if pf.app.hasPendingEvents():
                return
            if self.trackfunc:
                self.trackfunc(x,y,self.zplane)
                #pf.app.processEvents()
            if self.previewfunc:
                self.swapBuffers()
                self.drawn = self.unProject(x,y,self.zplane)
                self.drawn = Coords(self.drawn).reshape(-1,3)
                self.previewfunc(Coords.concatenate([self.drawing,self.drawn]),self.drawmode)
                self.swapBuffers()
            
        elif action == RELEASE:
            self.drawn = self.unProject(x,y,self.zplane)
            self.selection_busy = False

##########################################################################

    def start_drawing(self,mode):
        """Start an interactive line drawing mode."""
        pf.debug("START DRAWING MODE")
        self.setMouse(LEFT,self.mouse_draw_line)
        self.setMouse(RIGHT,self.emit_done)
        self.setMouse(RIGHT,self.emit_cancel,SHIFT)
        self.connect(self,DONE,self.accept_drawing)
        self.connect(self,CANCEL,self.cancel_drawing)
        #self.setCursorShape('pick')
        self.drawing_mode = mode
        self.edit_mode = None
        self.drawing = empty((0,2,2),dtype=int)

    def wait_drawing(self):
        """Wait for the user to interactively draw a line."""
        self.drawing_timer = QtCore.QThread
        self.drawing_busy = True
        while self.drawing_busy:
            self.drawing_timer.msleep(20)
            pf.app.processEvents()

    def finish_drawing(self):
        """End an interactive drawing mode."""
        pf.debug("END DRAWING MODE")
        #self.setCursorShape('default')
        self.resetMouse(LEFT)
        self.resetMouse(RIGHT)
        self.resetMouse(RIGHT,SHIFT)
        self.disconnect(self,DONE,self.accept_selection)
        self.disconnect(self,CANCEL,self.cancel_selection)
        self.drawing_mode = None

    def accept_drawing(self,clear=False):
        """Cancel an interactive drawing mode.

        If clear == True, the current drawing is cleared.
        """
        pf.debug("CANCEL DRAWING MODE")
        self.drawing_accepted = True
        if clear:
            self.drawing = empty((0,2,2),dtype=int)
            self.drawing_accepted = False
        self.drawing_canceled = True
        self.drawing_busy = False

    def cancel_drawing(self):
        """Cancel an interactive drawing mode and clear the drawing."""
        self.accept_drawing(clear=True)
    
    def edit_drawing(self,mode):
        """Edit an interactive drawing."""
        self.edit_mode = mode
        self.drawing_busy = False     

    def drawLinesInter(self,mode='line',single=False,func=None):
        """Interactively draw lines on the canvas.

        - single: if True, the function returns as soon as the user ends
          a drawing operation. The default is to let the user
          draw multiple lines and only to return after an explicit
          cancel (ESC or right mouse button).
        - func: if specified, this function will be called after each
          atomic drawing operation. The current drawing is passed as
          an argument. This can e.g. be used to show the drawing.

        When the drawing operation is finished, the drawing is returned.
        The return value is a (n,2,2) shaped array.
        """
        self.drawing_canceled = False
        self.start_drawing(mode)
        while not self.drawing_canceled:
            self.wait_drawing()
            if not self.drawing_canceled:
                if self.edit_mode: # an edit mode from the edit combo was clicked
                    if self.edit_mode == 'undo' and self.drawing.size != 0:
                        self.drawing = delete(self.drawing,-1,0)
                    elif self.edit_mode == 'clear':
                        self.drawing = empty((0,2,2),dtype=int)
                    elif self.edit_mode == 'close' and self.drawing.size != 0:
                        line = asarray([self.drawing[-1,-1],self.drawing[0,0]])
                        self.drawing = append(self.drawing,line.reshape(-1,2,2),0)
                    self.edit_mode = None
                else: # a line was drawn interactively
                    self.drawing = append(self.drawing,self.drawn.reshape(-1,2,2),0)
                if func:
                    func(self.drawing)
            if single:
                self.accept_drawing()                
        if func and not self.drawing_accepted:
            func(self.drawing)
        self.finish_drawing()
        return self.drawing


######## QtOpenGL interface ##############################
        
    def initializeGL(self):
        if pf.options.debug:
            p = self.sizePolicy()
            print(p.horizontalPolicy(), p.verticalPolicy(), p.horizontalStretch(), p.verticalStretch())
        self.initCamera()
        self.glinit()
        self.resizeGL(self.width(),self.height())
        self.setCamera()

    def	resizeGL(self,w,h):
        self.setSize(w,h)

    def	paintGL(self):
        if not self.mode2D:
            #pf.debugt("CANVAS DISPLAY")
            self.display()

    def getSize(self):
        return int(self.width()),int(self.height())

####### MOUSE EVENT HANDLERS ############################

    # Mouse functions can be bound to any of the mouse buttons
    # LEFT, MIDDLE or RIGHT.
    # Each mouse function should accept three possible actions:
    # PRESS, MOVE, RELEASE.
    # On a mouse button PRESS, the mouse screen position and the pressed
    # button are always saved in self.statex,self.statey,self.button.
    # The mouse function does not need to save these and can directly use
    # their values.
    # On a mouse button RELEASE, self.button is cleared, to avoid further
    # move actions.
    # Functions that change the camera settings should call saveModelView()
    # when they are done.
    # ATTENTION! The y argument is positive upwards, as in normal OpenGL
    # operations!


    def dynarot(self,x,y,action):
        """Perform dynamic rotation operation.

        This function processes mouse button events controlling a dynamic
        rotation operation. The action is one of PRESS, MOVE or RELEASE.
        """
        if action == PRESS:
            w,h = self.getSize()
            self.state = [self.statex-w/2, self.statey-h/2 ]

        elif action == MOVE:
            w,h = self.getSize()
            # set all three rotations from mouse movement
            # tangential movement sets twist,
            # but only if initial vector is big enough
            x0 = self.state        # initial vector
            d = length(x0)
            if d > h/8:
                # pf.debug(d)
                x1 = [x-w/2, y-h/2]     # new vector
                a0 = math.atan2(x0[0],x0[1])
                a1 = math.atan2(x1[0],x1[1])
                an = (a1-a0) / math.pi * 180
                ds = utils.stuur(d,[-h/4,h/8,h/4],[-1,0,1],2)
                twist = - an*ds
                self.camera.rotate(twist,0.,0.,1.)
                self.state = x1
            # radial movement rotates around vector in lens plane
            x0 = [self.statex-w/2, self.statey-h/2]    # initial vector
            if x0 == [0.,0.]:
                x0 = [1.,0.]
            dx = [x-self.statex, y-self.statey]        # movement
            b = projection(dx,x0)
            if abs(b) > 5:
                val = utils.stuur(b,[-2*h,0,2*h],[-180,0,+180],1)
                rot =  [ abs(val),-dx[1],dx[0],0 ]
                self.camera.rotate(*rot)
                self.statex,self.statey = (x,y)
            self.update()

        elif action == RELEASE:
            self.update()
            self.camera.saveModelView()

            
    def dynapan(self,x,y,action):
        """Perform dynamic pan operation.

        This function processes mouse button events controlling a dynamic
        pan operation. The action is one of PRESS, MOVE or RELEASE.
        """
        if action == PRESS:
            pass

        elif action == MOVE:
            w,h = self.getSize()
            dx,dy = float(self.statex-x)/w, float(self.statey-y)/h
            self.camera.transArea(dx,dy)
            self.statex,self.statey = (x,y)
            self.update()

        elif action == RELEASE:
            self.update()
            self.camera.saveModelView()          

            
    def dynazoom(self,x,y,action):
        """Perform dynamic zoom operation.

        This function processes mouse button events controlling a dynamic
        zoom operation. The action is one of PRESS, MOVE or RELEASE.
        """
        if action == PRESS:
            self.state = [self.camera.getDist(),self.camera.area.tolist(),pf.cfg['gui/dynazoom']]

        elif action == MOVE:
            w,h = self.getSize()
            dx,dy = float(self.statex-x)/w, float(self.statey-y)/h
            for method,state,value,size in zip(self.state[2],[self.statex,self.statey],[x,y],[w,h]):
                #pf.debug("%s %s %s %s" % (method,state,value,size))
                if method == 'area':
                    d = float(state-value)/size
                    f = exp(4*d)
                    self.camera.zoomArea(f,area=asarray(self.state[1]).reshape(2,2))
                elif method == 'dolly':
                    d = utils.stuur(value,[0,state,size],[5,1,0.2],1.2)
                    #pf.debug(d)
                    self.camera.setDist(d*self.state[0])
                    
            self.update()

        elif action == RELEASE:
            self.update()
            self.camera.saveModelView()

    def wheel_zoom(self,delta):
        """Zoom by rotating a wheel over an angle delta"""
        f = 2**(delta/120.*pf.cfg['gui/wheelzoomfactor'])
        if pf.cfg['gui/wheelzoom'] == 'area':
            self.camera.zoomArea(f)
        elif pf.cfg['gui/wheelzoom'] == 'lens':
            self.camera.zoom(f)
        else:
            self.camera.dolly(f)
        self.update()

    def emit_done(self,x,y,action):
        """Emit a DONE event by clicking the mouse.

        This is equivalent to pressing the ENTER button."""
        if action == RELEASE:
            self.emit(DONE,())
            
    def emit_cancel(self,x,y,action):
        """Emit a CANCEL event by clicking the mouse.

        This is equivalent to pressing the ESC button."""
        if action == RELEASE:
            self.emit(CANCEL,())


    def draw_state_rect(self,x,y):
        """Store the pos and draw a rectangle to it."""
        self.state = x,y
        decors.drawRect(self.statex,self.statey,x,y)


    def mouse_pick(self,x,y,action):
        """Process mouse events during interactive picking.

        On PRESS, record the mouse position.
        On MOVE, create a rectangular picking window.
        On RELEASE, pick the objects inside the rectangle.
        """
        if action == PRESS:
            self.makeCurrent()
            self.update()
            self.begin_2D_drawing()
            #self.swapBuffers()
            GL.glEnable(GL.GL_COLOR_LOGIC_OP)
            # An alternative is GL_XOR #
            GL.glLogicOp(GL.GL_INVERT)
            # Draw rectangle
            self.draw_state_rect(x,y)
            self.swapBuffers()

        elif action == MOVE:
            # Remove old rectangle
            self.swapBuffers()
            self.draw_state_rect(*self.state)
            # Draw new rectangle
            self.draw_state_rect(x,y)
            self.swapBuffers()

        elif action == RELEASE:
            GL.glDisable(GL.GL_COLOR_LOGIC_OP)
            self.swapBuffers()
            self.end_2D_drawing()

            x,y = (x+self.statex)/2., (y+self.statey)/2.
            w,h = abs(x-self.statex)*2., abs(y-self.statey)*2.
            if w <= 0 or h <= 0:
               w,h = pf.cfg.get('pick/size',(20,20))
            vp = GL.glGetIntegerv(GL.GL_VIEWPORT)
            self.pick_window = (x,y,w,h,vp)
            self.selection_busy = False


    def pick_actors(self):
        """Set the list of actors inside the pick_window."""
        self.camera.loadProjection(pick=self.pick_window)
        self.camera.loadModelView()
        stackdepth = 1
        npickable = len(self.actors)
        selbuf = GL.glSelectBuffer(npickable*(3+stackdepth))
        GL.glRenderMode(GL.GL_SELECT)
        GL.glInitNames()
        for i,a in enumerate(self.actors):
            GL.glPushName(i)
            GL.glCallList(a.list)
            GL.glPopName()
        libGL.glRenderMode(GL.GL_RENDER)
        # Read the selection buffer
        store_closest = self.selection_filter == 'single' or \
                        self.selection_filter == 'closest'
        self.picked = []
        if selbuf[0] > 0:
            buf = asarray(selbuf).reshape(-1,3+selbuf[0])
            buf = buf[buf[:,0] > 0]
            self.picked = buf[:,3]
            if store_closest:
                w = buf[:,1].argmin()
                self.closest_pick = (self.picked[w], buf[w,1])


    def pick_parts(self,obj_type,max_objects,store_closest=False):
        """Set the list of actor parts inside the pick_window.

        obj_type can be 'element', 'edge' or 'point'
        'edge' is only available for mesh type geometry
        max_objects specifies the maximum number of objects

        The picked object numbers are stored in self.picked.
        If store_closest==True, the closest picked object is stored in as a
        tuple ( [actor,object] ,distance) in self.picked_closest

        A list of actors from which can be picked may be given.
        If so, the resulting keys are indices in this list.
        By default, the full actor list is used.
        """
        self.picked = []
        pf.debug('PICK_PARTS %s %s %s' % (obj_type,max_objects,store_closest))
        if max_objects <= 0:
            pf.message("No such objects to be picked!")
            return
        self.camera.loadProjection(pick=self.pick_window)
        self.camera.loadModelView()
        stackdepth = 2
        selbuf = GL.glSelectBuffer(max_objects*(3+stackdepth))
        GL.glRenderMode(GL.GL_SELECT)
        GL.glInitNames()
        if self.pickable is None:
            pickable = self.actors
        else:
            pickable = self.pickable
        for i,a in enumerate(pickable):
            GL.glPushName(i)
            a.pickGL(obj_type)  # this will push the number of the part
            GL.glPopName()
        self.picked = []
        libGL.glRenderMode(GL.GL_RENDER)
        if selbuf[0] > 0:
            buf = asarray(selbuf).reshape(-1,3+selbuf[0])
            buf = buf[buf[:,0] > 0]
            self.picked = buf[:,3:]
            #pf.debug("PICKBUFFER: %s" % self.picked)
            if store_closest and len(buf) > 0:
                w = buf[:,1].argmin()
                self.closest_pick = (self.picked[w], buf[w,1])


    def pick_elements(self):
        """Set the list of actor elements inside the pick_window."""
        npickable = 0
        for a in self.actors:
            npickable += a.nelems()
        self.pick_parts('element',npickable,store_closest=\
                        self.selection_filter == 'single' or\
                        self.selection_filter == 'closest' or\
                        self.selection_filter == 'connected'
                        )


    def pick_points(self):
        """Set the list of actor points inside the pick_window."""
        npickable = 0
        for a in self.actors:
            #pf.debug("ADDING %s pickable points"%a.npoints())
            npickable += a.npoints()
        self.pick_parts('point',npickable,store_closest=\
                        self.selection_filter == 'single' or\
                        self.selection_filter == 'closest',
                        )


    def pick_edges(self):
        """Set the list of actor edges inside the pick_window."""
        npickable = 0
        for a in self.actors:
            if hasattr(a,'nedges'):
                npickable += a.nedges()
        self.pick_parts('edge',npickable,store_closest=\
                        self.selection_filter == 'single' or\
                        self.selection_filter == 'closest',
                        )


    def pick_numbers(self):
        """Return the numbers inside the pick_window."""
        self.camera.loadProjection(pick=self.pick_window)
        self.camera.loadModelView()
        self.picked = [0,1,2,3]
        if self.numbers:
            self.picked = self.numbers.drawpick()


    def draw_state_line(self,x,y):
        """Store the pos and draw a line to it."""
        self.state = x,y
        decors.drawLine(self.statex,self.statey,x,y)


    def mouse_draw_line(self,x,y,action):
        """Process mouse events during interactive drawing.

        On PRESS, record the mouse position.
        On MOVE, draw a line.
        On RELEASE, add the line to the drawing.
        """
        if action == PRESS:
            self.makeCurrent()
            self.update()
            self.begin_2D_drawing()
            self.swapBuffers()
            GL.glEnable(GL.GL_COLOR_LOGIC_OP)
            # An alternative is GL_XOR #
            GL.glLogicOp(GL.GL_INVERT)        
            # Draw rectangle
            if self.drawing.size != 0:
                self.statex,self.statey = self.drawing[-1,-1]
            self.draw_state_line(x,y)
            self.swapBuffers()

        elif action == MOVE:
            # Remove old rectangle
            self.swapBuffers()
            self.draw_state_line(*self.state)
            # Draw new rectangle
            self.draw_state_line(x,y)
            self.swapBuffers()

        elif action == RELEASE:
            GL.glDisable(GL.GL_COLOR_LOGIC_OP)
            #self.swapBuffers()
            self.end_2D_drawing()

            self.drawn = asarray([[self.statex,self.statey],[x,y]])
            self.drawing_busy = False


    @classmethod
    def has_modifier(clas,e,mod):
        return ( e.modifiers() & mod ) == mod
        
    def mousePressEvent(self,e):
        """Process a mouse press event."""
        pf.GUI.viewports.setCurrent(self)
        # on PRESS, always remember mouse position and button
        self.statex,self.statey = e.x(), self.height()-e.y()
        self.button = e.button()
        self.mod = e.modifiers() & ALLMODS
        #pf.debug("PRESS BUTTON %s WITH MODIFIER %s" % (self.button,self.mod))
        func = self.getMouseFunc()
        if func:
            func(self.statex,self.statey,PRESS)
        e.accept()
        
    def mouseMoveEvent(self,e):
        """Process a mouse move event."""
        # the MOVE event does not identify a button, use the saved one
        func = self.getMouseFunc()
        if func:
            func(e.x(),self.height()-e.y(),MOVE)
        e.accept()

    def mouseReleaseEvent(self,e):
        """Process a mouse release event."""
        func = self.getMouseFunc()
        self.button = None        # clear the stored button
        if func:
            func(e.x(),self.height()-e.y(),RELEASE)
        e.accept()

    def wheelEvent(self,e):
        """Process a wheel event."""
        func = self.wheel_zoom
        if func:
            func(e.delta())
        e.accept()
        


    # Any keypress with focus in the canvas generates a 'wakeup' signal.
    # This is used to break out of a wait status.
    # Events not handled here could also be handled by the toplevel
    # event handler.
    def keyPressEvent (self,e):
        self.emit(WAKEUP,())
        if e.key() == ESC:
            self.emit(CANCEL,())
            e.accept()
        elif e.key() == ENTER or e.key() == RETURN:
            self.emit(DONE,())
            e.accept()
        else:
            e.ignore()
Ejemplo n.º 37
0
class Toolpath:
    def __init__(self):
        self.length = 0.0
        self.lines = []
        self.current_pos = 0.0
        self.from_position = Point(0, 0, 0)
        self.current_point = self.from_position
        self.current_line_index = 0
        self.tools = {} # dictionary, tool id to Tool object
        self.rapid_flag = True
        self.mm_per_sec = 50.0
        self.running = False
        self.coords = Coords(0, 0, 0, 0, 0, 0)
        self.in_cut_to_position = False
        
        self.x = 0
        self.y = 0
        self.z = 50
        
        self.t = None
        
    def add_line(self, p0, p1):
        self.lines.append(Line(p0, p1, self.rapid_flag, self.t))
        
    def rewind(self):
        self.current_point = Point(0, 0, 0)
        if len(self.lines)>0:
            self.current_point = self.lines[0].p0
        self.current_pos = 0.0
        self.current_line_index = 0
        self.running = False
        
    def draw_tool(self):
        voxelcut.drawclear()
        
        index = self.current_line_index
        if index < 0: index = 0
        if index >= len(self.lines):
            return
        
        tool_number = self.lines[index].tool_number
        rapid = self.lines[index].rapid
        
        if tool_number in self.tools:
            x, y, z = self.coords.mm_to_voxels(self.current_point.x, self.current_point.y, self.current_point.z)
            self.tools[tool_number].draw(x, y, z, rapid)
        
    def cut_point(self, p):
        x, y, z = self.coords.mm_to_voxels(p.x, p.y, p.z)
        index = self.current_line_index
        if index < 0: index = 0
        tool_number = self.lines[index].tool_number
        rapid = self.lines[index].rapid
        
        if tool_number in self.tools:
            self.tools[tool_number].cut(x, y, z, rapid)
         
    def cut_line(self, line):
        length = line.Length()
        num_segments = int(1 + length * self.coords.voxels_per_mm * 0.2)
        step = length/num_segments
        dv = (line.p1 - line.p0) * (1.0/num_segments)
        for i in range (0, num_segments + 1):
            p = line.p0 + (dv * i)
            self.cut_point(p)
            
    def cut_to_position(self, pos):
        if self.current_line_index >= len(self.lines):
            return
        
        if self.cut_to_position == True:
            import wx
            wx.MessageBox("in cut_to_position again!")
        
        self.in_cut_to_position = True
        start_pos = self.current_pos
        while self.current_line_index < len(self.lines):
            line = copy.copy(self.lines[self.current_line_index])
            line.p0 = self.current_point
            line_length = line.Length()
            if line_length > 0:
                end_pos = self.current_pos + line_length
                if pos < end_pos:
                    fraction = (pos - self.current_pos)/(end_pos - self.current_pos)
                    line.p1 = line.p0 + ((line.p1 - line.p0) * fraction)
                    self.cut_line(line)
                    self.current_pos = pos
                    self.current_point = line.p1
                    break
                self.cut_line(line)
                self.current_pos = end_pos
            self.current_point = line.p1
            self.current_line_index = self.current_line_index + 1
            
        self.in_cut_to_position = False
        
    def begin_ncblock(self):
        pass

    def end_ncblock(self):
        pass

    def add_text(self, s, col, cdata):
        pass

    def set_mode(self, units):
        pass
        
    def metric(self):
        pass
        
    def imperial(self):
        pass

    def begin_path(self, col):
        pass

    def end_path(self):
        pass
        
    def rapid(self, x=None, y=None, z=None, a=None, b=None, c=None):
        self.rapid_flag = True
        if x == None: x = self.x
        if y == None: y = self.y
        if z == None: z = self.z
        self.add_line(Point(self.x, self.y, self.z), Point(x, y, z))
        self.x = x
        self.y = y
        self.z = z
        
    def feed(self, x=None, y=None, z=None, a=None, b=None, c=None):
        self.rapid_flag = False
        if x == None: x = self.x
        if y == None: y = self.y
        if z == None: z = self.z
        self.add_line(Point(self.x, self.y, self.z), Point(x, y, z))
        self.x = x
        self.y = y
        self.z = z
        
    def arc(self, dir, x, y, z, i, j, k, r):
        self.rapid_flag = False
        if x == None: x = self.x
        if y == None: y = self.y
        if z == None: z = self.z
        area.set_units(0.05)
        curve = area.Curve()
        curve.append(area.Point(self.x, self.y))
        curve.append(area.Vertex(dir, area.Point(x, y), area.Point(i, j)))
        curve.UnFitArcs()
        for span in curve.GetSpans():
            self.add_line(Point(span.p.x, span.p.y, z), Point(span.v.p.x, span.v.p.y, z))
        self.x = x
        self.y = y
        self.z = z

    def arc_cw(self, x=None, y=None, z=None, i=None, j=None, k=None, r=None):
        self.arc(-1, x, y, z, i, j, k, r)

    def arc_ccw(self, x=None, y=None, z=None, i=None, j=None, k=None, r=None):
        self.arc(1, x, y, z, i, j, k, r)
        
    def tool_change(self, id):
        self.t = id
            
    def current_tool(self):
        return self.t
            
    def spindle(self, s, clockwise):
        pass
    
    def feedrate(self, f):
        pass
Ejemplo n.º 38
0
 def checkWithinBounds(self,coords):
     """Returns true if the given coords are within the board's bounds."""
     trueCoords = Coords.make(coords)
     withinXBounds = (self.width == None) or (trueCoords.x >= 0 and trueCoords.x < self.width)
     withinYBounds = (self.height == None) or (trueCoords.y >= 0 and trueCoords.y < self.height)
     return withinXBounds and withinYBounds
Ejemplo n.º 39
0
 def __getitem__(self,key):
     coords = Coords.make(key)
     if not self.checkWithinBounds(coords):
         raise Exception, "{0} out of bounds.".format(coords)
     else:
         return dict.__getitem__(self,coords)
Ejemplo n.º 40
0
    'quad4',"A 4-node quadrilateral",
    ndim = 2,
    vertices = [ (  0.0,  0.0, 0.0 ),
                 (  1.0,  0.0, 0.0 ),
                 (  1.0,  1.0, 0.0 ),
                 (  0.0,  1.0, 0.0 ),
                 ],
    edges = ('line2', [ (0,1), (1,2), (2,3), (3,0) ], ),
    )

Quad6 = Element(
    'quad6',"A 6-node quadrilateral",
    ndim = 2,
    vertices = Coords.concatenate([
        Quad4.vertices,
        [ (  0.5,  0.0, 0.0 ),
          (  0.5,  1.0, 0.0 ),
          ]]),
    edges = ('line3', [ (0,4,1), (1,1,2), (2,5,3), (3,3,0) ] ),
    reversed = (3,2,1,0,5,4),
    drawedges = [ ('line2', [(1,2), (3,0)]), 
                  ('line3', [(0,4,1), (2,5,3)])
                  ],
#    drawfaces = [('tri3',[(0,4,3),(4,5,3),(4,1,5),(1,2,5)])]
    drawfaces = [('quad4',[(0,4,5,3),(2,5,4,1)], )],
    )

Quad8 = Element(
    'quad8',"A 8-node quadrilateral",
    ndim = 2,
    vertices = Coords.concatenate([
Ejemplo n.º 41
0
class Toolpath:
    def __init__(self):
        self.length = 0.0
        self.lines = []
        self.current_pos = 0.0
        self.current_point = Point(0, 0, 0)
        self.current_line_index = 0
        self.tools = {} # dictionary, tool id to Tool object
        self.current_tool = 1
        self.rapid = True
        self.mm_per_sec = 50.0
        self.running = False
        self.coords = Coords(0, 0, 0, 0, 0, 0)
        self.in_cut_to_position = False
        
    def add_line(self, p0, p1):
        self.lines.append(Line(p0, p1, self.rapid, self.current_tool))
        
    def load(self, nc_filepath):
        # this converts the G1s in an NC file into arcs with G2 or G3
        pattern_main = re.compile('([(!;].*|\s+|[a-zA-Z0-9_:](?:[+-])?\d*(?:\.\d*)?|\w\#\d+|\(.*?\)|\#\d+\=(?:[+-])?\d*(?:\.\d*)?)')

        self.lines = []
        self.length = 0.0
        file = open(nc_filepath, 'r')
        arc = 0
        self.rapid = False
        curx = None
        cury = None
        curz = None
        
        while(True):
            line = file.readline().rstrip()
            if len(line)== 0: break
            
            move = False
            
            x = None
            y = None
            z = None
            i = None
            j = None
            
            words = pattern_main.findall(line)
            for word in words:
                word = word.upper()
                if word == 'G1' or word == 'G01':
                    self.rapid = False
                    arc = 0
                elif word == 'G2' or word == 'G02':
                    self.rapid = False
                    arc = -1
                elif word == 'G3' or word == 'G03':
                    self.rapid = False
                    arc = 1
                elif word == 'G0' or word == 'G00':
                    self.rapid = True
                    arc = 0
                elif word[0] == 'X':
                    x = eval(word[1:])
                    move = True
                elif word[0] == 'Y':
                    y = eval(word[1:])
                    move = True
                elif word[0] == 'Z':
                    z = eval(word[1:])
                    move = True
                elif word[0] == 'I':
                    i = float(eval(word[1:]))
                elif word[0] == 'J':
                    j = float(eval(word[1:]))
                elif word[0] == 'T':
                    self.current_tool = eval(word[1:])
                    if (curx != None) and (cury != None) and (curz != None):
                        self.add_line(Point(curx, cury, curz ), Point(curx, cury, 30.0))
                        curz = 30.0
                elif word[0] == ';' : break

            if move:
                if (curx != None) and (cury != None) and (curz != None):
                    newx = curx
                    newy = cury
                    newz = curz
                    if x != None: newx = float(x)
                    if y != None: newy = float(y)
                    if z != None: newz = float(z)
                    if arc != 0:
                        area.set_units(0.05)
                        curve = area.Curve()
                        curve.append(area.Point(curx, cury))
                        # next 4 lines were for Bridgeport.
                        # this only works for LinuxCNC now
                        #if (newx > curx) != (arc > 0):
                        #    j = -j
                        #if (newy > cury) != (arc < 0):
                        #    i = -i
                        curve.append(area.Vertex(arc, area.Point(newx, newy), area.Point(curx+i, cury+j)))
                        curve.UnFitArcs()
                        for span in curve.GetSpans():
                            self.add_line(Point(span.p.x, span.p.y, newz), Point(span.v.p.x, span.v.p.y, newz))
                    else:
                        self.add_line(Point(curx, cury, curz), Point(newx, newy, newz))
                                    
                if x != None: curx = float(x)
                if y != None: cury = float(y)
                if z != None: curz = float(z)

        for line in self.lines:
            self.length += line.Length()
               
        file.close()
        
        self.rewind()
        
    def rewind(self):
        self.current_point = Point(0, 0, 0)
        if len(self.lines)>0:
            self.current_point = self.lines[0].p0
        self.current_pos = 0.0
        self.current_line_index = 0
        self.running = False
        
    def draw_tool(self):
        voxelcut.drawclear()
        
        index = self.current_line_index - 1
        if index < 0: index = 0
        tool_number = self.lines[index].tool_number
        
        if tool_number in self.tools:
            x, y, z = self.coords.mm_to_voxels(self.current_point.x, self.current_point.y, self.current_point.z)
            self.tools[tool_number].draw(x, y, z)
        
    def cut_point(self, p):
        x, y, z = self.coords.mm_to_voxels(p.x, p.y, p.z)
        index = self.current_line_index - 1
        if index < 0: index = 0
        tool_number = self.lines[index].tool_number
        
        if tool_number in self.tools:
            self.tools[tool_number].cut(x, y, z)
         
    def cut_line(self, line):
#        self.cut_point(line.p0)
#        self.cut_point(line.p1)
#        voxelcut.remove_line(int(line.p0.x), int(line.p0.y), int(line.p0.z), int(line.p1.x), int(line.p1.y), int(line.p1.z), 5)
        
        length = line.Length()
        num_segments = int(1 + length * self.coords.voxels_per_mm * 0.06)
        step = length/num_segments
        dv = (line.p1 - line.p0) * (1.0/num_segments)
        for i in range (0, num_segments + 1):
            p = line.p0 + (dv * i)
            self.cut_point(p)
            
    def cut_to_position(self, pos):
        if self.current_line_index >= len(self.lines):
            return
        
        if self.cut_to_position == True:
            import wx
            wx.MessageBox("in cut_to_position again!")
        
        self.in_cut_to_position = True
        start_pos = self.current_pos
        while self.current_line_index < len(self.lines):
            line = copy.copy(self.lines[self.current_line_index])
            line.p0 = self.current_point
            line_length = line.Length()
            if line_length > 0:
                end_pos = self.current_pos + line_length
                if pos < end_pos:
                    fraction = (pos - self.current_pos)/(end_pos - self.current_pos)
                    line.p1 = line.p0 + ((line.p1 - line.p0) * fraction)
                    self.cut_line(line)
                    self.current_pos = pos
                    self.current_point = line.p1
                    break
                self.cut_line(line)
                self.current_pos = end_pos
            self.current_point = line.p1
            self.current_line_index = self.current_line_index + 1
            
        self.in_cut_to_position = False