def get_ref_value(cls, shape, ref_key, ref=None): ''' computes reference-values (minimum, maxium) for adjustments depending on ref-key ''' if ref != None and type(ref_key) in [int, float]: value = ref_key * ref elif ref_key == 'deg': value = cm_to_pt( 1 ) #convert to pt as setter/getter are converting back -> "double conversion" elif ref_key == 'h': value = shape.Height elif ref_key == 'h/2': value = shape.Height / 2 elif ref_key == 'h/4': value = shape.Height / 4 elif ref_key == 'w': value = shape.Width elif ref_key == 'w/2': value = shape.Width / 2 elif ref_key == 'min(hw)/2': value = min(shape.height, shape.width) / 2 elif ref_key == 'min(hw)*2': value = min(shape.height, shape.width) * 2 elif ref_key == 'min(hw)': value = min(shape.height, shape.width) else: value = None return value
class SplitShapes(object): default_row_sep = cm_to_pt(0.2) default_col_sep = cm_to_pt(0.2) default_rows = 6 default_cols = 6 @classmethod def split_shapes(cls, shapes, rows, cols, row_sep, col_sep): for shape in shapes: cls.split_shape(shape, rows, cols, row_sep, col_sep) @classmethod def split_shape(cls, shape, rows, cols, row_sep, col_sep): shape_width = shape.width shape_height = shape.height if cols > 1: shape_width = (shape.width - (cols - 1) * col_sep) / cols if rows > 1: shape_height = (shape.height - (rows - 1) * row_sep) / rows #shape.width = shape_width #shape.height = shape_height last_lock_aspect_ratio = shape.LockAspectRatio shape.LockAspectRatio = 0 for row_idx in range(rows): for col_idx in range(cols): if row_idx == 0 and col_idx == 0: shape_copy = shape else: shape_copy = shape.duplicate() shape_copy.left = shape.left + col_idx * (shape_width + col_sep) shape_copy.top = shape.top + row_idx * (shape_height + row_sep) shape_copy.width = shape_width shape_copy.height = shape_height shape_copy.LockAspectRatio = last_lock_aspect_ratio shape_copy.select(False)
def set_adjustment(cls, shape, num, value): ''' sets n's adjustment of shape, where value is assumed to be cm-value ''' if cls.get_shape_type( shape ) in cls.allowed_shape_types and shape.adjustments.count >= num: if type(value) == str: value = float(value.replace(',', '.')) # if cls.get_shape_autotype(shape) in cls.auto_shape_type_settings.keys(): try: ref, minimum, maximum = cls.get_ref_min_max(shape, num) pt_value = cm_to_pt(value) logging.debug('shape adjustment pt value=%s' % pt_value) if minimum != None: pt_value = max(minimum, pt_value) if maximum != None: pt_value = min(maximum, pt_value) shape.adjustments.item[num] = pt_value / ref # else: except ( KeyError, IndexError ): #KeyError = shape type is not in database, IndexError = adjustment number is not in database shape.adjustments.item[num] = value / 100
def split_shapes(self, sender, event): SplitShapes.split_shapes(self.ref_shapes, self._vm.rows, self._vm.columns, cm_to_pt(self._vm.rowsep), cm_to_pt(self._vm.columnsep)) self.Close()
def multiply_shapes(self, sender, event): MultiplyShapes.multiply_shapes(self.ref_shapes, self._vm.rows, self._vm.columns, cm_to_pt(self._vm.rowsep), cm_to_pt(self._vm.columnsep)) self.Close()
class CircularArrangement(object): DEBUG = False midpoint = [0, 0] rotated = False fixed_radius = False centerpoint = False width = cm_to_pt(10.0) height = cm_to_pt(8.5) segment_start = 0 @classmethod def _draw_debug_point(cls, shape, point, text=None): if not cls.DEBUG: return dot = shape.parent.shapes.addshape( 9, #msoShapeOval point[0] - 5, point[1] - 5, 10, 10) dot.TextFrame2.TextRange.Font.Size = 8 if text: dot.TextFrame2.TextRange.Text = text @classmethod def _draw_debug_circle(cls, shape, point, width, height): if not cls.DEBUG: return dot = shape.parent.shapes.addshape( 9, #msoShapeOval point[0] - width / 2, point[1] - height / 2, width, height) dot.fill.visible = 0 dot.line.ForeColor.RGB = 255 @classmethod def arrange_circular(cls, shapes): midpoint, width, height, segment_start = cls.get_ellipse_params(shapes) cls.arrange_circular_wargs(shapes, midpoint, width, height, segment_start) @classmethod def get_ellipse_params(cls, shapes): # compute weightend midpoint # shape_midpoints = [ [s.left+s.width/2.0, s.top+s.height/2.0] for s in shapes] # cls.midpoint = algorithms.mid_point(shape_midpoints) cls.midpoint = algorithms.mid_point_shapes(shapes) if cls.fixed_radius: cls.height = cls.width return (cls.midpoint, cls.width, cls.height, cls.segment_start) @classmethod def determine_ellipse_params(cls, shapes): # compute weightend midpoint shape_midpoints = [[s.left + s.width / 2, s.top + s.height / 2] for s in shapes] cls.midpoint = algorithms.mid_point(shape_midpoints) # compute if centerpoint exists if algorithms.is_close(shape_midpoints[0][0], cls.midpoint[0], 0.1) and algorithms.is_close( shape_midpoints[0][1], cls.midpoint[1], 0.1): cls.centerpoint = True #exclude centerpoint from further calculations del shape_midpoints[0] shapes = shapes[1:] else: cls.centerpoint = False # compute all vectors from midpoints to shapes vectors = [[sm[0] - cls.midpoint[0], sm[1] - cls.midpoint[1]] for sm in shape_midpoints] # interpolate segment start (angle to frist vector) cls.segment_start = math.degrees( math.atan2(vectors[0][1], vectors[0][0]) + math.pi / 2) #add pi/2 as 90° is subtracted in determine_points if cls.segment_start <= 0: cls.segment_start = ( 360 + cls.segment_start) % 360 #ensure positive value # interpolate radius as max for each vector part cls.width = max([v[0] for v in vectors]) * 2 cls.height = max([v[1] for v in vectors]) * 2 # # determine points # points = cls.determine_points(shapes, cls.midpoint, 2, 2, 90) # # compute radius # # x-stretch faktor for every point # factors = [ 1.0* (shape_midpoints[i][0]-cls.midpoint[0])/(points[i][0]-cls.midpoint[0]) for i in range(0, len(shapes)) if (points[i][0]-cls.midpoint[0]) != 0] # # middle strech factor # radius_x = sum(factors)/len(factors) # cls.width = 2*radius_x # # y-stretch faktor for every point # factors = [ 1.0* (shape_midpoints[i][1]-cls.midpoint[1])/(points[i][1]-cls.midpoint[1]) for i in range(0, len(shapes)) if (points[i][1]-cls.midpoint[1]) != 0] # # middle strech factor # radius_y = sum(factors)/len(factors) # cls.height = 2*radius_y # compute options cls.fixed_radius = algorithms.is_close(cls.height, cls.width, 0.1) cls.rotated = any(shapes[0].rotation != s.rotation for s in shapes) #debug drawings cls._draw_debug_circle(shapes[0], cls.midpoint, cls.width, cls.height) cls._draw_debug_point(shapes[0], cls.midpoint, "C") cls._draw_debug_point(shapes[0], shape_midpoints[0], "1") return (cls.midpoint, cls.width, cls.height, cls.segment_start) @classmethod def set_circ_width(cls, shapes, value): value = float(max(0, value)) cls.width = value if cls.fixed_radius: cls.height = value cls.arrange_circular(shapes) @classmethod def get_circ_width(cls, shapes): return cls.width @classmethod def set_circ_height(cls, shapes, value): value = float(max(0, value)) cls.height = value if cls.fixed_radius: cls.width = value cls.arrange_circular(shapes) @classmethod def get_circ_height(cls, shapes): return cls.height @classmethod def get_segment_start(cls, shapes): return round(cls.segment_start, 1) @classmethod def set_segment_start(cls, shapes, value): #ensure that value is positive and between 0 and 359 cls.segment_start = value if 0 <= value < 360 else (360 + value) % 360 cls.arrange_circular(shapes) @classmethod def determine_points(cls, shapes, midpoint, width, height, segment_start): # # Nullpunkt als Mittelpunkt verwenden, mit Radius 1 # segments = bezier.kreisSegmente(len(shapes), 1, [0,0]) # points = [ [s[0][0][0], s[0][0][1]] for s in segments] # # Segments starten rechts im Kreis # # Alle Punkte um 90 Grad nach links drehen, damit erstes Objekt oben steht # cls._draw_debug_point(shapes[0], midpoint, "C") # cls._draw_debug_point(shapes[0], points[0], "A") # points = [ algorithms.rotate_point(p[0], p[1], 0, 0, segment_start) for p in points] # cls._draw_debug_point(shapes[0], points[0], "B") # # Punkte skalieren (Höhe/Breite) # points = [ [ width/2 * p[0], height/2 * p[1] ] for p in points] # # Punkte verschieben anhand midpoint # points = [ [ p[0] + midpoint[0], p[1] + midpoint[1] ] for p in points] # if centerpoint-shape is active, lead first shape out for remaining calculation if cls.centerpoint: shapes = shapes[1:] points = algorithms.get_ellipse_points(len(shapes), width / 2.0, height / 2.0, segment_start - 90, midpoint) return points @classmethod def arrange_circular_wargs(cls, shapes, midpoint, width, height, segment_start): points = cls.determine_points(shapes, midpoint, width, height, segment_start) if cls.centerpoint: center_shape = shapes.pop(0) center_shape.left = midpoint[0] - center_shape.width / 2 center_shape.top = midpoint[1] - center_shape.height / 2 for i in range(0, len(shapes)): shapes[i].left = points[i][0] - shapes[i].width / 2 shapes[i].top = points[i][1] - shapes[i].height / 2 if cls.rotated: shapes[i].rotation = (360 / len(shapes) * i + segment_start) % 360 else: shapes[i].rotation = shapes[0].rotation @classmethod def arrange_circular_rotated(cls, pressed): cls.rotated = pressed @classmethod def arrange_circular_rotated_pressed(cls): return cls.rotated @classmethod def arrange_circular_fixed(cls, pressed): cls.fixed_radius = pressed @classmethod def arrange_circular_fixed_pressed(cls): return cls.fixed_radius @classmethod def arrange_circular_centerpoint(cls, pressed): cls.centerpoint = pressed @classmethod def arrange_circular_centerpoint_pressed(cls): return cls.centerpoint