graphics/GraphicCommons.py
changeset 331 9106d66bd204
parent 329 1cf72cb51dc9
child 333 0a74fcfd4d03
equal deleted inserted replaced
330:d803ba077da0 331:9106d66bd204
   113     (3, 2) : 4,
   113     (3, 2) : 4,
   114     (2, 1) : 5,
   114     (2, 1) : 5,
   115     (2, 3) : 5
   115     (2, 3) : 5
   116 }
   116 }
   117 
   117 
       
   118 def round_scaling(x, n, constraint=0):
       
   119     fraction = float(x) / float(n)
       
   120     if constraint == - 1:
       
   121         xround = int(fraction)
       
   122     else:
       
   123         xround = round(fraction)
       
   124         if constraint == 1 and int(fraction) == xround:
       
   125             xround += 1
       
   126     return xround * n
       
   127 
   118 """
   128 """
   119 Basic vector operations for calculate wire points
   129 Basic vector operations for calculate wire points
   120 """
   130 """
   121 
   131 
   122 # Create a vector from two points and define if vector must be normal
   132 # Create a vector from two points and define if vector must be normal
   368         self.RefreshBoundingBox()
   378         self.RefreshBoundingBox()
   369 
   379 
   370     # Returns the element size
   380     # Returns the element size
   371     def GetSize(self):
   381     def GetSize(self):
   372         return self.Size.GetWidth(), self.Size.GetHeight()
   382         return self.Size.GetWidth(), self.Size.GetHeight()
       
   383     
       
   384     # Returns the minimum element size
       
   385     def GetMinSize(self):
       
   386         return 0, 0
   373     
   387     
   374     # Refresh the element Bounding Box
   388     # Refresh the element Bounding Box
   375     def RefreshBoundingBox(self):
   389     def RefreshBoundingBox(self):
   376         self.BoundingBox = wx.Rect(self.Pos.x, self.Pos.y, self.Size[0], self.Size[1])
   390         self.BoundingBox = wx.Rect(self.Pos.x, self.Pos.y, self.Size[0], self.Size[1])
   377     
   391     
   564     # Resizes the element from position and size given
   578     # Resizes the element from position and size given
   565     def Resize(self, x, y, width, height):
   579     def Resize(self, x, y, width, height):
   566         self.Move(x, y)
   580         self.Move(x, y)
   567         self.SetSize(width, height)
   581         self.SetSize(width, height)
   568     
   582     
       
   583     # Moves and Resizes the element for fitting scaling
       
   584     def AdjustToScaling(self, scaling):
       
   585         if scaling is not None:
       
   586             movex = round_scaling(self.Pos.x, scaling[0]) - self.Pos.x
       
   587             movey = round_scaling(self.Pos.y, scaling[1]) - self.Pos.y
       
   588             min_width, min_height = self.GetMinSize()
       
   589             width = max(round_scaling(min_width, scaling[0], 1),
       
   590                         round_scaling(self.Size.width, scaling[0]))
       
   591             height = max(round_scaling(min_height, scaling[1], 1),
       
   592                          round_scaling(self.Size.height, scaling[1]))
       
   593             self.Resize(movex, movey, width, height)
       
   594             return movex, movey
       
   595         return 0, 0
       
   596     
   569     # Refreshes the element state according to move defined and handle selected
   597     # Refreshes the element state according to move defined and handle selected
   570     def ProcessDragging(self, movex, movey, event, scaling, width_fac = 1, height_fac = 1):
   598     def ProcessDragging(self, movex, movey, event, scaling, width_fac = 1, height_fac = 1):
   571         handle_type, handle = self.Handle
   599         handle_type, handle = self.Handle
   572         # If it is a resize handle, calculate the values from resizing
   600         # If it is a resize handle, calculate the values from resizing
   573         if handle_type == HANDLE_RESIZE:
   601         if handle_type == HANDLE_RESIZE:
   577             width, height = start_width, start_height = self.GetSize()
   605             width, height = start_width, start_height = self.GetSize()
   578             proportion = float(start_width) / float(start_height)
   606             proportion = float(start_width) / float(start_height)
   579             if handle[0] == 1:
   607             if handle[0] == 1:
   580                 movex = max(-self.BoundingBox.x, movex)
   608                 movex = max(-self.BoundingBox.x, movex)
   581                 if scaling is not None:
   609                 if scaling is not None:
   582                     movex = -(round(float(width - movex) / float(scaling[0])) * scaling[0] - width)
   610                     movex = -(round_scaling(width - movex, scaling[0]) - width)
   583                 x = movex
   611                 x = movex
   584                 if event.ShiftDown():
   612                 if event.ShiftDown():
   585                     width -= 2 * movex
   613                     width -= 2 * movex
   586                 else:
   614                 else:
   587                     width -= movex
   615                     width -= movex
   588             elif handle[0] == 3:
   616             elif handle[0] == 3:
   589                 if scaling is not None:
   617                 if scaling is not None:
   590                     movex = round(float(width + movex) / float(scaling[0])) * scaling[0] - width
   618                     movex = round_scaling(width + movex, scaling[0]) - width
   591                 if event.ShiftDown():
   619                 if event.ShiftDown():
   592                     x = -movex
   620                     x = -movex
   593                     width += 2 * movex
   621                     width += 2 * movex
   594                 else:
   622                 else:
   595                     width += movex
   623                     width += movex
   596             if handle[1] == 1:
   624             if handle[1] == 1:
   597                 movey = max(-self.BoundingBox.y, movey)
   625                 movey = max(-self.BoundingBox.y, movey)
   598                 if scaling is not None:
   626                 if scaling is not None:
   599                     movey = -(round(float(height - movey) / float(scaling[1])) * scaling[1] - height)
   627                     movey = -(round_scaling(height - movey, scaling[1]) - height)
   600                 y = movey
   628                 y = movey
   601                 if event.ShiftDown():
   629                 if event.ShiftDown():
   602                     height -= 2 * movey
   630                     height -= 2 * movey
   603                 else:
   631                 else:
   604                     height -= movey
   632                     height -= movey
   605             elif handle[1] == 3:
   633             elif handle[1] == 3:
   606                 if scaling is not None:
   634                 if scaling is not None:
   607                     movey = round(float(height + movey) / float(scaling[1])) * scaling[1] - height
   635                     movey = round_scaling(height + movey, scaling[1]) - height
   608                 if event.ShiftDown():
   636                 if event.ShiftDown():
   609                     y = -movey
   637                     y = -movey
   610                     height += 2 * movey
   638                     height += 2 * movey
   611                 else:
   639                 else:
   612                     height += movey
   640                     height += movey
   628         # If it is a move handle, Move this element
   656         # If it is a move handle, Move this element
   629         elif handle_type == HANDLE_MOVE:
   657         elif handle_type == HANDLE_MOVE:
   630             movex = max(-self.BoundingBox.x, movex)
   658             movex = max(-self.BoundingBox.x, movex)
   631             movey = max(-self.BoundingBox.y, movey)
   659             movey = max(-self.BoundingBox.y, movey)
   632             if scaling is not None:
   660             if scaling is not None:
   633                 movex = round(float(self.Pos.x + movex) / float(scaling[0])) * scaling[0] - self.Pos.x
   661                 movex = round_scaling(self.Pos.x + movex, scaling[0]) - self.Pos.x
   634                 movey = round(float(self.Pos.y + movey) / float(scaling[1])) * scaling[1] - self.Pos.y
   662                 movey = round_scaling(self.Pos.y + movey, scaling[1]) - self.Pos.y
   635             if event.ControlDown():
   663             if event.ControlDown():
   636                 self.CurrentDrag.x = self.CurrentDrag.x + movex
   664                 self.CurrentDrag.x = self.CurrentDrag.x + movex
   637                 self.CurrentDrag.y = self.CurrentDrag.y + movey
   665                 self.CurrentDrag.y = self.CurrentDrag.y + movey
   638                 if abs(self.CurrentDrag.x) > abs(self.CurrentDrag.y):
   666                 if abs(self.CurrentDrag.x) > abs(self.CurrentDrag.y):
   639                     movex = self.StartPos.x + self.CurrentDrag.x - self.Pos.x
   667                     movex = self.StartPos.x + self.CurrentDrag.x - self.Pos.x
   898     
   926     
   899     # Returns the size of this group
   927     # Returns the size of this group
   900     def GetSize(self):
   928     def GetSize(self):
   901         return self.BoundingBox.width, self.BoundingBox.height
   929         return self.BoundingBox.width, self.BoundingBox.height
   902 
   930 
       
   931     # Moves and Resizes the group elements for fitting scaling
       
   932     def AdjustToScaling(self, scaling):
       
   933         movex_max = movey_max = 0
       
   934         for element in self.Elements:
       
   935             movex, movey = element.AdjustToScaling(scaling)
       
   936             movex_max = max(movex_max, abs(movex))
       
   937             movey_max = max(movey_max, abs(movey))
       
   938         return movex_max, movey_max
       
   939     
   903     # Change the variable that indicates if this element is highlighted
   940     # Change the variable that indicates if this element is highlighted
   904     def SetHighlighted(self, highlighted):
   941     def SetHighlighted(self, highlighted):
   905         for element in self.Elements:
   942         for element in self.Elements:
   906             element.SetHighlighted(highlighted)
   943             element.SetHighlighted(highlighted)
   907 
   944 
  1394         pass
  1431         pass
  1395     
  1432     
  1396     # Forbids to change the wire size
  1433     # Forbids to change the wire size
  1397     def SetSize(width, height):
  1434     def SetSize(width, height):
  1398         pass
  1435         pass
       
  1436     
       
  1437     # Moves and Resizes the element for fitting scaling
       
  1438     def AdjustToScaling(self, scaling):
       
  1439         if scaling is not None:
       
  1440             movex_max = movey_max = 0
       
  1441             for idx, point in enumerate(self.Points):
       
  1442                 if 0 < idx < len(self.Points) - 1:
       
  1443                     movex = round_scaling(point.x, scaling[0]) - point.x
       
  1444                     movey = round_scaling(point.y, scaling[1]) - point.y
       
  1445                     if idx == 1:
       
  1446                         if self.Segments[0][0] == 0:
       
  1447                             movex = 0
       
  1448                         elif (point.x + movex - self.Points[0].x) * self.Segments[0][0] < MIN_SEGMENT_SIZE:
       
  1449                             movex = round_scaling(self.Points[0].x + MIN_SEGMENT_SIZE * self.Segments[0][0], scaling[0], self.Segments[0][0]) - point.x
       
  1450                         if self.Segments[0][1] == 0:
       
  1451                             movey = 0
       
  1452                         elif (point.y + movey - self.Points[0].y) * self.Segments[0][1] < MIN_SEGMENT_SIZE:
       
  1453                             movey = round_scaling(self.Points[0].y + MIN_SEGMENT_SIZE * self.Segments[0][1], scaling[0], self.Segments[0][1]) - point.y
       
  1454                     elif idx == len(self.Points) - 2:
       
  1455                         if self.Segments[-1][0] == 0:
       
  1456                             movex = 0
       
  1457                         elif (self.Points[-1].x - (point.x + movex)) * self.Segments[-1][0] < MIN_SEGMENT_SIZE:
       
  1458                             movex = round_scaling(self.Points[-1].x + MIN_SEGMENT_SIZE * self.Segments[0][0], scaling[0], self.Segments[0][0]) - point.x
       
  1459                         if self.Segments[-1][1] == 0:
       
  1460                             movey = 0
       
  1461                         elif (self.Points[-1].y - (point.y + movey)) * self.Segments[-1][1] < MIN_SEGMENT_SIZE:
       
  1462                             movey = round_scaling(self.Points[-1].y - MIN_SEGMENT_SIZE * self.Segments[-1][1], scaling[1], -self.Segments[-1][1]) - point.y
       
  1463                     movex_max = max(movex_max, movex)
       
  1464                     movey_max = max(movey_max, movey)
       
  1465                     point.x += movex
       
  1466                     point.y += movey
       
  1467             return movex_max, movey_max
       
  1468         return 0, 0
  1399     
  1469     
  1400     # Returns connector to which start point is connected
  1470     # Returns connector to which start point is connected
  1401     def GetStartConnected(self):
  1471     def GetStartConnected(self):
  1402         return self.StartConnected
  1472         return self.StartConnected
  1403     
  1473     
  2027     def MoveSegment(self, idx, movex, movey, scaling):
  2097     def MoveSegment(self, idx, movex, movey, scaling):
  2028         if 0 < idx < len(self.Segments) - 1:
  2098         if 0 < idx < len(self.Segments) - 1:
  2029             if self.Segments[idx] in (NORTH, SOUTH):
  2099             if self.Segments[idx] in (NORTH, SOUTH):
  2030                 start_x = self.Points[idx].x
  2100                 start_x = self.Points[idx].x
  2031                 if scaling is not None:
  2101                 if scaling is not None:
  2032                     movex = round(float(self.Points[idx].x + movex) / float(scaling[0])) * scaling[0] - self.Points[idx].x
  2102                     movex = round_scaling(self.Points[idx].x + movex, scaling[0]) - self.Points[idx].x
       
  2103                     if idx == 1 and (self.Points[1].x + movex - self.Points[0].x) * self.Segments[0][0] < MIN_SEGMENT_SIZE:
       
  2104                         movex = round_scaling(self.Points[0].x + MIN_SEGMENT_SIZE * self.Segments[0][0], scaling[0], self.Segments[0][0]) - self.Points[idx].x
       
  2105                     elif idx == len(self.Segments) - 2 and (self.Points[-1].x - (self.Points[-2].x + movex)) * self.Segments[-1][0] < MIN_SEGMENT_SIZE:
       
  2106                         movex = round_scaling(self.Points[-1].x - MIN_SEGMENT_SIZE * self.Segments[-1][0], scaling[0], -self.Segments[-1][0]) - self.Points[idx].x
  2033                 self.Points[idx].x += movex
  2107                 self.Points[idx].x += movex
  2034                 self.Points[idx + 1].x += movex
  2108                 self.Points[idx + 1].x += movex
  2035                 self.GeneratePoints()
  2109                 self.GeneratePoints()
  2036                 if start_x != self.Points[idx].x:
  2110                 if start_x != self.Points[idx].x:
  2037                     return self.Points[idx].x - start_x, 0
  2111                     return self.Points[idx].x - start_x, 0
  2038             elif self.Segments[idx] in (EAST, WEST):
  2112             elif self.Segments[idx] in (EAST, WEST):
  2039                 start_y = self.Points[idx].y
  2113                 start_y = self.Points[idx].y
  2040                 if scaling is not None:
  2114                 if scaling is not None:
  2041                     movey = round(float(self.Points[idx].y + movey) / float(scaling[1])) * scaling[1] - self.Points[idx].y
  2115                     movey = round_scaling(self.Points[idx].y + movey, scaling[1]) - self.Points[idx].y
       
  2116                     if idx == 1 and (self.Points[1].y + movey - self.Points[0].y) * self.Segments[0][1] < MIN_SEGMENT_SIZE:
       
  2117                         movex = round_scaling(self.Points[0].y + MIN_SEGMENT_SIZE * self.Segments[0][1], scaling[0], self.Segments[0][1]) - self.Points[idx].y
       
  2118                     elif idx == len(self.Segments) - 2 and (self.Points[-1].y - (self.Points[-2].y + movey)) * self.Segments[-1][1] < MIN_SEGMENT_SIZE:
       
  2119                         movey = round_scaling(self.Points[idx].y - MIN_SEGMENT_SIZE * self.Segments[-1][1], scaling[1], -self.Segments[-1][1]) - self.Points[idx].y
  2042                 self.Points[idx].y += movey
  2120                 self.Points[idx].y += movey
  2043                 self.Points[idx + 1].y += movey
  2121                 self.Points[idx + 1].y += movey
  2044                 self.GeneratePoints()
  2122                 self.GeneratePoints()
  2045                 if start_y != self.Points[idx].y:
  2123                 if start_y != self.Points[idx].y:
  2046                     return 0, self.Points[idx].y - start_y
  2124                     return 0, self.Points[idx].y - start_y
  2218         # A point has been handled
  2296         # A point has been handled
  2219         if handle_type == HANDLE_POINT:
  2297         if handle_type == HANDLE_POINT:
  2220             movex = max(-self.Points[handle].x + POINT_RADIUS, movex)
  2298             movex = max(-self.Points[handle].x + POINT_RADIUS, movex)
  2221             movey = max(-self.Points[handle].y + POINT_RADIUS, movey)
  2299             movey = max(-self.Points[handle].y + POINT_RADIUS, movey)
  2222             if scaling is not None:
  2300             if scaling is not None:
  2223                 movex = round(float(self.Points[handle].x + movex) / float(scaling[0])) * scaling[0] - self.Points[handle].x
  2301                 movex = round_scaling(self.Points[handle].x + movex, scaling[0]) - self.Points[handle].x
  2224                 movey = round(float(self.Points[handle].y + movey) / float(scaling[1])) * scaling[1] - self.Points[handle].y
  2302                 movey = round_scaling(self.Points[handle].y + movey, scaling[1]) - self.Points[handle].y
  2225             # Try to connect point to a connector
  2303             # Try to connect point to a connector
  2226             new_pos = wx.Point(self.Points[handle].x + movex, self.Points[handle].y + movey)
  2304             new_pos = wx.Point(self.Points[handle].x + movex, self.Points[handle].y + movey)
  2227             connector = self.Parent.FindBlockConnector(new_pos, self.GetConnectionDirection())
  2305             connector = self.Parent.FindBlockConnector(new_pos, self.GetConnectionDirection())
  2228             if connector:
  2306             if connector:
  2229                 if handle == 0 and self.EndConnected != connector and connector.IsCompatible(self.GetEndConnectedType()):
  2307                 if handle == 0 and self.EndConnected != connector and connector.IsCompatible(self.GetEndConnectedType()):