door_function.py
Go to the documentation of this file.
00001 #!/bin/env python
00002 
00003 from functools import partial
00004 import math
00005 import os.path
00006 from python_qt_binding.QtCore import QPoint, QPointF, QSize, Qt
00007 from python_qt_binding.QtGui import QImage, QLabel, QLineEdit, QPainter, QPolygon, QPushButton
00008 import rospy
00009 import yaml
00010 
00011 from bwi_tools import saveMapToFile
00012 
00013 from .utils import clearLayoutAndFixHeight, \
00014                    getDoorsMapLocationFromDataDirectory, \
00015                    scalePoint, \
00016                    transformPointToPixelCoordinates, \
00017                    transformPointToRealWorldCoordinates
00018 
00019 class Door(object):
00020 
00021     def __init__(self,
00022                  door_corner_pt_1,
00023                  door_corner_pt_2,
00024                  approach_pt_1,
00025                  approach_pt_2):
00026 
00027         self.door_corner_pt_1 = door_corner_pt_1
00028         self.door_corner_pt_2 = door_corner_pt_2
00029         self.approach_pt_1 = approach_pt_1
00030         self.approach_pt_2 = approach_pt_2
00031 
00032     def clone(self):
00033         return Door(QPoint(self.door_corner_pt_1),
00034                     QPoint(self.door_corner_pt_2),
00035                     QPoint(self.approach_pt_1),
00036                     QPoint(self.approach_pt_2))
00037 
00038 class DoorFunction(object):
00039 
00040     EDIT_DOOR_PROPERITIES = 'Edit Door Properties'
00041     ADD_NEW_DOOR = 'Add Door'
00042     EDIT_EXISTING_DOOR = 'Edit Door'
00043 
00044     def __init__(self,
00045                  door_file,
00046                  map,
00047                  location_function,
00048                  widget,
00049                  subfunction_layout,
00050                  configuration_layout,
00051                  image):
00052 
00053         self.edit_door_location_button = None
00054         self.selected_door_color = Qt.blue
00055         self.unselected_door_color = Qt.darkGreen
00056 
00057         # Dictionary that maps door names to the actual door object (string->Door)
00058         self.doors = {}
00059         self.draw_door = {}
00060         self.unique_door_counter = 1
00061 
00062         self.editing_door_location = False
00063         self.edit_existing_door = None
00064 
00065         self.editing_properties = False
00066         self.edit_properties_door = None
00067 
00068         # Use this to initialize variables.
00069         self.clearCurrentSelection()
00070 
00071         self.is_modified = False
00072 
00073         self.widget = widget
00074         self.subfunction_layout = subfunction_layout
00075         self.image = image
00076         self.image_size = image.overlay_image.size()
00077         self.configuration_layout = configuration_layout
00078 
00079         self.door_file = door_file
00080         self.map = map
00081         self.map_size = QSize(map.map.info.width, map.map.info.height)
00082         self.location_function = location_function
00083         self.readDoorsFromFile()
00084 
00085         self.edit_door_location_button = {}
00086 
00087     def readDoorsFromFile(self):
00088 
00089         if os.path.isfile(self.door_file):
00090             stream = open(self.door_file, 'r')
00091             try:
00092                 contents = yaml.load(stream)
00093                 for door in contents:
00094                     door_key = door["name"]
00095                     approach_pts = door["approach"]
00096                     if len(approach_pts) != 2:
00097                         rospy.logerr("Door " + door_key + " read from file " + self.door_file + " has " + str(len(approach_pts)) + " approach points instead of 2. Ignoring this door.")
00098                         continue
00099                     approach_pt_1 = QPointF(approach_pts[0]["point"][0], approach_pts[0]["point"][1])
00100                     approach_pt_1 = transformPointToPixelCoordinates(approach_pt_1, self.map, self.image_size)
00101                     approach_pt_2 = QPointF(approach_pts[1]["point"][0], approach_pts[1]["point"][1])
00102                     approach_pt_2 = transformPointToPixelCoordinates(approach_pt_2, self.map, self.image_size)
00103 
00104                     # Door corner points were not available in the original format.
00105                     if "door_corner_pt_1" in door:
00106                         door_corner_pt_1 = transformPointToPixelCoordinates(QPointF(*door["door_corner_pt_1"]), 
00107                                                                             self.map,
00108                                                                             self.image_size)
00109                         door_corner_pt_2 = transformPointToPixelCoordinates(QPointF(*door["door_corner_pt_2"]), 
00110                                                                             self.map,
00111                                                                             self.image_size)
00112                     else:
00113                         width = 1.0
00114                         if "width" in door:
00115                             width = door["width"]
00116                         scaled_origin = transformPointToPixelCoordinates(QPointF(0, 0), self.map, self.image_size)
00117                         scaled_width_pt = transformPointToPixelCoordinates(QPointF(0, width), self.map, self.image_size)
00118                         scaled_width_diff = scaled_width_pt - scaled_origin
00119                         scaled_width = math.sqrt(scaled_width_diff.x() * scaled_width_diff.x() + scaled_width_diff.y() * scaled_width_diff.y())
00120                         midpoint = (approach_pt_1 + approach_pt_2) / 2
00121                         diff = approach_pt_1 - approach_pt_2
00122                         segment_angle = math.atan2(diff.y(), diff.x())
00123                         perpendicular_angle = segment_angle + math.pi / 2.0
00124                         perpendicular_diff_pt = QPoint(int((scaled_width / 2) * math.cos(perpendicular_angle)), 
00125                                                        int((scaled_width / 2) * math.sin(perpendicular_angle))) 
00126 
00127                         door_corner_pt_1 = midpoint + perpendicular_diff_pt
00128                         door_corner_pt_2 = midpoint - perpendicular_diff_pt
00129 
00130 
00131                     self.doors[door_key] = Door(door_corner_pt_1,
00132                                                 door_corner_pt_2,
00133                                                 approach_pt_1,
00134                                                 approach_pt_2)
00135                     self.draw_door[door_key] = True
00136             except yaml.YAMLError, KeyError:
00137                 rospy.logerr("File found at " + self.door_file + ", but cannot be parsed by YAML parser. I'm starting doors from scratch.")
00138 
00139             stream.close()
00140         else:
00141             rospy.logwarn("Door file not found at " + self.door_file + ". I'm starting doors from scratch and will attempt to write to this door before exiting.")
00142 
00143     def saveConfiguration(self):
00144         self.writeDoorsToFile()
00145 
00146     def writeDoorsToFile(self):
00147 
00148         out_list = []
00149         for door_name in self.doors:
00150             door = self.doors[door_name]
00151             door_corner_pt_1 = transformPointToRealWorldCoordinates(door.door_corner_pt_1, self.map, self.image_size)
00152             door_corner_pt_2 = transformPointToRealWorldCoordinates(door.door_corner_pt_2, self.map, self.image_size)
00153             door_dict = {}
00154             door_dict["name"] = door_name
00155             door_dict["door_corner_pt_1"] = [door_corner_pt_1.x(), door_corner_pt_1.y()]
00156             door_dict["door_corner_pt_2"] = [door_corner_pt_2.x(), door_corner_pt_2.y()]
00157             door_dict["approach"] = []
00158             mid_point = (door_corner_pt_1 + door_corner_pt_2) / 2
00159             for point in [door.approach_pt_1, door.approach_pt_2]:
00160                 approach_pt_dict = {}
00161                 approach_pt_dict["from"] = self.location_function.getLocationNameFromPoint(point)
00162                 transformed_point = transformPointToRealWorldCoordinates(point, self.map, self.image_size)
00163                 diff_pt = transformed_point - mid_point
00164                 approach_angle = math.atan2(diff_pt.y(), diff_pt.x())
00165                 approach_pt_dict["point"] = [transformed_point.x(), transformed_point.y(), approach_angle]
00166                 door_dict["approach"].append(approach_pt_dict)
00167             out_list.append(door_dict)
00168 
00169         stream = open(self.door_file, 'w')
00170         yaml.dump(out_list, stream)
00171         stream.close()
00172 
00173         # Also dump out a version of the map with all the doors closed.
00174         data_directory = os.path.dirname(os.path.realpath(self.door_file))
00175         map_file = getDoorsMapLocationFromDataDirectory(data_directory)
00176         map_image_file = "doors_map.pgm"
00177 
00178         scaled_map_image = self.image.map_image.scaled(self.map_size)
00179         map_with_doors_image = QImage(self.map_size, QImage.Format_RGB32)
00180         painter = QPainter(map_with_doors_image) 
00181         painter.drawImage(0,0,scaled_map_image)
00182         painter.setPen(Qt.black)
00183         for door_name in self.doors:
00184             door = self.doors[door_name]
00185             # Draw the doors onto the map.
00186             door_corner_pt_1 = scalePoint(door.door_corner_pt_1, self.image_size, self.map_size)
00187             door_corner_pt_2 = scalePoint(door.door_corner_pt_2, self.image_size, self.map_size)
00188             painter.drawLine(door_corner_pt_1, door_corner_pt_2)
00189         painter.end()
00190 
00191         saveMapToFile(self.map.map, map_file, map_image_file, False, 0.2, 0.8, map_with_doors_image)
00192 
00193         self.is_modified = False
00194 
00195     def deactivateFunction(self):
00196 
00197         if self.editing_door_location:
00198             self.endDoorLocationEdit("Cancel")
00199         elif self.editing_properties:
00200             self.endPropertyEdit()
00201 
00202         clearLayoutAndFixHeight(self.subfunction_layout)
00203         self.edit_door_location_button.clear()
00204         self.image.enableDefaultMouseHooks()
00205 
00206         # Just in case we were editing a door, that door was not being drawn. 
00207         for door in self.draw_door:
00208             self.draw_door[door] = True
00209 
00210     def activateFunction(self):
00211 
00212         # Add all the necessary buttons to the subfunction layout.
00213         clearLayoutAndFixHeight(self.subfunction_layout)
00214         for button_text in [DoorFunction.ADD_NEW_DOOR, 
00215                             DoorFunction.EDIT_EXISTING_DOOR]:
00216             button = QPushButton(button_text, self.widget)
00217             button.clicked[bool].connect(partial(self.startDoorLocationEdit, button_text))
00218             button.setCheckable(True)
00219             self.subfunction_layout.addWidget(button)
00220             self.edit_door_location_button[button_text] = button
00221         self.edit_door_location_button[DoorFunction.EDIT_EXISTING_DOOR].setEnabled(False)
00222         self.subfunction_layout.addStretch(1)
00223 
00224         # ActivateMouseHooks.
00225         self.image.mousePressEvent = self.mousePressEvent
00226         self.image.mouseMoveEvent = self.mouseMoveEvent
00227         self.image.mouseReleaseEvent = self.mouseReleaseEvent
00228 
00229         self.updateOverlay()
00230 
00231     def getDoorNameFromPoint(self, point):
00232         for door in self.doors:
00233             # Check if the user is clicking on the line between the doors or the two approach points.
00234             if self.getPointDistanceToAnotherPoint(point, self.doors[door].approach_pt_1) <= 3:
00235                 return door
00236             if self.getPointDistanceToAnotherPoint(point, self.doors[door].approach_pt_2) <= 3:
00237                 return door
00238             if self.getPointDistanceToLineSegment(point,
00239                                                   self.doors[door].door_corner_pt_1,
00240                                                   self.doors[door].door_corner_pt_2) <= 3:
00241                 return door
00242         return None
00243 
00244     def startDoorLocationEdit(self, edit_type):
00245 
00246         if self.editing_properties:
00247             self.endPropertyEdit()
00248 
00249         self.editing_door_location = True
00250 
00251         if edit_type == DoorFunction.ADD_NEW_DOOR:
00252             self.edit_existing_door = None
00253         # else edit_existing_door was set to the correct door by startPropertyEdit()
00254 
00255         # Make sure all active selections have been cleared.
00256         self.clearCurrentSelection()
00257 
00258         # If we're going to edit an existing area, stop drawing it and copy it to the active selection.
00259         if self.edit_existing_door is not None:
00260             self.draw_door[self.edit_existing_door] = False 
00261             self.current_selection = self.doors[self.edit_existing_door].clone()
00262             self.edit_existing_door = self.edit_existing_door
00263 
00264         # Setup the buttons in the configuration toolbar, and disable the original buttons to edit an area.
00265         clearLayoutAndFixHeight(self.configuration_layout)
00266         for button_text in ["Done", "Cancel"]:
00267             button = QPushButton(button_text, self.widget)
00268             button.clicked[bool].connect(partial(self.endDoorLocationEdit, button_text))
00269             self.configuration_layout.addWidget(button)
00270         self.current_selection_label = QLabel(self.widget)
00271         self.configuration_layout.addWidget(self.current_selection_label)
00272         self.configuration_layout.addStretch(1)
00273 
00274         self.edit_door_location_button[DoorFunction.ADD_NEW_DOOR].setEnabled(False)
00275         self.edit_door_location_button[DoorFunction.EDIT_EXISTING_DOOR].setEnabled(False)
00276 
00277         self.updateOverlay()
00278 
00279     def clearCurrentSelection(self):
00280 
00281         # Make sure all selections are clear.
00282         self.new_selection_start_point = None
00283         self.new_selection_end_point = None
00284 
00285         # Door
00286         self.current_selection = None
00287         self.current_selection_label = None # Displays which two locations the door is connecting.
00288         self.move_selection = None
00289 
00290     def endDoorLocationEdit(self, button_text):
00291 
00292         edit_properties_door = None
00293 
00294         if (button_text == "Done") and (self.current_selection is not None):
00295 
00296             if self.edit_existing_door == None:
00297                 # We're adding a new door. Generate a new door name and color.
00298                 self.edit_existing_door = self.getUniqueName()
00299             self.doors[self.edit_existing_door] = self.current_selection
00300             self.draw_door[self.edit_existing_door] = True
00301             edit_properties_door = self.edit_existing_door
00302 
00303             # Since a door was added or edited, set file modification to true.
00304             self.is_modified = True
00305         else:
00306             # Cancel was pressed, draw the original door if we were editing as before.
00307             if self.edit_existing_door is not None:
00308                 self.draw_door[self.edit_existing_door] = True
00309 
00310         self.editing_door_location = False
00311         self.edit_existing_door = None
00312         self.clearCurrentSelection()
00313 
00314         # Update the entire image overlay.
00315         self.updateOverlay()
00316 
00317         self.edit_door_location_button[DoorFunction.ADD_NEW_DOOR].setEnabled(True)
00318         self.edit_door_location_button[DoorFunction.ADD_NEW_DOOR].setChecked(False)
00319         self.edit_door_location_button[DoorFunction.EDIT_EXISTING_DOOR].setChecked(False)
00320         clearLayoutAndFixHeight(self.configuration_layout)
00321 
00322         if edit_properties_door is not None:
00323             self.edit_properties_door = edit_properties_door
00324             self.startPropertyEdit()
00325 
00326     def startPropertyEdit(self):
00327 
00328         self.editing_properties = True
00329         self.edit_existing_door = self.edit_properties_door
00330 
00331         self.edit_door_location_button[DoorFunction.ADD_NEW_DOOR].setEnabled(True)
00332         self.edit_door_location_button[DoorFunction.EDIT_EXISTING_DOOR].setEnabled(True)
00333 
00334         # Construct the configuration layout.
00335         clearLayoutAndFixHeight(self.configuration_layout)
00336 
00337         connects_text = self.getConnectingText(self.doors[self.edit_properties_door])
00338         self.update_name_label = QLabel("Door (" + self.edit_properties_door + " - " + connects_text + ")      New Name: ", self.widget)
00339         self.configuration_layout.addWidget(self.update_name_label)
00340 
00341         self.update_name_textedit = QLineEdit(self.widget)
00342         self.update_name_textedit.setText(self.edit_properties_door)
00343         self.update_name_textedit.textEdited.connect(self.doorNameTextEdited)
00344         self.configuration_layout.addWidget(self.update_name_textedit)
00345 
00346         self.update_name_button = QPushButton("Update door Name", self.widget)
00347         self.update_name_button.clicked[bool].connect(self.updateDoorName)
00348         self.update_name_button.setEnabled(False)
00349         self.configuration_layout.addWidget(self.update_name_button)
00350 
00351         self.remove_door_button = QPushButton("Remove Door", self.widget)
00352         self.remove_door_button.clicked[bool].connect(self.removeCurrentDoor)
00353         self.configuration_layout.addWidget(self.remove_door_button)
00354 
00355         self.configuration_layout.addStretch(1)
00356 
00357         self.updateOverlay()
00358 
00359     def endPropertyEdit(self):
00360 
00361         self.edit_door_location_button[DoorFunction.ADD_NEW_DOOR].setEnabled(True)
00362         self.edit_door_location_button[DoorFunction.EDIT_EXISTING_DOOR].setEnabled(False)
00363 
00364         clearLayoutAndFixHeight(self.configuration_layout)
00365 
00366         self.update_name_label = None
00367         self.update_name_textedit = None
00368         self.update_name_button = None
00369 
00370         self.editing_properties = False
00371 
00372         self.edit_properties_door = None
00373 
00374         self.updateOverlay()
00375 
00376     def doorNameTextEdited(self, text):
00377         if str(text) != self.edit_properties_door and str(text) not in self.doors:
00378             self.update_name_button.setEnabled(True)
00379         else:
00380             self.update_name_button.setEnabled(False)
00381 
00382     def updateDoorName(self):
00383         old_door_name = self.edit_properties_door
00384         new_door_name = str(self.update_name_textedit.text())
00385 
00386         # This is a simple rename task.
00387         self.doors[new_door_name] = self.doors.pop(old_door_name)
00388         self.draw_door[new_door_name] = self.draw_door.pop(old_door_name)
00389 
00390         # Since a door name was modified, set file modification to true.
00391         self.is_modified = True
00392 
00393         # Restart property edit with the updated name.
00394         self.endPropertyEdit()
00395         self.edit_properties_door = new_door_name
00396         self.startPropertyEdit()
00397 
00398     def removeCurrentDoor(self):
00399         old_door_name = self.edit_properties_door
00400         self.removeDoor(old_door_name)
00401         self.endPropertyEdit()
00402         self.updateOverlay()
00403 
00404         # Since a door was removed, set file modification to true.
00405         self.is_modified = True
00406 
00407     def removeDoor(self, door_name):
00408         if door_name in self.doors:
00409             self.doors.pop(door_name)
00410         if door_name in self.draw_door:
00411             self.draw_door.pop(door_name)
00412 
00413     def isModified(self):
00414         return self.is_modified
00415 
00416     def mousePressEvent(self, event):
00417         if self.editing_door_location:
00418             if self.current_selection == None:
00419                 # We are drawing the original door, and not moving it.
00420                 self.new_selection_start_point = event.pos()
00421                 self.new_selection_end_point = event.pos()
00422                 self.move_selection = None
00423             else:
00424                 # The initial door is already drawn. See if the user wants to move a point.
00425                 self.new_selection_start_point = None
00426                 self.new_selection_end_point = None
00427 
00428                 # Check if the user is clicking on 1 of the 4 points that define the door.
00429                 self.move_selection = None
00430                 for pt in [self.current_selection.door_corner_pt_1,
00431                            self.current_selection.door_corner_pt_2,
00432                            self.current_selection.approach_pt_1,
00433                            self.current_selection.approach_pt_2]:
00434                     if self.getPointDistanceToAnotherPoint(event.pos(), pt) <= 3:
00435                         self.move_selection = pt
00436                         break
00437         else:
00438             door = self.getDoorNameFromPoint(event.pos()) 
00439             if door is not None:
00440                 self.edit_properties_door = door
00441                 self.startPropertyEdit()
00442             else:
00443                 self.endPropertyEdit()
00444 
00445     def mouseReleaseEvent(self, event):
00446         if self.editing_door_location:
00447             self.mouseMoveEvent(event)
00448             if self.current_selection is None:
00449                 midpoint = (self.new_selection_start_point + self.new_selection_end_point) / 2 
00450                 diff = self.new_selection_end_point - self.new_selection_start_point
00451                 segment_angle = math.atan2(diff.y(), diff.x())
00452                 perpendicular_angle = segment_angle + math.pi / 2.0
00453                 perpendicular_diff_pt = QPoint(int(10.0 * math.cos(perpendicular_angle)), 
00454                                                int(10.0 * math.sin(perpendicular_angle))) 
00455 
00456                 approach_pt_1 = midpoint + perpendicular_diff_pt
00457                 approach_pt_2 = midpoint - perpendicular_diff_pt
00458                 self.current_selection = Door(self.new_selection_start_point,
00459                                               self.new_selection_end_point,
00460                                               approach_pt_1,
00461                                               approach_pt_2)
00462                 self.current_selection_label.setText(self.getConnectingText(self.current_selection))
00463                 self.new_selection_start_pt = None
00464                 self.new_selection_end_point = None
00465                 self.updateOverlay()
00466 
00467     def mouseMoveEvent(self, event):
00468 
00469         if self.editing_door_location:
00470             overlay_update_region = None
00471             if self.current_selection is None:
00472                 # First make sure we update the region corresponding to the old mark.
00473                 old_overlay_update_rect = self.getRectangularPolygon(self.new_selection_start_point, self.new_selection_end_point)
00474                 self.new_selection_end_point = event.pos()
00475                 # Next determine the region that needs to be update because of the new mark.
00476                 new_overlay_update_rect = self.getRectangularPolygon(self.new_selection_start_point, self.new_selection_end_point)
00477                 overlay_update_region = (old_overlay_update_rect + new_overlay_update_rect).boundingRect()
00478                 overlay_update_region.setTopLeft(QPoint(overlay_update_region.topLeft().x() - 4,
00479                                                         overlay_update_region.topLeft().y() - 4))
00480                 overlay_update_region.setBottomRight(QPoint(overlay_update_region.bottomRight().x() + 4,
00481                                                             overlay_update_region.bottomRight().y() + 4))
00482 
00483                 self.updateOverlay(overlay_update_region)
00484             elif self.move_selection is not None:
00485                 # Move the current point.
00486                 self.move_selection.setX(event.pos().x())
00487                 self.move_selection.setY(event.pos().y())
00488                 # TODO do some math to figure out the overlay update region. from the old and new point. remember
00489                 # that the connecting line may also have to be updated.
00490 
00491                 self.current_selection_label.setText(self.getConnectingText(self.current_selection))
00492                 self.updateOverlay()
00493 
00494     def updateOverlay(self, rect = None):
00495 
00496         # Redraw the overlay image from scratch using the door image and current door.
00497 
00498         self.image.overlay_image.fill(Qt.transparent)
00499         painter = QPainter(self.image.overlay_image)
00500         painter.setBackgroundMode(Qt.TransparentMode)
00501         painter.setCompositionMode(QPainter.CompositionMode_Source)
00502 
00503         for door in self.doors:
00504             if self.draw_door[door]:
00505                 color = self.unselected_door_color
00506                 if self.edit_properties_door == door and self.editing_properties:
00507                     color = self.selected_door_color
00508                 self.drawDoor(self.doors[door], painter, color)
00509 
00510         if self.current_selection is not None:
00511             color = self.selected_door_color
00512             self.drawDoor(self.current_selection, painter, color)
00513         elif self.new_selection_start_point is not None:
00514             color = self.selected_door_color
00515             self.drawLine(self.new_selection_start_point, self.new_selection_end_point, painter, color)
00516         painter.end()
00517 
00518         if rect is None:
00519             self.image.update()
00520         else:
00521             self.image.update(rect)
00522 
00523     def getConnectingText(self, door):
00524         # Get the two locations this door connects by looking up the locations of the approach points in the 
00525         # door function.
00526         approach_location_1 = self.location_function.getLocationNameFromPoint(door.approach_pt_1)
00527         if approach_location_1 is None:
00528             approach_location_1 = "<None>"
00529         approach_location_2 = self.location_function.getLocationNameFromPoint(door.approach_pt_2)
00530         if approach_location_2 is None:
00531             approach_location_2 = "<None>"
00532         return "Connects: " + approach_location_1 + " <-> " + approach_location_2
00533 
00534     def getUniqueName(self):
00535         name = "new_door" + str(self.unique_door_counter)
00536         self.unique_door_counter += 1
00537         return name
00538 
00539     def getPointDistanceToAnotherPoint(self, pt1, pt2):
00540         diff = pt1 - pt2
00541         return math.sqrt(diff.x() * diff.x() + diff.y() * diff.y())
00542 
00543     def getPointDistanceToLineSegment(self, pt, segment_pt_1, segment_pt_2):
00544         """
00545         http://stackoverflow.com/questions/849211/shortest-distance-between-a-point-and-a-line-segment
00546         """
00547         px = segment_pt_2.x()-segment_pt_1.x()
00548         py = segment_pt_2.y()-segment_pt_1.y()
00549 
00550         something = px*px + py*py
00551 
00552         u =  ((pt.x() - segment_pt_1.x()) * px + (pt.y() - segment_pt_1.y()) * py) / float(something)
00553 
00554         if u > 1:
00555             u = 1
00556         elif u < 0:
00557             u = 0
00558 
00559         x = segment_pt_1.x() + u * px
00560         y = segment_pt_1.y() + u * py
00561 
00562         dx = x - pt.x()
00563         dy = y - pt.y()
00564 
00565         return math.sqrt(dx*dx + dy*dy)
00566 
00567     def getRectangularPolygon(self, pt1, pt2):
00568         return QPolygon([pt1, QPoint(pt1.x(), pt2.y()), pt2, QPoint(pt2.x(), pt1.y())])
00569 
00570     def drawDoor(self, door, painter, color):
00571         self.drawLine(door.door_corner_pt_1, door.door_corner_pt_2, painter, color)
00572         self.drawPoint(door.approach_pt_1, painter, color)
00573         self.drawPoint(door.approach_pt_2, painter, color)
00574 
00575     def drawLine(self, pt1, pt2, painter, color):
00576         painter.setPen(color)
00577         painter.drawLine(pt1, pt2)
00578         self.drawPoint(pt1, painter, color)
00579         self.drawPoint(pt2, painter, color)
00580 
00581     def drawPoint(self, pt, painter, color):
00582         painter.setPen(color)
00583         painter.drawPoint(pt)
00584         painter.drawEllipse(pt, 3, 3)


bwi_planning_common
Author(s): Piyush Khandelwal
autogenerated on Thu Jun 6 2019 17:57:32