Example #1
0
 def resize( self, coords, fix=()):
   if not fix:
     x1, y1, x2, y2 = misc.normalize_coords( coords)
     dx = x2 - x1
     dy = y2 - y1
     d = (abs( dx) + abs( dy))/2
     self.coords = (x1, y1, x1+d, y1+d)
   else:
     x1, y1, x2, y2 = coords
     dx = (fix[0] - x1) or (fix[0] - x2)
     dy = (fix[1] - y2) or (fix[1] - y1)
     d = (abs( dx) + abs( dy))/2
     self.coords = misc.normalize_coords( (fix[0], fix[1], x1-(d*misc.signum( dx) or d), y1-( d*misc.signum( dy) or d)))
   self.paper.coords( self.item, self.coords)
Example #2
0
  def _where_to_draw_from_and_to( self):
    x1, y1 = self.atom1.get_xy()
    x2, y2 = self.atom2.get_xy()
    # at first check if the bboxes are not overlapping
    bbox1 = list( misc.normalize_coords( self.atom1.bbox( substract_font_descent=True)))
    bbox2 = list( misc.normalize_coords( self.atom2.bbox( substract_font_descent=True)))
    if geometry.do_rectangles_intersect( bbox1, bbox2):
      return None
    # then we continue with computation
    if self.atom1.show:
      x1, y1 = geometry.intersection_of_line_and_rect( (x1,y1,x2,y2), bbox1, round_edges=0)
    if self.atom2.show:
      x2, y2 = geometry.intersection_of_line_and_rect( (x1,y1,x2,y2), bbox2, round_edges=0)

    if geometry.point_distance( x1, y1, x2, y2) <= 1.0:
      return None
    else:
      return (x1, y1, x2, y2)
Example #3
0
  def _where_to_draw_from_and_to( self):
    x1, y1 = self.atom1.get_xy()
    x2, y2 = self.atom2.get_xy()
    # at first check if the bboxes are not overlapping
    bbox1 = list( misc.normalize_coords( self.atom1.bbox( substract_font_descent=True)))
    bbox2 = list( misc.normalize_coords( self.atom2.bbox( substract_font_descent=True)))
    if geometry.do_rectangles_intersect( bbox1, bbox2):
      return None
    # then we continue with computation
    if self.atom1.show:
      x1, y1 = geometry.intersection_of_line_and_rect( (x1,y1,x2,y2), bbox1, round_edges=0)
    if self.atom2.show:
      x2, y2 = geometry.intersection_of_line_and_rect( (x1,y1,x2,y2), bbox2, round_edges=0)

    if geometry.point_distance( x1, y1, x2, y2) <= 1.0:
      return None
    else:
      return (x1, y1, x2, y2)
Example #4
0
def intersection_of_line_and_rect(line, rect, round_edges=0):
    """finds a point where a line and a rectangle intersect,
  both are given as lists of len == 4"""
    lx0, ly0, lx1, ly1 = map(float, line)
    rx0, ry0, rx1, ry1 = map(float, normalize_coords(rect))

    # find which end of line is in the rect and reverse the line if needed
    if (lx0 > rx0) and (lx0 < rx1) and (ly0 > ry0) and (ly0 < ry1):
        lx0, lx1 = lx1, lx0
        ly0, ly1 = ly1, ly0

    # the computation itself
    ldx = lx1 - lx0
    ldy = ly1 - ly0

    if abs(ldx) > 0.0001:
        # we calculate using y = f(x)
        k = ldy / ldx
        q = ly0 - k * lx0
        if ldx < 0:
            xx = rx1
        else:
            xx = rx0
        xy = k * xx + q
        # the result must be in the rectangle boundaries
        # but sometimes is not because rounding problems
        if not ry0 <= xy <= ry1:
            xx = lx0
            xy = ly0
    else:
        xx = lx0
        xy = ly0

    if abs(ldy) > 0.0001:
        # we calculate using x = f(y)
        k = ldx / ldy
        q = lx0 - k * ly0
        if ldy < 0:
            yy = ry1
        else:
            yy = ry0
        yx = k * yy + q
        # the result must be in the rectangle boundaries
        # but sometimes is not because rounding problems
        if not rx0 <= yx <= rx1:
            yy = ly0
            yx = lx0
    else:
        yy = ly0
        yx = lx0

    if point_distance(lx0, ly0, xx, xy) < point_distance(lx0, ly0, yx, yy):
        return (yx, yy)
    else:
        return (xx, xy)
Example #5
0
def intersection_of_line_and_rect( line, rect, round_edges=0):
  """finds a point where a line and a rectangle intersect,
  both are given as lists of len == 4"""
  lx0, ly0, lx1, ly1 = map( float, line)
  rx0, ry0, rx1, ry1 = map( float, normalize_coords( rect))

  # find which end of line is in the rect and reverse the line if needed
  if (lx0 > rx0) and (lx0 < rx1) and (ly0 > ry0) and (ly0 < ry1):
    lx0, lx1 = lx1, lx0
    ly0, ly1 = ly1, ly0

  # the computation itself
  ldx = lx1 - lx0
  ldy = ly1 - ly0

  if abs( ldx) > 0.0001:
    # we calculate using y = f(x)
    k = ldy/ldx
    q = ly0 - k*lx0
    if ldx < 0:
      xx = rx1
    else:
      xx = rx0
    xy = k*xx + q
    # the result must be in the rectangle boundaries
    # but sometimes is not because rounding problems
    if not ry0 <= xy <= ry1:
      xx = lx0
      xy = ly0
  else:
    xx = lx0
    xy = ly0
    
  if abs( ldy) > 0.0001:
    # we calculate using x = f(y)
    k = ldx/ldy
    q = lx0 - k*ly0
    if ldy < 0:
      yy = ry1
    else:
      yy = ry0
    yx = k*yy + q
    # the result must be in the rectangle boundaries
    # but sometimes is not because rounding problems
    if not rx0 <= yx <= rx1:
      yy = ly0
      yx = lx0
  else:
    yy = ly0
    yx = lx0
    
  if point_distance( lx0, ly0, xx, xy) < point_distance( lx0, ly0, yx, yy):
    return (yx, yy)
  else:
    return (xx, xy)
Example #6
0
 def get_fix(self):
     """returns the coords that should be fixed if we now start to drag the selected corner"""
     fix = [0, 0]
     self.coords = misc.normalize_coords(self.coords)
     if self._active_item in (self._lt, self._lb):
         fix[0] = self.coords[2]
     else:
         fix[0] = self.coords[0]
     if self._active_item in (self._lt, self._rt):
         fix[1] = self.coords[3]
     else:
         fix[1] = self.coords[1]
     return fix
Example #7
0
  def get_fix( self):
    """Return coords that should be fixed if we now drag selected corner.

    """
    fix = [0,0]
    self.coords = misc.normalize_coords( self.coords)
    if self._active_item in (self._lt, self._lb):
      fix[0] = self.coords[2]
    else:
      fix[0] = self.coords[0]
    if self._active_item in (self._lt, self._rt):
      fix[1] = self.coords[3]
    else:
      fix[1] = self.coords[1]
    return fix
Example #8
0
  def find_place_for_mark( self, mark, resolution=30):
    """resolution says if the angles should be somehow 'rounded', it is given in degrees;
    see geometry.point_on_circle for a similar thing"""
    mark_name, mark_class = self._mark_to_name_and_class( mark)

    # deal with marks centered
    if mark_class.meta__mark_positioning == 'atom':
      return self.x, self.y

    # deal with statically positioned marks
    if mark_class.meta__mark_positioning == 'righttop':
      bbox = self.bbox()
      return bbox[2]+2, bbox[1]
    
    # deal with marks in linear_form
    if self.is_part_of_linear_fragment():
      if mark_name == "atom_number":
        bbox = self.bbox()
        return int( self.x-0.5*self.font_size), bbox[1]-2
    

    if not self.show:
      dist = 5 + round( mark_class.standard_size / 2)
    else:
      dist = 0.75*self.font_size + round( mark_class.standard_size / 2)

    atms = self.get_neighbors()
    x, y = self.get_xy()

    # special cases
    if not atms:
      # single atom molecule
      if self.show_hydrogens and self.pos == "center-first":
        return x -dist, y-3
      else:
        return x +dist, y-3

    # normal case
    coords = [(a.x,a.y) for a in atms]
    # we have to take marks into account
    [coords.append( (m.x, m.y)) for m in self.marks]
    # hydrogen positioning is also important
    if self.show_hydrogens and self.show:
      if self.pos == 'center-last':
        coords.append( (x-10,y))
      else:
        coords.append( (x+10,y))
    # now we can compare the angles
    angles = [geometry.clockwise_angle_from_east( x1-x, y1-y) for x1,y1 in coords]
    angles.append( 2*pi + min( angles))
    angles.sort()
    angles.reverse()
    diffs = misc.list_difference( angles)
    i = diffs.index( max( diffs))
    angle = (angles[i] +angles[i+1]) / 2

    # we calculate the distance here again as it is anisotropic (depends on direction)
    bbox = list( misc.normalize_coords( self.bbox()))
    x0, y0 = geometry.point_on_circle( x, y, 500, direction=(cos(angle), sin( angle)), resolution=resolution)
    x1, y1 = geometry.intersection_of_line_and_rect( (x,y,x0,y0), bbox, round_edges=0)
    dist = geometry.point_distance( x, y, x1, y1) + round( mark_class.standard_size / 2)
    # //

    
    retx, rety = geometry.point_on_circle( x, y, dist, direction=(cos(angle), sin( angle)), resolution=resolution)

    # in visible text x,y are not on the center, therefore we compensate for it
#    if self.show:
#      y -= 0.166 * self.font_size
    
    return retx, rety
Example #9
0
 def resize( self, coords, fix=()):
   self.coords = misc.normalize_coords( coords)
   self.paper.coords( self.item, self.coords)
Example #10
0
    def find_place_for_mark(self, mark, resolution=30):
        """resolution says if the angles should be somehow 'rounded', it is given in degrees;
    see geometry.point_on_circle for a similar thing"""
        mark_name, mark_class = self._mark_to_name_and_class(mark)

        # deal with marks centered
        if mark_class.meta__mark_positioning == 'atom':
            return self.x, self.y

        # deal with statically positioned marks
        if mark_class.meta__mark_positioning == 'righttop':
            bbox = self.bbox()
            return bbox[2] + 2, bbox[1]

        # deal with marks in linear_form
        if self.is_part_of_linear_fragment():
            if mark_name == "atom_number":
                bbox = self.bbox()
                return int(self.x - 0.5 * self.font_size), bbox[1] - 2

        if not self.show:
            dist = 5 + round(mark_class.standard_size / 2)
        else:
            dist = 0.75 * self.font_size + round(mark_class.standard_size / 2)

        atms = self.get_neighbors()
        x, y = self.get_xy()

        # special cases
        if not atms:
            # single atom molecule
            if self.show_hydrogens and self.pos == "center-first":
                return x - dist, y - 3
            else:
                return x + dist, y - 3

        # normal case
        coords = [(a.x, a.y) for a in atms]
        # we have to take marks into account
        [coords.append((m.x, m.y)) for m in self.marks]
        # hydrogen positioning is also important
        if self.show_hydrogens and self.show:
            if self.pos == 'center-last':
                coords.append((x - 10, y))
            else:
                coords.append((x + 10, y))
        # now we can compare the angles
        angles = [
            geometry.clockwise_angle_from_east(x1 - x, y1 - y)
            for x1, y1 in coords
        ]
        angles.append(2 * pi + min(angles))
        angles.sort()
        angles.reverse()
        diffs = misc.list_difference(angles)
        i = diffs.index(max(diffs))
        angle = (angles[i] + angles[i + 1]) / 2

        # we calculate the distance here again as it is anisotropic (depends on direction)
        bbox = list(misc.normalize_coords(self.bbox()))
        x0, y0 = geometry.point_on_circle(x,
                                          y,
                                          500,
                                          direction=(cos(angle), sin(angle)),
                                          resolution=resolution)
        x1, y1 = geometry.intersection_of_line_and_rect((x, y, x0, y0),
                                                        bbox,
                                                        round_edges=0)
        dist = geometry.point_distance(x, y, x1, y1) + round(
            mark_class.standard_size / 2)
        # //

        retx, rety = geometry.point_on_circle(x,
                                              y,
                                              dist,
                                              direction=(cos(angle),
                                                         sin(angle)),
                                              resolution=resolution)

        # in visible text x,y are not on the center, therefore we compensate for it
        #    if self.show:
        #      y -= 0.166 * self.font_size

        return retx, rety