def buildScanPoints(cls, points: PolygonPoints) -> ScanPoints: minX: int = points[0].x maxX: int = points[0].y minY: int = points[0].x maxY: int = points[0].y for point in points: currX: int = point.x currY: int = point.y if currX < minX: minX = currX if currX > maxX: maxX = currX if currY < minY: minY = currY if currY > maxY: maxY = currY scanPoints: ScanPoints = ScanPoints() scanPoints.startScan = InternalPosition(minX, minY) scanPoints.endScan = InternalPosition(maxX, maxY) return scanPoints
def __computeTheArrowVertices(self, src: InternalPosition, dst: InternalPosition) -> ArrowPoints: """ Draw an arrow at the end of the line source-destination. Args: src: points of the segment dst: points of the segment Returns: A list of positions that describes a diamond to draw """ # x1: float = src.x # y1: float = src.y # x2: float = dst.x # y2: float = dst.y # # deltaX: float = x2 - x1 # deltaY: float = y2 - y1 deltaX, deltaY = self.__computeDeltaXDeltaY(src, dst) if abs(deltaX) < 0.01: # vertical segment if deltaY > 0: alpha = -pi / 2 else: alpha = pi / 2 else: if deltaX == 0: alpha = pi / 2 else: alpha = atan(deltaY / deltaX) if deltaX > 0: alpha += pi pi_6: float = pi / 6 # radians for 30 degree angle alpha1: float = alpha + pi_6 alpha2: float = alpha - pi_6 size: float = PdfLine.INHERITANCE_ARROW_HEIGHT x2: int = dst.x y2: int = dst.y # # The names for the left and right points are correct for upward facing arrows # They are inverted for downward facing arrows # arrowTip: InternalPosition = InternalPosition(x2, y2) rightPoint: InternalPosition = InternalPosition( x2 + round(size * cos(alpha1)), y2 + round(size * sin(alpha1))) leftPoint: InternalPosition = InternalPosition( x2 + round(size * cos(alpha2)), y2 + round(size * sin(alpha2))) points: ArrowPoints = [rightPoint, arrowTip, leftPoint] return points
def computeDiamondVertices(cls, src: InternalPosition, dest: InternalPosition) -> DiamondPoints: """ Args: src: The source point dest: The destination point """ pi_6: float = pi / 6 # radians for 30 degree angle x2: int = dest.x y2: int = dest.y deltaX, deltaY = Common.computeDeltaXDeltaY(src, dest) if abs(deltaX) < 0.01: # vertical segment if deltaY > 0: alpha = -pi / 2 else: alpha = pi / 2 else: if deltaX == 0: if deltaY > 0: alpha = pi / 2 else: alpha = 3 * pi / 2 else: alpha = atan(deltaY / deltaX) if deltaX > 0: alpha += pi alpha1: float = alpha + pi_6 alpha2: float = alpha - pi_6 size: int = Common.DIAMOND_HEIGHT # noinspection PyListCreation points: DiamondPoints = [] points.append( (InternalPosition(x2 + size * cos(alpha1), y2 + size * sin(alpha1)))) # type: ignore points.append(InternalPosition(x2, y2)) points.append( InternalPosition(x2 + size * cos(alpha2), y2 + size * sin(alpha2))) # type: ignore points.append( InternalPosition(x2 + 2 * size * cos(alpha), y2 + 2 * size * sin(alpha))) # type: ignore return points
def testPointLeftOfArrow(self): notInPolygon: InternalPosition = InternalPosition(0.0, 0.0) actualAns: bool = PdfCommon.pointInsidePolygon(pos=notInPolygon, polygon=self.arrow) self.assertFalse(actualAns, 'Arrow check is bad')
def testPointRightOfDiamond(self): notInPolygon: InternalPosition = InternalPosition(1122.0, 490.0) actualAns: bool = PdfCommon.pointInsidePolygon(pos=notInPolygon, polygon=self.diamond) self.assertFalse(actualAns, 'Diamond check is bad')
def testInCenterOfDiamond(self): inPolygon: InternalPosition = InternalPosition(1118.0, 470.0) actualAns: bool = PdfCommon.pointInsidePolygon(pos=inPolygon, polygon=self.diamond) self.assertTrue(actualAns, 'Diamond check in center of diamond is bad')
def testInCenterOfArrow(self): inPolygon: InternalPosition = InternalPosition(1118.0, 472.0) actualAns: bool = PdfCommon.pointInsidePolygon(pos=inPolygon, polygon=self.arrow) self.assertTrue(actualAns, 'Diamond check is bad')
def __computeDiamondVertices(self, src: InternalPosition, dst: InternalPosition) -> DiamondPoints: """ Args: src: dst: """ pi_6: float = pi / 6 # radians for 30 degree angle x2: int = dst.x y2: int = dst.y deltaX, deltaY = self.__computeDeltaXDeltaY(src, dst) if abs(deltaX) < 0.01: # vertical segment if deltaY > 0: alpha = -pi / 2 else: alpha = pi / 2 else: if deltaX == 0: if deltaY > 0: alpha = pi / 2 else: alpha = 3 * pi / 2 else: alpha = atan(deltaY / deltaX) if deltaX > 0: alpha += pi alpha1: float = alpha + pi_6 alpha2: float = alpha - pi_6 size: int = PdfLine.DIAMOND_HEIGHT # noinspection PyListCreation points: DiamondPoints = [] points.append((InternalPosition(x2 + round(size * cos(alpha1)), y2 + round(size * sin(alpha1))))) points.append(InternalPosition(x2, y2)) points.append( InternalPosition(x2 + round(size * cos(alpha2)), y2 + round(size * sin(alpha2)))) points.append( InternalPosition(x2 + 2 * round(size * cos(alpha)), y2 + 2 * round(size * sin(alpha)))) return points
def setUp(self): self.logger: Logger = TestDiagramCommon.clsLogger self.diamond: PolygonPoints = [ InternalPosition(1118.0, 460.0), InternalPosition(1122.0, 469.0717), InternalPosition(1114.0, 469.0717), InternalPosition(1118.0, 476.0) ] self.arrow: PolygonPoints = [ InternalPosition(1122.0, 469.0717), InternalPosition(1118.0, 476.0), InternalPosition(1114.0, 469.0717) ]
def __convertEndPoints( self, src: Position, dst: Position) -> Tuple[InternalPosition, InternalPosition]: verticalGap: int = self._diagramPadding.verticalGap horizontalGap: int = self._diagramPadding.horizontalGap sourceCoordinates: Coordinates = PdfCommon.convertPosition( pos=src, dpi=self._dpi, verticalGap=verticalGap, horizontalGap=horizontalGap) destinationCoordinates: Coordinates = PdfCommon.convertPosition( pos=dst, dpi=self._dpi, verticalGap=verticalGap, horizontalGap=horizontalGap) convertedSrc: InternalPosition = InternalPosition( sourceCoordinates.x, sourceCoordinates.y) convertedDst: InternalPosition = InternalPosition( destinationCoordinates.x, destinationCoordinates.y) return convertedSrc, convertedDst
def toInternal(cls, position: Position, verticalGap: int, horizontalGap: int) -> InternalPosition: """ Assumes a 1 to 1 relationship between display device and the image we are generating. Args: position: The original position verticalGap: Account for the vertical gap on the X-axis horizontalGap: Account for the horizontal gap on the Y-axis Returns: The new position adjust for margins and gaps """ adjustedX: int = position.x + LEFT_MARGIN + verticalGap adjustedY: int = position.y + TOP_MARGIN + horizontalGap return InternalPosition(x=adjustedX, y=adjustedY)
def __computeMidPointOfBottomLine( self, startPos: InternalPosition, endPos: InternalPosition) -> InternalPosition: """ These two coordinates are the two end-points of the bottom leg of the inheritance arrow midPoint = (x1+x2/2, y1+y2/2) Args: startPos: start of line endPos: end of line Returns: Midpoint between startPos - endPos """ x1: int = startPos.x y1: int = startPos.y x2: int = endPos.x y2: int = endPos.y midX: int = (x1 + x2) // 2 midY: int = (y1 + y2) // 2 return InternalPosition(midX, midY)
def __fillInDiamond(self, points: DiamondPoints): """ Args: points: The polygon that defines the composition diamond """ scanPoints: ScanPoints = PdfCommon.buildScanPoints(points) startX: int = scanPoints.startScan.x startY: int = scanPoints.startScan.y endX: int = scanPoints.endScan.x endY: int = scanPoints.endScan.y x = startX while x <= endX: y = startY while y <= endY: if PdfCommon.pointInsidePolygon(pos=InternalPosition(x, y), polygon=points): self._docMaker.line(x1=x, y1=y, x2=x, y2=y) y += 1 x += 1