ChartsOrg / Charts

Beautiful charts for iOS/tvOS/OSX! The Apple side of the crossplatform MPAndroidChart.
Apache License 2.0
27.43k stars 5.97k forks source link

[Unknown process name] CGAffineTransformInvert: singular matrix #5160

Open AnmolVarshney1 opened 3 months ago

AnmolVarshney1 commented 3 months ago
class StencilQuadView: UIImageView {
    var addFreeTool: (() -> ())?

    override init(frame: CGRect) {
        super.init(frame: frame)
        self.layer.anchorPoint = .zero
        self.isUserInteractionEnabled = true
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        self.layer.anchorPoint = .zero
    }

    // Function to transform the view to fit specified quad
    func transformToFitQuadTopLeft(tl: CGPoint, tr: CGPoint, bl: CGPoint, br: CGPoint) {
            guard self.layer.anchorPoint == .zero else {
                return
            }
            let b = boundingBoxForQuadTR(tl, tr, bl, br)
            self.frame = b
            self.layer.transform = rectToQuad(bounds,
                .init(x: tl.x-b.origin.x, y: tl.y-b.origin.y),
                .init(x: tr.x-b.origin.x, y: tr.y-b.origin.y),
                .init(x: bl.x-b.origin.x, y: bl.y-b.origin.y),
                .init(x: br.x-b.origin.x, y: br.y-b.origin.y))
        }

    // Helper function to calculate bounding box for the quad
    private func boundingBoxForQuadTR(_ tl: CGPoint, _ tr: CGPoint, _ bl: CGPoint, _ br: CGPoint) -> CGRect {
        let xmin = min(tl.x, tr.x, bl.x, br.x)
        let ymin = min(tl.y, tr.y, bl.y, br.y)
        let xmax = max(tl.x, tr.x, bl.x, br.x)
        let ymax = max(tl.y, tr.y, bl.y, br.y)
        return CGRect(x: xmin, y: ymin, width: xmax - xmin, height: ymax - ymin)
    }

    // Function to calculate the CATransform3D for a quad
    func rectToQuad(_ rect: CGRect,
                        _ topLeft: CGPoint, _ topRight: CGPoint, _ bottomLeft: CGPoint, _ bottomRight: CGPoint) -> CATransform3D {
            rectToQuadCalculation(rect,
                    topLeft.x, topLeft.y,
                    topRight.x, topRight.y,
                    bottomLeft.x, bottomLeft.y,
                    bottomRight.x, bottomRight.y)
        }

    // Function to perform the rect to quad calculation
    func rectToQuadCalculation(_ rect: CGRect,
                        _ x1a: CGFloat, _ y1a: CGFloat,
                        _ x2a: CGFloat, _ y2a: CGFloat,
                        _ x3a: CGFloat, _ y3a: CGFloat,
                        _ x4a: CGFloat, _ y4a: CGFloat) -> CATransform3D {
        let XX = rect.origin.x
        let YY = rect.origin.y
        let WW = rect.size.width
        let HH = rect.size.height

        let y21 = y2a - y1a
        let y32 = y3a - y2a
        let y43 = y4a - y3a
        let y14 = y1a - y4a
        let y31 = y3a - y1a
        let y42 = y4a - y2a

        let a = -HH * (x2a*x3a*y14 + x2a*x4a*y31 - x1a*x4a*y32 + x1a*x3a*y42)
        let b = WW * (x2a*x3a*y14 + x3a*x4a*y21 + x1a*x4a*y32 + x1a*x2a*y43)

        let c0 = -HH * WW * x1a * (x4a*y32 - x3a*y42 + x2a*y43)
        let cx = HH * XX * (x2a*x3a*y14 + x2a*x4a*y31 - x1a*x4a*y32 + x1a*x3a*y42)
        let cy = -WW * YY * (x2a*x3a*y14 + x3a*x4a*y21 + x1a*x4a*y32 + x1a*x2a*y43)
        let c = c0 + cx + cy
        let d = HH * (-x4a*y21*y3a + x2a*y1a*y43 - x1a*y2a*y43 - x3a*y1a*y4a + x3a*y2a*y4a)
        let e = WW * (x4a*y2a*y31 - x3a*y1a*y42 - x2a*y31*y4a + x1a*y3a*y42)

        let f0 = -WW * HH * (x4a * y1a * y32 - x3a * y1a * y42 + x2a * y1a * y43)
        let fx = HH * XX * (x4a * y21 * y3a - x2a * y1a * y43 - x3a * y21 * y4a + x1a * y2a * y43)
        let fy = -WW * YY * (x4a * y2a * y31 - x3a * y1a * y42 - x2a * y31 * y4a + x1a * y3a * y42)
        let f = f0 + fx + fy
        let g = HH * (x3a * y21 - x4a * y21 + (-x1a + x2a) * y43)
        let h = WW * (-x2a * y31 + x4a * y31 + (x1a - x3a) * y42)

        let iy = WW * YY * (x2a * y31 - x4a * y31 - x1a * y42 + x3a * y42)
        let ix = HH * XX * (x4a * y21 - x3a * y21 + x1a * y43 - x2a * y43)
        let i0 = HH * WW * (x3a * y42 - x4a * y32 - x2a * y43)
        var i = i0 + ix + iy
        let kEpsilon: CGFloat = 0.0001
        if abs(i) < kEpsilon {
            i = kEpsilon * (i > 0 ? 1 : -1)
        }

        return CATransform3D(
            m11: a/i, m12: d/i, m13: 0, m14: g/i,
            m21: b/i, m22: e/i, m23: 0, m24: h/i,
            m31: 0, m32: 0, m33: 1, m34: 0,
            m41: c/i, m42: f/i, m43: 0, m44: 1.0)
        }
}

struct DragView{
    var cornerTag: Int?
    var frame: CGRect?
    var radius: Int?
    var stencilId: Int?
    var center: CGPoint?
    var updatedIndex: Int?
    var stencilQuadView: StencilQuadView?
}

class DraggableCorner: UIView {

    var drag: ((CGPoint) -> Void)?
    var isDragDone: (((Bool, CGPoint, Int)) -> Void)?
    var stencilId: Int = 0

    override init(frame: CGRect) {
        super.init(frame: frame)
        initialize()
    }

    required init?(coder: NSCoder) {
        super.init(coder: coder)
        initialize()
    }

    private func initialize() {
        let panGesture = UIPanGestureRecognizer(target: self, action: #selector(panGestureAction(_:)))
        self.addGestureRecognizer(panGesture)
    }

    @objc private func panGestureAction(_ gesture: UIPanGestureRecognizer) {
        let translation = gesture.translation(in: self.superview)
        guard let superview = superview else { return }
        self.center = CGPoint(x: self.center.x + translation.x, y: self.center.y + translation.y)
        gesture.setTranslation(.zero, in: superview)
        if gesture.state == .ended {
            isDragDone?((true, self.center, stencilId))
        }
        else{
            drag?(self.center)
        }
    }
}

From the above code I have attached four new corners for the image view and as soon as I drag the image is changing to any quadrilateral but when I do more operation the image is hiding and the error is showing please anyone help!