def Snap(self, p): try: r, phi = self.trafo.inverse()(p).polar() start_angle = self.start_angle end_angle = self.end_angle p2 = self.trafo(Polar(1, phi)) if start_angle == end_angle: result = (abs(p - p2), p2) else: result = [] if phi < 0: phi = phi + 2 * pi if start_angle < end_angle: between = start_angle <= phi <= end_angle else: between = start_angle <= phi or phi <= end_angle if between: result.append((abs(p - p2), p2)) start = self.trafo(Polar(self.start_angle)) end = self.trafo(Polar(self.end_angle)) if self.arc_type == ArcArc: result.append((abs(start - p), start)) result.append((abs(end - p), end)) elif self.arc_type == ArcChord: result.append((snap_to_line(start, end, p))) elif self.arc_type == ArcPieSlice: center = self.trafo.offset() result.append(snap_to_line(start, center, p)) result.append(snap_to_line(end, center, p)) result = min(result) return result except SingularMatrix: # XXX this case could be handled better. return (1e200, p)
def create_star_path(corners, outer_radius, inner_radius): outer_radius = unit.convert(outer_radius) inner_radius = unit.convert(inner_radius) path = CreatePath() angle = math.pi * 2 / corners for i in range(corners): path.AppendLine(Polar(outer_radius, angle * i)) path.AppendLine(Polar(inner_radius, angle * i + angle / 2)) path.AppendLine(path.Node(0)) path.ClosePath() return path
def gradient_geometry(self, flag, name, xorig, yorig, angle, length, a, b, c, d, tx, ty): trafo = Trafo(a, b, c, d, tx, ty) trafo = artboard_trafo_inv(trafo(artboard_trafo)) start = Point(xorig, yorig) end = start + Polar(length, (pi * angle) / 180.0) self.gradient_geo = (name, trafo, start, end)
def apply_constraint(self, p, state): if state & const.ConstraintMask: r, phi = (p - self.start).polar() pi12 = pi / 12 phi = pi12 * floor(phi / pi12 + 0.5) p = self.start + Polar(r, phi) return p
def apply_constraint(self, p, state): if state: if self.selection in self.selAspect: ref_x, ref_y = self.reference aspect = self.aspect if aspect is None: # width is 0 p = Point(self.drag_start.x, p.y) else: w = p.x - ref_x h = p.y - ref_y if w == 0: w = 0.00001 a = h / w if a > 0: sign = 1 else: sign = -1 if abs(a) > aspect: h = sign * w * aspect else: w = sign * h / aspect p = Point(ref_x + w, ref_y + h) # if state & const.AlternateMask: # pi4 = math.pi / 4 # off = p - self.drag_start # d = Polar(pi4 * round(math.atan2(off.y, off.x) / pi4)) # p = self.drag_start + (off * d) * d # print 'ALT' if state & const.ConstraintMask:# and self.selection == -1: pi4 = math.pi / 4 off = p - self.drag_start d = Polar(pi4 * round(math.atan2(off.y, off.x) / pi4)) p = self.drag_start + (off * d) * d return p
def GetSnapPoints(self): t = self.trafo start_angle = self.start_angle end_angle = self.end_angle if self.start_angle == self.end_angle: a = Point(t.m11, t.m21) b = Point(t.m12, t.m22) c = t.offset() return [c, c + a, c - a, c + b, c - b] else: points = [t(Polar(start_angle)), t(Polar(end_angle)), t.offset()] if end_angle < start_angle: end_angle = end_angle + 2 * pi pi2 = pi / 2 angle = pi2 * (floor(start_angle / pi2) + 1) while angle < end_angle: points.append(t(Polar(1, angle))) angle = angle + pi2 return points
def Snap(self, p): try: x, y = self.trafo.inverse()(p) minx = self.radius1 maxx = 1 - self.radius1 miny = self.radius2 maxy = 1 - self.radius2 if minx < x < maxx: if miny < y < maxy: ratio = hypot(self.trafo.m11, self.trafo.m21) \ / hypot(self.trafo.m12, self.trafo.m22) if x < 0.5: dx = x else: dx = 1 - x if y < 0.5: dy = y else: dy = 1 - y if dy / dx > ratio: x = round(x) else: y = round(y) elif y > maxy: y = 1 else: y = 0 elif miny < y < maxy: if x > maxx: x = 1 else: x = 0 elif minx > 0 and miny > 0: # the round corners if x < 0.5: cx = minx else: cx = maxx if y < 0.5: cy = miny else: cy = maxy trafo = Trafo(minx, 0, 0, miny, cx, cy) r, phi = trafo.inverse()(x, y).polar() x, y = trafo(Polar(1, phi)) else: # normal corners x = round(min(max(x, 0), 1)) y = round(min(max(y, 0), 1)) p2 = self.trafo(x, y) return (abs(p - p2), p2) except SingularMatrix: return (1e200, p)
def Ellipse(self, ell): trf = ell.trafo if (trf.m12 == 0 and trf.m21 == 0) or (trf.m11 == 0 and trf.m22 == 0): self.FillStyle(ell.Properties()) left, top, right, bottom = self.rect_to_ltrb(ell, Point(-1, -1)) if ell.start_angle == ell.end_angle: self.packrec('<LHhhhh', 7, 0x0418, bottom, right, top, left) else: xe, ye = map(rndtoint, self.trafo(ell.trafo(Polar(1, ell.start_angle)))) xs, ys = map(rndtoint, self.trafo(ell.trafo(Polar(1, ell.end_angle)))) if ell.arc_type == const.ArcArc: function = 0x0817 elif ell.arc_type == const.ArcPieSlice: function = 0x081A elif ell.arc_type == const.ArcChord: function = 0x0830 self.packrec('<LHhhhhhhhh', 11, function, ye, xe, ys, xs, bottom, right, top, left) else: self.PolyBezier(ell.Paths(), ell.Properties())
def update_rects(self): trafo = self.trafo start = trafo.offset() # On some systems, atan2 can raise a ValueError if both # parameters are 0. In that case, the actual value the of angle # is not important since in the computation of p below, the # coordinate depending on the angle will always be 0 because # both trafo coefficients are 0. So set the angle to 0 in case # of an exception. try: phi1 = atan2(trafo.m12, trafo.m11) except ValueError: phi1 = 0 try: phi2 = atan2(trafo.m22, trafo.m21) except ValueError: phi2 = 0 p = Point(trafo.m11 * cos(phi1) + trafo.m12 * sin(phi1), trafo.m21 * cos(phi2) + trafo.m22 * sin(phi2)) self.coord_rect = r = Rect(start + p, start - p) if self.properties.HasLine(): width = self.properties.line_width r = r.grown(width / 2 + 1) # add the bounding boxes of arrows if self.arc_type == ArcArc: pi2 = pi / 2 arrow1 = self.properties.line_arrow1 if arrow1 is not None: pos = trafo(Polar(1, self.start_angle)) dir = trafo.DTransform(Polar(1, self.start_angle - pi2)) r = UnionRects(r, arrow1.BoundingRect(pos, dir, width)) arrow2 = self.properties.line_arrow2 if arrow2 is not None: pos = trafo(Polar(1, self.end_angle)) dir = trafo.DTransform(Polar(1, self.end_angle + pi2)) r = UnionRects(r, arrow2.BoundingRect(pos, dir, width)) self.bounding_rect = r
def create_star_path(corners, step, radius): # create a star-like polygon. center = Point(300, 400) radius = 100 angle = step * 2 * pi / corners # create an empty path and append the line segments path = CreatePath() for i in range(corners): p = Polar(radius, angle * i + pi / 2) path.AppendLine(p) # close the path. path.AppendLine(path.Node(0)) path.ClosePath() return path
def create_spiral_path(rotation, radius): r = unit.convert(radius) rate = r / (rotation * 2 * pi) def tangent(phi, a=0.55197 * rate): return a * Point(cos(phi) - phi * sin(phi), sin(phi) + phi * cos(phi)) pi2 = pi / 2.0 angle = 0 tang = tangent(0) path = CreatePath() p = Point(0, 0) path.AppendLine(p) for i in range(rotation * 4): p1 = p + tang angle = pi2 * (i + 1) p = Polar(rate * angle, angle) tang = tangent(angle) p2 = p - tang path.AppendBezier(p1, p2, p, ContSymmetrical) return path
def apply_constraint(self, p, state): if state & ConstraintMask: try: inverse = self.trafo.inverse() p2 = inverse(p) r, phi = p2.polar() pi12 = pi / 12 angle = pi12 * floor(phi / pi12 + 0.5) pi2 = 2 * pi d1 = fmod(abs(phi - angle), pi2) if self.selection == 1: selected_angle = self.end_angle else: selected_angle = self.start_angle d2 = fmod(abs(phi - selected_angle), pi2) if d2 < d1: phi = selected_angle else: phi = angle p = self.trafo(Polar(r, phi)) except SingularMatrix: pass return p