def create_mark( self, mark='radical', angle='auto', draw=1, angle_resolution=1): """creates the mark, does not care about the chemical meaning of this""" # decide where to put the mark mark_name, mark_class = self._mark_to_name_and_class( mark) if angle == 'auto': x, y = self.find_place_for_mark( mark, resolution=angle_resolution) else: if not self.show: dist = 5 + round( mark_class.standard_size / 2) else: bbox = self.bbox() x2 = self.x + round( cos( angle) *1000) y2 = self.y + round( sin( angle) *1000) x1, y1 = geometry.intersection_of_line_and_rect( (self.x,self.y,x2,y2), bbox, round_edges=0) dist = geometry.point_distance( self.x, self.y, x1, y1) + round( mark_class.standard_size / 2) x = self.x + round( cos( angle) *dist) y = self.y + round( sin( angle) *dist) #ang = angle m = mark_class( self, x, y, auto=(angle=='auto')) if draw: m.draw() self.marks.add( m) return m
def create_mark(self, mark='radical', angle='auto', draw=1, angle_resolution=1): """creates the mark, does not care about the chemical meaning of this""" # decide where to put the mark mark_name, mark_class = self._mark_to_name_and_class(mark) if angle == 'auto': x, y = self.find_place_for_mark(mark, resolution=angle_resolution) else: if not self.show: dist = 5 + round(mark_class.standard_size / 2) else: bbox = self.bbox() x2 = self.x + round(cos(angle) * 1000) y2 = self.y + round(sin(angle) * 1000) x1, y1 = geometry.intersection_of_line_and_rect( (self.x, self.y, x2, y2), bbox, round_edges=0) dist = geometry.point_distance(self.x, self.y, x1, y1) + round( mark_class.standard_size / 2) x = self.x + round(cos(angle) * dist) y = self.y + round(sin(angle) * dist) #ang = angle m = mark_class(self, x, y, auto=(angle == 'auto')) if draw: m.draw() self.marks.add(m) return m
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)
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
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