graphics/GraphicCommons.py
branchpython3
changeset 3792 365f866ee120
parent 3774 5a3c5dc888cc
child 3794 36934591f6eb
equal deleted inserted replaced
3791:c98646b1c981 3792:365f866ee120
   181     """
   181     """
   182     Function that calculates the nearest point of the grid defined by scaling for the given point
   182     Function that calculates the nearest point of the grid defined by scaling for the given point
   183     """
   183     """
   184     pos = event.GetLogicalPosition(dc)
   184     pos = event.GetLogicalPosition(dc)
   185     if scaling:
   185     if scaling:
   186         pos.x = round(pos.x / scaling[0]) * scaling[0]
   186         sx,sy=tuple(map(round,scaling))
   187         pos.y = round(pos.y / scaling[1]) * scaling[1]
   187         pos.x = round(pos.x / sx) * sx
       
   188         pos.y = round(pos.y / sy) * sy
   188     return pos
   189     return pos
   189 
   190 
   190 
   191 
   191 def DirectionChoice(v_base, v_target, dir_target):
   192 def DirectionChoice(v_base, v_target, dir_target):
   192     """
   193     """
   199         return dir_target
   200         return dir_target
   200     return v_base
   201     return v_base
   201 
   202 
   202 
   203 
   203 def MiterPen(colour, width=1, style=wx.SOLID):
   204 def MiterPen(colour, width=1, style=wx.SOLID):
   204     pen = wx.Pen(colour, width, style)
   205     pen = wx.Pen(colour, round(width), style)
   205     pen.SetJoin(wx.JOIN_MITER)
   206     pen.SetJoin(wx.JOIN_MITER)
   206     pen.SetCap(wx.CAP_PROJECTING)
   207     pen.SetCap(wx.CAP_PROJECTING)
   207     return pen
   208     return pen
   208 
   209 
   209 
   210 
   312     def Clone(self, parent):
   313     def Clone(self, parent):
   313         return Graphic_Element(parent, self.Id)
   314         return Graphic_Element(parent, self.Id)
   314 
   315 
   315     # Changes the block position
   316     # Changes the block position
   316     def SetPosition(self, x, y):
   317     def SetPosition(self, x, y):
   317         self.Pos.x = x
   318         self.Pos.x = int(x)
   318         self.Pos.y = y
   319         self.Pos.y = int(y)
   319         self.RefreshConnected()
   320         self.RefreshConnected()
   320         self.RefreshBoundingBox()
   321         self.RefreshBoundingBox()
   321 
   322 
   322     # Returns the block position
   323     # Returns the block position
   323     def GetPosition(self):
   324     def GetPosition(self):
   324         return self.Pos.x, self.Pos.y
   325         return self.Pos.x, self.Pos.y
   325 
   326 
   326     # Changes the element size
   327     # Changes the element size
   327     def SetSize(self, width, height):
   328     def SetSize(self, width, height):
   328         self.Size.SetWidth(width)
   329         self.Size.SetWidth(int(width))
   329         self.Size.SetHeight(height)
   330         self.Size.SetHeight(int(height))
   330         self.RefreshConnectors()
   331         self.RefreshConnectors()
   331         self.RefreshBoundingBox()
   332         self.RefreshBoundingBox()
   332 
   333 
   333     # Returns the element size
   334     # Returns the element size
   334     def GetSize(self):
   335     def GetSize(self):
   429         dc = self.Parent.GetLogicalDC()
   430         dc = self.Parent.GetLogicalDC()
   430         scalex, scaley = dc.GetUserScale()
   431         scalex, scaley = dc.GetUserScale()
   431         pos = event.GetPosition()
   432         pos = event.GetPosition()
   432         pt = wx.Point(*self.Parent.CalcUnscrolledPosition(pos.x, pos.y))
   433         pt = wx.Point(*self.Parent.CalcUnscrolledPosition(pos.x, pos.y))
   433 
   434 
   434         left = (self.BoundingBox.x - 2) * scalex - HANDLE_SIZE
   435         left = round((self.BoundingBox.x - 2) * scalex - HANDLE_SIZE)
   435         center = (self.BoundingBox.x + self.BoundingBox.width // 2) * scalex - HANDLE_SIZE // 2
   436         center = round((self.BoundingBox.x + self.BoundingBox.width // 2) * scalex - HANDLE_SIZE // 2)
   436         right = (self.BoundingBox.x + self.BoundingBox.width + 2) * scalex
   437         right = round((self.BoundingBox.x + self.BoundingBox.width + 2) * scalex)
   437 
   438 
   438         top = (self.BoundingBox.y - 2) * scaley - HANDLE_SIZE
   439         top = round((self.BoundingBox.y - 2) * scaley - HANDLE_SIZE)
   439         middle = (self.BoundingBox.y + self.BoundingBox.height / 2) * scaley - HANDLE_SIZE // 2
   440         middle = round((self.BoundingBox.y + self.BoundingBox.height / 2) * scaley - HANDLE_SIZE // 2)
   440         bottom = (self.BoundingBox.y + self.BoundingBox.height + 2) * scaley
   441         bottom = round((self.BoundingBox.y + self.BoundingBox.height + 2) * scaley)
   441 
   442 
   442         extern_rect = wx.Rect(left, top, right + HANDLE_SIZE - left, bottom + HANDLE_SIZE - top)
   443         extern_rect = wx.Rect(left, top, right + HANDLE_SIZE - left, bottom + HANDLE_SIZE - top)
   443         intern_rect = wx.Rect(left + HANDLE_SIZE, top + HANDLE_SIZE, right - left - HANDLE_SIZE, bottom - top - HANDLE_SIZE)
   444         intern_rect = wx.Rect(left + HANDLE_SIZE, top + HANDLE_SIZE, right - left - HANDLE_SIZE, bottom - top - HANDLE_SIZE)
   444 
   445 
   445         # Verify that this element is selected
   446         # Verify that this element is selected
   677                 scalex, scaley = dc.GetUserScale()
   678                 scalex, scaley = dc.GetUserScale()
   678                 dc.SetUserScale(1, 1)
   679                 dc.SetUserScale(1, 1)
   679                 dc.SetPen(MiterPen(wx.BLACK))
   680                 dc.SetPen(MiterPen(wx.BLACK))
   680                 dc.SetBrush(wx.BLACK_BRUSH)
   681                 dc.SetBrush(wx.BLACK_BRUSH)
   681 
   682 
   682                 left = (self.BoundingBox.x - 2) * scalex - HANDLE_SIZE
   683                 left = round((self.BoundingBox.x - 2) * scalex - HANDLE_SIZE)
   683                 center = (self.BoundingBox.x + self.BoundingBox.width // 2) * scalex - HANDLE_SIZE // 2
   684                 center = round((self.BoundingBox.x + self.BoundingBox.width // 2) * scalex - HANDLE_SIZE // 2)
   684                 right = (self.BoundingBox.x + self.BoundingBox.width + 2) * scalex
   685                 right = round((self.BoundingBox.x + self.BoundingBox.width + 2) * scalex)
   685 
   686 
   686                 top = (self.BoundingBox.y - 2) * scaley - HANDLE_SIZE
   687                 top = round((self.BoundingBox.y - 2) * scaley - HANDLE_SIZE)
   687                 middle = (self.BoundingBox.y + self.BoundingBox.height // 2) * scaley - HANDLE_SIZE // 2
   688                 middle = round((self.BoundingBox.y + self.BoundingBox.height // 2) * scaley - HANDLE_SIZE // 2)
   688                 bottom = (self.BoundingBox.y + self.BoundingBox.height + 2) * scaley
   689                 bottom = round((self.BoundingBox.y + self.BoundingBox.height + 2) * scaley)
   689 
   690 
   690                 for x, y in [(left, top), (center, top), (right, top),
   691                 for x, y in [(left, top), (center, top), (right, top),
   691                              (left, middle), (right, middle),
   692                              (left, middle), (right, middle),
   692                              (left, bottom), (center, bottom), (right, bottom)]:
   693                              (left, bottom), (center, bottom), (right, bottom)]:
   693                     dc.DrawRectangle(x, y, HANDLE_SIZE, HANDLE_SIZE)
   694                     dc.DrawRectangle(x, y, HANDLE_SIZE, HANDLE_SIZE)
  1976 
  1977 
  1977             # Calculate the start and end directions
  1978             # Calculate the start and end directions
  1978             self.StartPoint = [None, vector(self.Points[0], self.Points[1])]
  1979             self.StartPoint = [None, vector(self.Points[0], self.Points[1])]
  1979             self.EndPoint = [None, vector(self.Points[-1], self.Points[-2])]
  1980             self.EndPoint = [None, vector(self.Points[-1], self.Points[-2])]
  1980             # Calculate the start and end points
  1981             # Calculate the start and end points
  1981             self.StartPoint[0] = wx.Point(self.Points[0].x + CONNECTOR_SIZE * self.StartPoint[1][0],
  1982             self.StartPoint[0] = wx.Point(self.Points[0].x + round(CONNECTOR_SIZE * self.StartPoint[1][0]),
  1982                                           self.Points[0].y + CONNECTOR_SIZE * self.StartPoint[1][1])
  1983                                           self.Points[0].y + round(CONNECTOR_SIZE * self.StartPoint[1][1]))
  1983             self.EndPoint[0] = wx.Point(self.Points[-1].x + CONNECTOR_SIZE * self.EndPoint[1][0],
  1984             self.EndPoint[0] = wx.Point(self.Points[-1].x + round(CONNECTOR_SIZE * self.EndPoint[1][0]),
  1984                                         self.Points[-1].y + CONNECTOR_SIZE * self.EndPoint[1][1])
  1985                                         self.Points[-1].y + round(CONNECTOR_SIZE * self.EndPoint[1][1]))
  1985             self.Points[0] = self.StartPoint[0]
  1986             self.Points[0] = self.StartPoint[0]
  1986             self.Points[-1] = self.EndPoint[0]
  1987             self.Points[-1] = self.EndPoint[0]
  1987             # Calculate the segments directions
  1988             # Calculate the segments directions
  1988             self.Segments = []
  1989             self.Segments = []
  1989             i = 0
  1990             i = 0
  1990             while True:
  1991             while True:
  1991                 lp = len(self.Points)
  1992                 lp = len(self.Points)
  1992                 if i > lp - 2:
  1993                 if i > lp - 2:
  1993                     break
  1994                     break
  1994 
  1995 
  1995                 segment = vector(self.Points[i], self.Points[i + 1])
  1996                 segment = tuple(map(round,vector(self.Points[i], self.Points[i + 1])))
  1996 
  1997 
  1997                 # merge segment if requested
  1998                 # merge segment if requested
  1998                 if merge_segments and 0 < i and \
  1999                 if merge_segments and 0 < i and \
  1999                    self.Segments[-1] == segment:
  2000                    self.Segments[-1] == segment:
  2000                     self.Points.pop(i)
  2001                     self.Points.pop(i)
  2024         return None
  2025         return None
  2025 
  2026 
  2026     # Returns a list of the position of all wire points
  2027     # Returns a list of the position of all wire points
  2027     def GetPoints(self, invert=False):
  2028     def GetPoints(self, invert=False):
  2028         points = self.VerifyPoints()
  2029         points = self.VerifyPoints()
  2029         points[0] = wx.Point(points[0].x - CONNECTOR_SIZE * self.StartPoint[1][0],
  2030         points[0] = wx.Point(points[0].x - round(CONNECTOR_SIZE * self.StartPoint[1][0]),
  2030                              points[0].y - CONNECTOR_SIZE * self.StartPoint[1][1])
  2031                              points[0].y - round(CONNECTOR_SIZE * self.StartPoint[1][1]))
  2031         points[-1] = wx.Point(points[-1].x - CONNECTOR_SIZE * self.EndPoint[1][0],
  2032         points[-1] = wx.Point(points[-1].x - round(CONNECTOR_SIZE * self.EndPoint[1][0]),
  2032                               points[-1].y - CONNECTOR_SIZE * self.EndPoint[1][1])
  2033                               points[-1].y - round(CONNECTOR_SIZE * self.EndPoint[1][1]))
  2033         # An inversion of the list is asked
  2034         # An inversion of the list is asked
  2034         if invert:
  2035         if invert:
  2035             points.reverse()
  2036             points.reverse()
  2036         return points
  2037         return points
  2037 
  2038 
  2066 
  2067 
  2067     # Update the wire points position by keeping at most possible the current positions
  2068     # Update the wire points position by keeping at most possible the current positions
  2068     def GeneratePoints(self, realpoints=True):
  2069     def GeneratePoints(self, realpoints=True):
  2069         i = 0
  2070         i = 0
  2070         # Calculate the start enad end points with the minimum segment size in the right direction
  2071         # Calculate the start enad end points with the minimum segment size in the right direction
  2071         end = wx.Point(self.EndPoint[0].x + self.EndPoint[1][0] * MIN_SEGMENT_SIZE,
  2072         end = wx.Point(self.EndPoint[0].x + round(self.EndPoint[1][0] * MIN_SEGMENT_SIZE),
  2072                        self.EndPoint[0].y + self.EndPoint[1][1] * MIN_SEGMENT_SIZE)
  2073                        self.EndPoint[0].y + round(self.EndPoint[1][1] * MIN_SEGMENT_SIZE))
  2073         start = wx.Point(self.StartPoint[0].x + self.StartPoint[1][0] * MIN_SEGMENT_SIZE,
  2074         start = wx.Point(self.StartPoint[0].x + round(self.StartPoint[1][0] * MIN_SEGMENT_SIZE),
  2074                          self.StartPoint[0].y + self.StartPoint[1][1] * MIN_SEGMENT_SIZE)
  2075                          self.StartPoint[0].y + round(self.StartPoint[1][1] * MIN_SEGMENT_SIZE))
  2075         # Evaluate the point till it's the last
  2076         # Evaluate the point till it's the last
  2076         while i < len(self.Points) - 1:
  2077         while i < len(self.Points) - 1:
  2077             # The next point is the last
  2078             # The next point is the last
  2078             if i + 1 == len(self.Points) - 1:
  2079             if i + 1 == len(self.Points) - 1:
  2079                 # Calculate the direction from current point to end point
  2080                 # Calculate the direction from current point to end point
  2080                 v_end = vector(self.Points[i], end)
  2081                 v_end = tuple(map(round,vector(self.Points[i], end)))
  2081                 # The current point is the first
  2082                 # The current point is the first
  2082                 if i == 0:
  2083                 if i == 0:
  2083                     # If the end point is not in the start direction, a point is added
  2084                     # If the end point is not in the start direction, a point is added
  2084                     if v_end != self.Segments[0] or v_end == self.EndPoint[1]:
  2085                     if v_end != self.Segments[0] or v_end == self.EndPoint[1]:
  2085                         self.Points.insert(1, wx.Point(start.x, start.y))
  2086                         self.Points.insert(1, wx.Point(start.x, start.y))
  2197                         self.Points.insert(1, wx.Point(start.x, start.y))
  2198                         self.Points.insert(1, wx.Point(start.x, start.y))
  2198                         self.Segments.insert(
  2199                         self.Segments.insert(
  2199                             1,
  2200                             1,
  2200                             DirectionChoice((self.Segments[0][1],
  2201                             DirectionChoice((self.Segments[0][1],
  2201                                              self.Segments[0][0]),
  2202                                              self.Segments[0][0]),
  2202                                             vector(start, self.Points[1]),
  2203                                             tuple(map(round,vector(start, self.Points[1]))),
  2203                                             self.Segments[1]))
  2204                                             self.Segments[1]))
  2204                     else:
  2205                     else:
  2205                         self.Points[1].x, self.Points[1].y = start.x, start.y
  2206                         self.Points[1].x, self.Points[1].y = start.x, start.y
  2206                 else:
  2207                 else:
  2207                     # Next point is aligned with current point
  2208                     # Next point is aligned with current point
  2284             # Calculate the real points from the new size, it's important for
  2285             # Calculate the real points from the new size, it's important for
  2285             # keeping a proportionality in the points position with the size
  2286             # keeping a proportionality in the points position with the size
  2286             # during a resize dragging
  2287             # during a resize dragging
  2287             for i, point in enumerate(self.RealPoints):
  2288             for i, point in enumerate(self.RealPoints):
  2288                 if not (i == 0 and self.StartConnected) and not (i == len(self.Points) - 1 and self.EndConnected):
  2289                 if not (i == 0 and self.StartConnected) and not (i == len(self.Points) - 1 and self.EndConnected):
  2289                     point[0] = point[0] * width / max(lastwidth, 1)
  2290                     point[0] = int(point[0] * width / max(lastwidth, 1))
  2290                     point[1] = point[1] * height / max(lastheight, 1)
  2291                     point[1] = int(point[1] * height / max(lastheight, 1))
  2291             # Calculate the correct position of the points from real points
  2292             # Calculate the correct position of the points from real points
  2292             for i, point in enumerate(self.RealPoints):
  2293             for i, point in enumerate(self.RealPoints):
  2293                 if not (i == 0 and self.StartConnected) and not (i == len(self.Points) - 1 and self.EndConnected):
  2294                 if not (i == 0 and self.StartConnected) and not (i == len(self.Points) - 1 and self.EndConnected):
  2294                     if i == 0:
  2295                     if i == 0:
  2295                         dir = self.StartPoint[1]
  2296                         dir = self.StartPoint[1]
  2669         dc.SetLogicalFunction(wx.AND)
  2670         dc.SetLogicalFunction(wx.AND)
  2670         # Draw the start and end points if they are not connected or the mouse is over them
  2671         # Draw the start and end points if they are not connected or the mouse is over them
  2671         if len(self.Points) > 0 and (not self.StartConnected or self.OverStart):
  2672         if len(self.Points) > 0 and (not self.StartConnected or self.OverStart):
  2672             dc.DrawCircle(round(self.Points[0].x * scalex),
  2673             dc.DrawCircle(round(self.Points[0].x * scalex),
  2673                           round(self.Points[0].y * scaley),
  2674                           round(self.Points[0].y * scaley),
  2674                           (POINT_RADIUS + 1) * scalex + 2)
  2675                           round((POINT_RADIUS + 1) * scalex + 2))
  2675         if len(self.Points) > 1 and (not self.EndConnected or self.OverEnd):
  2676         if len(self.Points) > 1 and (not self.EndConnected or self.OverEnd):
  2676             dc.DrawCircle(self.Points[-1].x * scalex, self.Points[-1].y * scaley, (POINT_RADIUS + 1) * scalex + 2)
  2677             dc.DrawCircle(round(self.Points[-1].x * scalex), round(self.Points[-1].y * scaley), round((POINT_RADIUS + 1) * scalex + 2))
  2677         # Draw the wire lines and the last point (it seems that DrawLines stop before the last point)
  2678         # Draw the wire lines and the last point (it seems that DrawLines stop before the last point)
  2678         if len(self.Points) > 1:
  2679         if len(self.Points) > 1:
  2679             points = [wx.Point(round((self.Points[0].x - self.Segments[0][0]) * scalex),
  2680             points = [wx.Point(round((self.Points[0].x - self.Segments[0][0]) * scalex),
  2680                                round((self.Points[0].y - self.Segments[0][1]) * scaley))]
  2681                                round((self.Points[0].y - self.Segments[0][1]) * scaley))]
  2681             points.extend([wx.Point(round(point.x * scalex), round(point.y * scaley)) for point in self.Points[1:-1]])
  2682             points.extend([wx.Point(round(point.x * scalex), round(point.y * scaley)) for point in self.Points[1:-1]])
  2920         dc.SetUserScale(1, 1)
  2921         dc.SetUserScale(1, 1)
  2921         dc.SetPen(MiterPen(HIGHLIGHTCOLOR))
  2922         dc.SetPen(MiterPen(HIGHLIGHTCOLOR))
  2922         dc.SetBrush(wx.Brush(HIGHLIGHTCOLOR))
  2923         dc.SetBrush(wx.Brush(HIGHLIGHTCOLOR))
  2923         dc.SetLogicalFunction(wx.AND)
  2924         dc.SetLogicalFunction(wx.AND)
  2924 
  2925 
  2925         left = (self.Pos.x - 1) * scalex - 2
  2926         left = round((self.Pos.x - 1) * scalex - 2)
  2926         right = (self.Pos.x + self.Size[0] + 1) * scalex + 2
  2927         right = round((self.Pos.x + self.Size[0] + 1) * scalex + 2)
  2927         top = (self.Pos.y - 1) * scaley - 2
  2928         top = round((self.Pos.y - 1) * scaley - 2)
  2928         bottom = (self.Pos.y + self.Size[1] + 1) * scaley + 2
  2929         bottom = round((self.Pos.y + self.Size[1] + 1) * scaley + 2)
  2929         angle_top = (self.Pos.x + self.Size[0] - 9) * scalex + 2
  2930         angle_top = round((self.Pos.x + self.Size[0] - 9) * scalex + 2)
  2930         angle_right = (self.Pos.y + 9) * scaley - 2
  2931         angle_right = round((self.Pos.y + 9) * scaley - 2)
  2931 
  2932 
  2932         polygon = [wx.Point(left, top), wx.Point(angle_top, top),
  2933         polygon = [wx.Point(left, top), wx.Point(angle_top, top),
  2933                    wx.Point(right, angle_right), wx.Point(right, bottom),
  2934                    wx.Point(right, angle_right), wx.Point(right, bottom),
  2934                    wx.Point(left, bottom)]
  2935                    wx.Point(left, bottom)]
  2935         dc.DrawPolygon(polygon)
  2936         dc.DrawPolygon(polygon)