X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/dcbafcc2df78243a012627b3eb88d5cbde574ae7..b2f6eb0606be607c176121ad4ae272e3112f44eb:/wxPython/wx/lib/ogl/_oglmisc.py?ds=inline diff --git a/wxPython/wx/lib/ogl/_oglmisc.py b/wxPython/wx/lib/ogl/_oglmisc.py new file mode 100644 index 0000000000..42a79b2b15 --- /dev/null +++ b/wxPython/wx/lib/ogl/_oglmisc.py @@ -0,0 +1,416 @@ +# -*- coding: iso-8859-1 -*- +#---------------------------------------------------------------------------- +# Name: oglmisc.py +# Purpose: Miscellaneous OGL support functions +# +# Author: Pierre Hjälm (from C++ original by Julian Smart) +# +# Created: 2004-05-08 +# RCS-ID: $Id$ +# Copyright: (c) 2004 Pierre Hjälm - 1998 Julian Smart +# Licence: wxWindows license +#---------------------------------------------------------------------------- + +from __future__ import division +import math + +import wx + +# Control point types +# Rectangle and most other shapes +CONTROL_POINT_VERTICAL = 1 +CONTROL_POINT_HORIZONTAL = 2 +CONTROL_POINT_DIAGONAL = 3 + +# Line +CONTROL_POINT_ENDPOINT_TO = 4 +CONTROL_POINT_ENDPOINT_FROM = 5 +CONTROL_POINT_LINE = 6 + +# Types of formatting: can be combined in a bit list +FORMAT_NONE = 0 # Left justification +FORMAT_CENTRE_HORIZ = 1 # Centre horizontally +FORMAT_CENTRE_VERT = 2 # Centre vertically +FORMAT_SIZE_TO_CONTENTS = 4 # Resize shape to contents + +# Attachment modes +ATTACHMENT_MODE_NONE, ATTACHMENT_MODE_EDGE, ATTACHMENT_MODE_BRANCHING = 0, 1, 2 + +# Shadow mode +SHADOW_NONE, SHADOW_LEFT, SHADOW_RIGHT = 0, 1, 2 + +OP_CLICK_LEFT, OP_CLICK_RIGHT, OP_DRAG_LEFT, OP_DRAG_RIGHT = 1, 2, 4, 8 +OP_ALL = OP_CLICK_LEFT | OP_CLICK_RIGHT | OP_DRAG_LEFT | OP_DRAG_RIGHT + +# Sub-modes for branching attachment mode +BRANCHING_ATTACHMENT_NORMAL = 1 +BRANCHING_ATTACHMENT_BLOB = 2 + +# logical function to use when drawing rubberband boxes, etc. +OGLRBLF = wx.INVERT + +CONTROL_POINT_SIZE = 6 + +# Types of arrowhead +# (i) Built-in +ARROW_HOLLOW_CIRCLE = 1 +ARROW_FILLED_CIRCLE = 2 +ARROW_ARROW = 3 +ARROW_SINGLE_OBLIQUE = 4 +ARROW_DOUBLE_OBLIQUE = 5 +# (ii) Custom +ARROW_METAFILE = 20 + +# Position of arrow on line +ARROW_POSITION_START = 0 +ARROW_POSITION_END = 1 +ARROW_POSITION_MIDDLE = 2 + +# Line alignment flags +# Vertical by default +LINE_ALIGNMENT_HORIZ = 1 +LINE_ALIGNMENT_VERT = 0 +LINE_ALIGNMENT_TO_NEXT_HANDLE = 2 +LINE_ALIGNMENT_NONE = 0 + + + +# Format a string to a list of strings that fit in the given box. +# Interpret %n and 10 or 13 as a new line. +def FormatText(dc, text, width, height, formatMode): + i = 0 + word="" + word_list = [] + end_word = False + new_line = False + while i0: + string_list.append(buffer) + buffer="" + else: + if len(buffer): + buffer+=" " + buffer += s + x, y = dc.GetTextExtent(buffer) + + # Don't fit within the bounding box if we're fitting + # shape to contents + if (x>width) and not (formatMode & FORMAT_SIZE_TO_CONTENTS): + # Deal with first word being wider than box + if len(oldBuffer): + string_list.append(oldBuffer) + buffer = s + if len(buffer): + string_list.append(buffer) + + return string_list + + + +def GetCentredTextExtent(dc, text_list, xpos = 0, ypos = 0, width = 0, height = 0): + if not text_list: + return 0, 0 + + max_width = 0 + for line in text_list: + current_width, char_height = dc.GetTextExtent(line) + if current_width>max_width: + max_width = current_width + + return max_width, len(text_list) * char_height + + + +def CentreText(dc, text_list, xpos, ypos, width, height, formatMode): + if not text_list: + return + + # First, get maximum dimensions of box enclosing text + char_height = 0 + max_width = 0 + current_width = 0 + + # Store text extents for speed + widths = [] + for line in text_list: + current_width, char_height = dc.GetTextExtent(line.GetText()) + widths.append(current_width) + if current_width>max_width: + max_width = current_width + + max_height = len(text_list) * char_height + + if formatMode & FORMAT_CENTRE_VERT: + if max_height(val2 - tol) and \ + val2<(val1 + tol) and val2>(val1 - tol) + + + +def FindEndForBox(width, height, x1, y1, x2, y2): + xvec = [x1 - width / 2, x1 - width / 2, x1 + width / 2, x1 + width / 2, x1 - width / 2] + yvec = [y1 - height / 2, y1 + height / 2, y1 + height / 2, y1 - height / 2, y1 - height / 2] + + return FindEndForPolyline(xvec, yvec, x2, y2, x1, y1) + + + +def CheckLineIntersection(x1, y1, x2, y2, x3, y3, x4, y4): + denominator_term = (y4 - y3) * (x2 - x1) - (y2 - y1) * (x4 - x3) + numerator_term = (x3 - x1) * (y4 - y3) + (x4 - x3) * (y1 - y3) + + length_ratio = 1.0 + k_line = 1.0 + + # Check for parallel lines + if denominator_term<0.005 and denominator_term>-0.005: + line_constant=-1.0 + else: + line_constant = float(numerator_term) / denominator_term + + # Check for intersection + if line_constant<1.0 and line_constant>0.0: + # Now must check that other line hits + if (y4 - y3)<0.005 and (y4 - y3)>-0.005: + k_line = (x1 - x3 + line_constant * (x2 - x1)) / (x4 - x3) + else: + k_line = (y1 - y3 + line_constant * (y2 - y1)) / (y4 - y3) + if k_line >= 0 and k_line<1: + length_ratio = line_constant + else: + k_line = 1 + + return length_ratio, k_line + + + +def FindEndForPolyline(xvec, yvec, x1, y1, x2, y2): + lastx = xvec[0] + lasty = yvec[0] + + min_ratio = 1.0 + + for i in range(1, len(xvec)): + line_ratio, other_ratio = CheckLineIntersection(x1, y1, x2, y2, lastx, lasty, xvec[i], yvec[i]) + lastx = xvec[i] + lasty = yvec[i] + + if line_ratio1: + point2[0] = point1[0] + else: + point2[1] = point1[0] + + + +def GetPointOnLine(x1, y1, x2, y2, length): + l = math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1)) + if l<0.01: + l = 0.01 + + i_bar = (x2 - x1) / l + j_bar = (y2 - y1) / l + + return -length * i_bar + x2,-length * j_bar + y2 + + + +def GetArrowPoints(x1, y1, x2, y2, length, width): + l = math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1)) + + if l<0.01: + l = 0.01 + + i_bar = (x2 - x1) / l + j_bar = (y2 - y1) / l + + x3=-length * i_bar + x2 + y3=-length * j_bar + y2 + + return x2, y2, width*-j_bar + x3, width * i_bar + y3,-width*-j_bar + x3,-width * i_bar + y3 + + + +def DrawArcToEllipse(x1, y1, width1, height1, x2, y2, x3, y3): + a1 = width1 / 2 + b1 = height1 / 2 + + # Check that x2 != x3 + if abs(x2 - x3)<0.05: + x4 = x2 + if y3>y2: + y4 = y1 - math.sqrt((b1 * b1 - (((x2 - x1) * (x2 - x1)) * (b1 * b1) / (a1 * a1)))) + else: + y4 = y1 + math.sqrt((b1 * b1 - (((x2 - x1) * (x2 - x1)) * (b1 * b1) / (a1 * a1)))) + return x4, y4 + + # Calculate the x and y coordinates of the point where arc intersects ellipse + A = (1 / (a1 * a1)) + B = ((y3 - y2) * (y3 - y2)) / ((x3 - x2) * (x3 - x2) * b1 * b1) + C = (2 * (y3 - y2) * (y2 - y1)) / ((x3 - x2) * b1 * b1) + D = ((y2 - y1) * (y2 - y1)) / (b1 * b1) + E = (A + B) + F = (C - (2 * A * x1) - (2 * B * x2)) + G = ((A * x1 * x1) + (B * x2 * x2) - (C * x2) + D - 1) + H = ((y3 - y2) / (x2 - x2)) + K = ((F * F) - (4 * E * G)) + + if K >= 0: + # In this case the line intersects the ellipse, so calculate intersection + if x2 >= x1: + ellipse1_x = ((F*-1) + math.sqrt(K)) / (2 * E) + ellipse1_y = ((H * (ellipse1_x - x2)) + y2) + else: + ellipse1_x = (((F*-1) - math.sqrt(K)) / (2 * E)) + ellipse1_y = ((H * (ellipse1_x - x2)) + y2) + else: + # in this case, arc does not intersect ellipse, so just draw arc + ellipse1_x = x3 + ellipse1_y = y3 + + return ellipse1_x, ellipse1_y + + + +def FindEndForCircle(radius, x1, y1, x2, y2): + H = math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1)) + + if H == 0: + return x1, y1 + else: + return radius * (x2 - x1) / H + x1, radius * (y2 - y1) / H + y1