示例#1
0
    def byCenter2Points(cls, pc, p1, p2):
        """Create an ellipse by center and 2 points for axis.

             /----p2----\
            /            \
            |     pc     p1
            \            /
             \----------/
        """
        if not isinstance(pc, (QgsPoint, CADPoint)) \
            or not isinstance(p1,
                              (QgsPoint, CADPoint)) \
            or not isinstance(p2,
                              (QgsPoint, CADPoint)):
            raise AttributeError

        pc = CADPoint(pc)
        p1 = CADPoint(p1)
        p2 = CADPoint(p2)

        angle_exist = pc.getAngleOfLineBetweenTwoPoints(p1)

        axis_a = pc.distance(p1)

        pp = CADLine.pointOnALine(CADLine(pc, p1), p2)
        length = p2.distance(pp)
        pp2 = pc.pointProjected(length, 90 + angle_exist)
        axis_b = pc.distance(pp2)

        return cls(pc, axis_a, axis_b, angle_exist)
示例#2
0
    def by2Corners(cls, p1, p2, nbEdges=5):
        """CADRegularPolygon by 2 corners (AB):
           A----B
          /      \
         /        \
         \        /
          \------/
          """
        if not isinstance(p1, (QgsPoint, CADPoint)) or \
           not isinstance(p2, (QgsPoint, CADPoint)) or \
           not isinstance(nbEdges, (long, int)):
            raise AttributeError
        else:
            p1 = CADPoint(p1)
            p2 = CADPoint(p2)
            angle_exist = p1.getAngleOfLineBetweenTwoPoints(p2)
            pm = p1.midpoint(p2)
            length = p1.distance(pm)

            angle = (180.0 - (360.0 / nbEdges)) / 2.0
            hypo = length / math.cos(math.radians(angle))
            pc = p1.pointProjected(hypo, angle_exist + angle)

            return cls(pc, p1, nbEdges)

        return None
示例#3
0
    def by3Points(cls, p1, p2, p3):
        """Create a CADRectangle with 2 points (AD) and a length (X - AD)
        D-------C
        |       X
        A-------B
        """
        if not isinstance(p1, (CADPoint, QgsPoint)) or \
           not isinstance(p2, (CADPoint, QgsPoint)) or \
           not isinstance(p3, (CADPoint, QgsPoint)):
            raise AttributeError

        p1 = CADPoint(p1)
        p2 = CADPoint(p2)
        p3 = CADPoint(p3)

        l = CADLine(p1, p2)
        angle_exist = p1.getAngleOfLineBetweenTwoPoints(p2)
        side = CADPoint.isCollinear(p1, p2, p3)
        if side == 0:
            return None

        pp = CADLine.pointOnALine(CADLine(p1, p2), p3)

        length = p3.distance(pp) * side

        p3 = p2.pointProjected(length, 90 + angle_exist)
        p4 = p1.pointProjected(length, 90 + angle_exist)

        return cls(p1, p2, p3, p4)
示例#4
0
    def perpendicular_segment(self, p):
        """Create a perpendicular line segment from `p` to this line.

        The enpoints of the segment are ``p`` and the closest point in
        the line containing self. (If self is not a line, the point might
        not be in self.)
        """
        if not isinstance(p, (QgsPoint, CADPoint)):
            raise AttributeError

        p = CADPoint(p)
        if p in self.points:
            return p
        a, b, c = self.coefficients
        if a == 0:  # horizontal
            p2 = CADPoint(p.x, self.p1.y)
        elif b == 0:  # vertical
            p2 = CADPoint(self.p1.x, p.y)
        else:
            # ax + by + c = 0
            y = (-c - a * p.x) / b
            m = self.slope
            d2 = 1 + m**2
            H = p.y - y
            dx = m * H / d2
            dy = m * dx
            p2 = CADPoint(p.x + dx, y + dy)
        return CADLine(p, p2)
示例#5
0
    def by2PointsAndWidth(cls, p1, p2, w):
        """Create a CADRectangle with 2 points (AD) and the width
        D-------C
        |       |
        A-------B
        """

        if not isinstance(p1, (CADPoint, QgsPoint)) or \
           not isinstance(p2, (CADPoint, QgsPoint)) or \
           not isinstance(w, (float, long, int)):
            raise AttributeError

        p1 = CADPoint(p1)
        p2 = CADPoint(p2)

        angle_exist = p1.getAngleOfLineBetweenTwoPoints(p2)

        pt1 = p1
        pt2 = p1.pointProjected(w, 90 - angle_exist)
        pt3 = p2.pointProjected(w, 90 - angle_exist)
        pt4 = p2

        l = CADLine(p1, p2)
        if CADPoint.isCollinear(pt1, pt2, pt3) == 0:
            pt2 = p1.pointProjected(w, 90 + angle_exist)
            pt3 = p2.pointProjected(w, 90 + angle_exist)

        return cls(pt1, pt2, pt3, pt4)
示例#6
0
    def fromFoci(cls, f1, f2, f3):
        """Create an ellipse from foci.
            f1 and f2 are foci
            f3 is the axis_b

             /----f3----\
            /            \
            |  f1    f2  |
            \            /
             \----------/
        """
        if not isinstance(f1, (QgsPoint, CADPoint)) \
            or not isinstance(f2,
                              (QgsPoint, CADPoint)) \
            or not isinstance(f3,
                              (QgsPoint, CADPoint)):
            raise AttributeError

        f1 = CADPoint(f1)
        f2 = CADPoint(f2)
        f3 = CADPoint(f3)

        dist_f1f2 = f1.distance(f2)
        dist_f1f3 = f1.distance(f3)
        dist_f2f3 = f2.distance(f3)

        dist_tot = dist_f1f3 + dist_f2f3
        angle_exist = f1.getAngleOfLineBetweenTwoPoints(f2)
        center_f1f2 = f1.midpoint(f2)

        axis_a = dist_tot / 2.0
        axis_b = math.sqrt((dist_tot / 2.0)**2.0 - (dist_f1f2 / 2.0)**2.0)

        return cls(center_f1f2, axis_a, axis_b, angle_exist)
示例#7
0
 def quadrant(self):
     """Return 4 coordinates [East, North, West, South]
     of circle's quadrant"""
     N = CADPoint(self._center.x, self._center.y + self._radius)
     S = CADPoint(self._center.x, self._center.y - self._radius)
     E = CADPoint(self._center.x + self._radius, self._center.y)
     W = CADPoint(self._center.x - self._radius, self._center.y)
     return [E, N, W, S]
示例#8
0
    def fromQgsRectangle(cls, r):
        """Create a CADRectangle from a QgsRectangle
        """
        if not isinstance(r, QgsRectangle):
            raise AttributeError("Error:" + cls.__name__ + " - " + __file__)
            return cls()

        return cls.byExtent(CADPoint(r.xMinimum(), r.yMinimum()),
                            CADPoint(r.xMaximum(), r.yMaximum()))
示例#9
0
    def by3Points(cls, p1, p2, p3, epsilon=1e-8):
        """Create a CADCircle with 3 points ABC
          /------\
         |        |
         A        C
         |        |
          \--B---/
        """
        if not all(isinstance(p, (QgsPoint, CADPoint)) for p in [p1, p2, p3]):
            raise AttributeError

        p1 = CADPoint(p1)
        p2 = CADPoint(p2)
        p3 = CADPoint(p3)

        # Paul Bourke's algorithm
        m_Center = CADPoint()
        m_dRadius = -1
        yDelta_a = p2.y - p1.y
        xDelta_a = p2.x - p1.x
        yDelta_b = p3.y - p2.y
        xDelta_b = p3.x - p2.x

        try:
            aSlope = yDelta_a / xDelta_a
        except ZeroDivisionError:
            return None

        try:
            bSlope = yDelta_b / xDelta_b
        except ZeroDivisionError:
            return None

        if (math.fabs(xDelta_a) <= epsilon and math.fabs(yDelta_b) <= epsilon):
            m_Center.x = (0.5 * (p2.x + p3.x))
            m_Center.y = (0.5 * (p1.y + p2.y))
            m_dRadius = m_Center.distance(p1)

            return cls(m_Center, m_dRadius)

        if math.fabs(aSlope-bSlope) <= epsilon:
            return None

        m_Center.x = (
                      (aSlope * bSlope * (p1.y - p3.y) +
                       bSlope * (p1.x + p2.x) -
                       aSlope * (p2.x + p3.x)) /
                      (2.0 * (bSlope - aSlope))
                     )
        m_Center.y = (
                      -1.0 * (m_Center.x - (p1.x + p2.x) / 2.0) /
                      aSlope + (p1.y + p2.y) / 2.0
                     )

        m_dRadius = m_Center.distance(p1)

        return cls(m_Center, m_dRadius)
示例#10
0
    def __init__(self, p1, p2):
        if not all([isinstance(p, (QgsPoint, CADPoint)) for p in [p1, p2]]):
            raise AttributeError
        if p1 == p2:
            # Adapted from SymPy
            # if it makes sense to return a Point, handle in subclass
            raise ValueError("CADLine requires two unique Points.")

        self._p1 = CADPoint(p1)
        self._p2 = CADPoint(p2)
示例#11
0
 def __init__(self, pCenter, pCorner, nbEdges=5):
     if not isinstance(pCenter, (QgsPoint, CADPoint)) \
         or not isinstance(pCorner, (QgsPoint, CADPoint)) \
         or not isinstance(nbEdges,
                           (long, int)):
         raise AttributeError
     else:
         self._center = CADPoint(pCenter)
         self._corner = CADPoint(pCorner)
         self._nbEdges = nbEdges
         self.__points = self.__updatePoints()
示例#12
0
 def __init__(self, ptStart, ptEnd, ptArc):
     if not all([
             isinstance(p, (CADPoint, QgsPoint))
             for p in [ptStart, ptEnd, ptArc]
     ]):
         raise AttributeError
     else:
         self._ptStart = CADPoint(ptStart)
         self._ptEnd = CADPoint(ptEnd)
         self._ptArc = CADPoint(ptArc)
         self._ptCenter = self.__getArcCenter()
示例#13
0
    def byCenterPoint(cls, pc, p1):
        """Create a CADCircle by Extent CA
          /------\A
         |        |
         |   C    |
         |        |
          \------/
        """
        if not all(isinstance(p, (QgsPoint, CADPoint)) for p in [p1, pc]):
            raise AttributeError

        p1 = CADPoint(p1)
        pc = CADPoint(pc)

        return cls(pc, pc.distance(p1))
示例#14
0
    def trim(self, other, p):
        """Return the new CADLine result of intersection with other.
        For segment AB intersected at i and clicked on p, the CADLine returned
        will iB
        A-----i------p---B
        return:
              i----------B
        """
        if isinstance(p, (QgsPoint, CADPoint)) and \
           isinstance(other, CADLine) and \
           self.intersects(other):
            p = CADPoint(p)

            try:
                pt_inter = self.intersection(other)
                p1pi = CADLine(pt_inter, self.p1)
                p2pi = CADLine(self.p2, pt_inter)
                if p1pi.isOnSegment(p) == 2:
                    return p1pi
                elif p2pi.isOnSegment(p) == 2:
                    return p2pi
                else:
                    return None
            except:
                return None

            return None
        else:
            raise AttributeError
示例#15
0
 def __init__(self, pc, radius):
     if not isinstance(pc, (CADPoint, QgsPoint)) or \
        not isinstance(radius, (float, long, int)):
         raise AttributeError
     else:
         self._center = CADPoint(pc)
         self._radius = radius
示例#16
0
    def isOnSegment(self, p):
        """Test if this point is on the segment defined by points a, b.
        Returns
        0 if this point is not on the open ray through a and b,
        1 if point is on open ray a,
        2 if point is within line segment,
        3 if point is on open ray b.
        """
        if not isinstance(p, (QgsPoint, CADPoint)):
            raise AttributeError

        p = CADPoint(p)
        a, b = self.points
        # algorithm from 'graphics GEMS',
        # A. Paeth: 'A Fast 2D Point-on-line test'
        if (abs((b.y - a.y) * (p.x - a.x) - (p.y - a.y) *
                (b.x - a.x)) >= max(abs(b.x - a.x), abs(b.y - a.y))):
            return 0
        if ((b.x < a.x and a.x < p.x) or (b.y < a.y and a.y < p.y)):
            return 1
        if ((p.x < a.x and a.x < b.x) or (p.y < a.y and a.y < b.y)):
            return 1
        if ((a.x < b.x and b.x < p.x) or (a.y < b.y and b.y < p.y)):
            return 3
        if ((p.x < b.x and b.x < a.x) or (p.y < b.y and b.y < a.y)):
            return 3

        return 2
示例#17
0
 def corner(self, pc):
     """Set the first corner (edge) of the RegularPolygon
     """
     if not isinstance(pc, (QgsPoint, CADPoint)):
         raise AttributeError
     self._corner = CADPoint(pc)
     self.__update()
示例#18
0
    def isValid(self, tolerance=0.1):
        """Return True if is really a rectangle"""
        if not isinstance(tolerance, (float, int, long)):
            tolerance = 0.1

        p1, p2, p3, p4 = self.__points[:]
        p12 = p1.getAngleOfLineBetweenTwoPoints(p2)
        p23 = p2.getAngleOfLineBetweenTwoPoints(p3)
        a1 = p23 - p12

        p34 = p3.getAngleOfLineBetweenTwoPoints(p4)
        p41 = p4.getAngleOfLineBetweenTwoPoints(p1)
        a2 = p41 - p34

        if self.__points == [CADPoint(0.0, 0.0)] * 4:
            return False

        if len(set(self.__points)) != 4:
            return False

        if not near(a1 % 90, 0.0, tolerance) or not near(
                a2 % 90, 0.0, tolerance):
            return False

        return True
示例#19
0
 def __contains__(self, other):
     if isinstance(other, (QgsPoint, CADPoint)):
         other = CADPoint(other)
         return bool(self.isOnSegment(other) == 2)
     elif isinstance(other, CADLine):
         return self.intersects(other)
     else:
         return False
示例#20
0
    def byCenter2Points(cls, ptCenter, ptStart, ptEnd, direction=1):
        """Create a CADCirclurArc with by Center C and 2 points AB
         A   C    B
         |        |
          \------/
        """
        if all([isinstance(p, (CADPoint, QgsPoint))
                for p in [ptCenter, ptStart, ptEnd]]) and \
           isinstance(direction, (int, long)):
            ptCenter = CADPoint(ptCenter)
            ptStart = CADPoint(ptStart)
            ptEnd = CADPoint(ptEnd)

            a1 = ptCenter.getAngleOfLineBetweenTwoPoints(ptStart)
            a2 = ptCenter.getAngleOfLineBetweenTwoPoints(ptEnd)
            return cls.byCenterPointAngle(ptCenter, ptStart, a2 - a1,
                                          direction)
示例#21
0
 def __iter__(self, segments=36):
     angle = math.radians(self._angle)
     for t in [(2 * math.pi) / segments * i for i in range(segments)]:
         p = CADPoint(
             self._center.x + self._axis_a * math.cos(t) * math.cos(angle) -
             self._axis_b * math.sin(t) * math.sin(angle),
             self._center.y + self._axis_a * math.cos(t) * math.sin(angle) +
             self._axis_b * math.sin(t) * math.cos(angle))
         yield p
示例#22
0
    def by2Points(cls, p1, p2):
        """Create a CADCircle with 2 points (from diameter : AB)
          /------\
         |        |
         A        B
         |        |
          \------/
        """
        if not all(isinstance(p, (QgsPoint, CADPoint)) for p in [p1, p2]):
            raise AttributeError

        p1 = CADPoint(p1)
        p2 = CADPoint(p2)

        center = p1.midpoint(p2)
        radius = p1.distance(center)

        return cls(center, radius)
示例#23
0
 def nearestPoints(self, other):
     if isinstance(other, (QgsPoint, CADPoint)):
         other = CADPoint(other)
         dist = [other.distance(p) for p in self.points]
         neareastDist = min(dist)
         idx = dist.index(neareastDist)
         return (self.points[idx], idx)
     else:
         raise AttributeError
示例#24
0
 def center(self, pointC):
     if isinstance(pointC, CADPoint):
         offsetX = pointC.x - self._center.x
         offsetY = pointC.y - self._center.y
         self._center = pointC
         for i, p in enumerate(self.__points):
             self.__points[i] = CADPoint(p.x + offsetX, p.y + offsetY)
         self.__updateMin()
         self.__updateMax
示例#25
0
    def perpendicular_line(self, p):
        """Create a new Line perpendicular to this linear entity which passes
        through the point `p`.
        """
        if not isinstance(p, (QgsPoint, CADPoint)):
            raise AttributeError

        p = CADPoint(p)
        d1, d2 = (self.p1.x - self.p2.x, self.p1.y - self.p2.y)
        if d2 == 0:  # If a horizontal line
            if p.y == self.p1.y:  # if p is on this linear entity
                return CADLine(p, p + CADPoint(0, 1))
            else:
                p2 = CADPoint(p.x, self.p1.y)
                return CADLine(p, p2)
        else:
            p2 = CADPoint(p.x - d2, p.y + d1)
            return CADLine(p, p2)
示例#26
0
    def parallel_line(self, p):
        """Create a new Line parallel to this linear entity which passes
        through the point `p`.
        """
        if not isinstance(p, (QgsPoint, CADPoint)):
            raise AttributeError

        p = CADPoint(p)
        d = self.p1 - self.p2
        return CADLine(p, p + d)
示例#27
0
    def pointOnALine(line, pp):
        """Return orthogonal point projected (pp) on line
        """
        if not isinstance(pp, (QgsPoint, CADPoint)) or \
           not isinstance(line, CADLine):
            raise AttributeError

        p1, p2 = line.points
        pp = CADPoint(pp)

        # http://stackoverflow.com/a/15187473
        t_num = ((pp.x - p1.x) * (p2.x - p1.x) + (pp.y - p1.y) * (p2.y - p1.y))
        t_denum = ((p2.x - p1.x)**2 + (p2.y - p1.y)**2)
        t = t_num / t_denum

        Dx = p1.x + t * (p2.x - p1.x)
        Dy = p1.y + t * (p2.y - p1.y)

        return CADPoint(Dx, Dy)
示例#28
0
    def by2Points(cls, p1, p2):
        """Create a CADRectangle with 2 points (from extent : AC)
        D-------C
        |       |
        A-------B
        """
        if not isinstance(p1, (CADPoint, QgsPoint)) or \
           not isinstance(p2, (CADPoint, QgsPoint)):
            raise AttributeError

        p1 = CADPoint(p1)
        p2 = CADPoint(p2)

        pt0 = p1
        pt1 = CADPoint(p2.x, p1.y)
        pt2 = p2
        pt3 = CADPoint(p1.x, p2.y)

        return cls(pt0, pt1, pt2, pt3)
示例#29
0
    def center(self, pc):
        """Set the center of the RegularPolygon
        """
        if not isinstance(pc, (QgsPoint, CADPoint)):
            raise AttributeError

        angle_exist = self._rotation
        dist_exist = self._radius
        self._center = CADPoint(pc)
        self._corner = self._center.pointProjected(dist_exist, angle_exist)
        self._update()
示例#30
0
    def byCenterPoint(cls, pc, p1):
        """Create an ellipse by this center and an extent point

             /----------\ p1
            /            \
            |     pc     |
            \            /
             \----------/
        """
        if not isinstance(pc, (QgsPoint, CADPoint)) \
            or not isinstance(p1,
                              (QgsPoint, CADPoint)):
            raise AttributeError

        pc = CADPoint(pc)
        p1 = CADPoint(p1)

        xOffset = abs(pc.x - p1.x)
        yOffset = abs(pc.y - p1.y)

        return cls(pc, xOffset, yOffset)