दिलचस्प पोस्ट
ये जावास्क्रिप्ट bitwise ऑपरेटर्स क्या करते हैं? पंडस टाइमर चीजों को एक्स-अक्ष प्रमुख और मामूली टिक और लेबल सेट करते हैं कैस्परजेएस बाँध मुद्दे एचटीएमएल टैग्स <div> और <span> के बीच अंतर क्या है? सामग्री के बाद कॉल करने के लिए एन्जिलरज इवेंट लाए जाते हैं केस और ग्रुप द्वारा धुरी के लिए डायनामिक विकल्प सूची <सूची <int >> का संयोजन एचटीएमएल की छिपी हुई विशेषताओं Rails और Rake समस्याओं पर रूबी: uninitialized निरंतर रेक :: डीएसएल एक निश्चित समय के बाद कमांड लाइन को स्वतः-मारने के लिए कमांड लाइन कमांड सी ++ 11 के लिए अनुक्रम-ज़िप फ़ंक्शन? कोर डंप फ़ाइल विश्लेषण क्या चारों ओर हस्ताक्षरित या हस्ताक्षरित डिफ़ॉल्ट रूप से? GetMapAsync के साथ getMap को बदलें सी # विंडोज फॉर्म से मौजूदा यूआरएल को पुनर्प्राप्त करें

एक कैरेट्रांसफोर्म 3 डी का उपयोग करते हुए एक चौकोर आकार में एक आयताकार छवि को ट्रांसफ़ॉर्म करना

मेरे पास एक छवि और चार बिंदुओं का एक सेट है (एक चतुर्भुज क्यू का वर्णन करना) मैं इस छवि को बदलना चाहता हूं ताकि यह चतुर्भुज क्यू फिट हो। फ़ोटोशॉप इस परिवर्तन को "विकृत" कहते हैं। लेकिन इस चतुर्भुज (अंतरिक्ष में चलने वाली छवि के परिप्रेक्ष्य) के अनुसार, यह वास्तव में एक पैमाने, एक रोटेशन और परिप्रेक्ष्य मैट्रिक्स का संयोजन है।

मैं सोच रहा हूं कि यह संभवतः एक कैटरसफोर्स 3 डी 4×4 मैट्रिक्स का उपयोग कर रहा है। क्या आपको ऐसा करने का कोई संकेत है? मैंने चार अंक लेने की कोशिश की है और 16 समीकरणों का निर्माण किया है (A '= A xu से बाहर), लेकिन यह काम नहीं करता: मुझे यकीन नहीं है कि मुझे जेड, जेड, डब्ल्यू और डब्ल्यू' गुणांक के रूप में उपयोग करना चाहिए …

निम्न चित्र से पता चलता है कि मैं क्या करना चाहता हूं:

एक कैरेट्रांसफोर्म 3 डी का उपयोग करते हुए एक चौकोर आकार में एक आयताकार छवि को ट्रांसफ़ॉर्म करना

यहां कुछ उदाहरण दिए गए हैं:

276.523, 236.438, 517.656, 208.945, 275.984, 331.285, 502.23, 292.344 261.441, 235.059, 515.09, 211.5, 263.555, 327.066, 500.734, 295 229.031, 161.277, 427.125, 192.562, 229.16, 226, 416.48, 256 

वेब के समाधान से एकत्रित समाधान "एक कैरेट्रांसफोर्म 3 डी का उपयोग करते हुए एक चौकोर आकार में एक आयताकार छवि को ट्रांसफ़ॉर्म करना"

मैंने आईओएस पर यह करने के लिए एक किट बनाया है: https://github.com/hfossli/AGGemometryKit/


सुनिश्चित करें कि आपका लंगर बिंदु शीर्ष बायां है ( CGPointZero )

 + (CATransform3D)rectToQuad:(CGRect)rect quadTL:(CGPoint)topLeft quadTR:(CGPoint)topRight quadBL:(CGPoint)bottomLeft quadBR:(CGPoint)bottomRight { return [self rectToQuad:rect quadTLX:topLeft.x quadTLY:topLeft.y quadTRX:topRight.x quadTRY:topRight.y quadBLX:bottomLeft.x quadBLY:bottomLeft.y quadBRX:bottomRight.x quadBRY:bottomRight.y]; } + (CATransform3D)rectToQuad:(CGRect)rect quadTLX:(CGFloat)x1a quadTLY:(CGFloat)y1a quadTRX:(CGFloat)x2a quadTRY:(CGFloat)y2a quadBLX:(CGFloat)x3a quadBLY:(CGFloat)y3a quadBRX:(CGFloat)x4a quadBRY:(CGFloat)y4a { CGFloat X = rect.origin.x; CGFloat Y = rect.origin.y; CGFloat W = rect.size.width; CGFloat H = rect.size.height; CGFloat y21 = y2a - y1a; CGFloat y32 = y3a - y2a; CGFloat y43 = y4a - y3a; CGFloat y14 = y1a - y4a; CGFloat y31 = y3a - y1a; CGFloat y42 = y4a - y2a; CGFloat a = -H*(x2a*x3a*y14 + x2a*x4a*y31 - x1a*x4a*y32 + x1a*x3a*y42); CGFloat b = W*(x2a*x3a*y14 + x3a*x4a*y21 + x1a*x4a*y32 + x1a*x2a*y43); CGFloat c = H*X*(x2a*x3a*y14 + x2a*x4a*y31 - x1a*x4a*y32 + x1a*x3a*y42) - H*W*x1a*(x4a*y32 - x3a*y42 + x2a*y43) - W*Y*(x2a*x3a*y14 + x3a*x4a*y21 + x1a*x4a*y32 + x1a*x2a*y43); CGFloat d = H*(-x4a*y21*y3a + x2a*y1a*y43 - x1a*y2a*y43 - x3a*y1a*y4a + x3a*y2a*y4a); CGFloat e = W*(x4a*y2a*y31 - x3a*y1a*y42 - x2a*y31*y4a + x1a*y3a*y42); CGFloat f = -(W*(x4a*(Y*y2a*y31 + H*y1a*y32) - x3a*(H + Y)*y1a*y42 + H*x2a*y1a*y43 + x2a*Y*(y1a - y3a)*y4a + x1a*Y*y3a*(-y2a + y4a)) - H*X*(x4a*y21*y3a - x2a*y1a*y43 + x3a*(y1a - y2a)*y4a + x1a*y2a*(-y3a + y4a))); CGFloat g = H*(x3a*y21 - x4a*y21 + (-x1a + x2a)*y43); CGFloat h = W*(-x2a*y31 + x4a*y31 + (x1a - x3a)*y42); CGFloat i = W*Y*(x2a*y31 - x4a*y31 - x1a*y42 + x3a*y42) + H*(X*(-(x3a*y21) + x4a*y21 + x1a*y43 - x2a*y43) + W*(-(x3a*y2a) + x4a*y2a + x2a*y3a - x4a*y3a - x2a*y4a + x3a*y4a)); const double kEpsilon = 0.0001; if(fabs(i) < kEpsilon) { i = kEpsilon* (i > 0 ? 1.0 : -1.0); } CATransform3D transform = {a/i, d/i, 0, g/i, b/i, e/i, 0, h/i, 0, 0, 1, 0, c/i, f/i, 0, 1.0}; return transform; } 

मैं इस कोड के लिए कोई क्रेडिट नहीं लेता है मैंने सभी को इंटरनेट पर दस्तक कर दिया था और एक साथ कई अपूर्ण जवाब दिए थे।

हम अंत में यह काम करने के लिए मिला है। हमने कई अलग-अलग तरीकों की कोशिश की है, लेकिन ज्यादातर असफल रहे हैं। और कुछ भी गैर पहचान मैट्रिक्स को पुनः प्राप्त कर रहे थे जब इनपुट और आउटपुट के रूप में समान अंक देते हैं (उदाहरण के लिए, केनीटीएम से एक … हमें वहां कुछ याद किया जाना चाहिए)।

निम्नलिखित के रूप में CATransform3D का उपयोग करना, हमें CATransform3D लेयर पर इस्तेमाल होने के लिए एक CATransform3D तैयार मिलता है:

 + (CATransform3D)transformQuadrilateral:(Quadrilateral)origin toQuadrilateral:(Quadrilateral)destination { CvPoint2D32f *cvsrc = [self openCVMatrixWithQuadrilateral:origin]; CvMat *src_mat = cvCreateMat( 4, 2, CV_32FC1 ); cvSetData(src_mat, cvsrc, sizeof(CvPoint2D32f)); CvPoint2D32f *cvdst = [self openCVMatrixWithQuadrilateral:destination]; CvMat *dst_mat = cvCreateMat( 4, 2, CV_32FC1 ); cvSetData(dst_mat, cvdst, sizeof(CvPoint2D32f)); CvMat *H = cvCreateMat(3,3,CV_32FC1); cvFindHomography(src_mat, dst_mat, H); cvReleaseMat(&src_mat); cvReleaseMat(&dst_mat); CATransform3D transform = [self transform3DWithCMatrix:H->data.fl]; cvReleaseMat(&H); return transform; } + (CvPoint2D32f *)openCVMatrixWithQuadrilateral:(Quadrilateral)origin { CvPoint2D32f *cvsrc = (CvPoint2D32f *)malloc(4*sizeof(CvPoint2D32f)); cvsrc[0].x = origin.upperLeft.x; cvsrc[0].y = origin.upperLeft.y; cvsrc[1].x = origin.upperRight.x; cvsrc[1].y = origin.upperRight.y; cvsrc[2].x = origin.lowerRight.x; cvsrc[2].y = origin.lowerRight.y; cvsrc[3].x = origin.lowerLeft.x; cvsrc[3].y = origin.lowerLeft.y; return cvsrc; } + (CATransform3D)transform3DWithCMatrix:(float *)matrix { CATransform3D transform = CATransform3DIdentity; transform.m11 = matrix[0]; transform.m21 = matrix[1]; transform.m41 = matrix[2]; transform.m12 = matrix[3]; transform.m22 = matrix[4]; transform.m42 = matrix[5]; transform.m14 = matrix[6]; transform.m24 = matrix[7]; transform.m44 = matrix[8]; return transform; } 

यहाँ एक नमूना प्रोजेक्ट है जो उपरोक्त hfossli के उत्तर से कोड लागू करता है और UIView पर एक श्रेणी बनाता है जो फ्रेम सेट करता है और एक कॉल में परिवर्तन लागू करता है:

https://github.com/joshrl/FreeTransform

UIView + चतुर्भुज कोड:

 #import <UIKit/UIKit.h> #import <QuartzCore/QuartzCore.h> @interface UIView (Quadrilateral) //Sets frame to bounding box of quad and applies transform - (void)transformToFitQuadTopLeft:(CGPoint)tl topRight:(CGPoint)tr bottomLeft:(CGPoint)bl bottomRight:(CGPoint)br; @end @implementation UIView (Quadrilateral) - (void)transformToFitQuadTopLeft:(CGPoint)tl topRight:(CGPoint)tr bottomLeft:(CGPoint)bl bottomRight:(CGPoint)br { NSAssert(CGPointEqualToPoint(self.layer.anchorPoint, CGPointZero),@"Anchor point must be (0,0)!"); CGRect boundingBox = [[self class] boundingBoxForQuadTR:tr tl:tl bl:bl br:br]; self.frame = boundingBox; CGPoint frameTopLeft = boundingBox.origin; CATransform3D transform = [[self class] rectToQuad:self.bounds quadTL:CGPointMake(tl.x-frameTopLeft.x, tl.y-frameTopLeft.y) quadTR:CGPointMake(tr.x-frameTopLeft.x, tr.y-frameTopLeft.y) quadBL:CGPointMake(bl.x-frameTopLeft.x, bl.y-frameTopLeft.y) quadBR:CGPointMake(br.x-frameTopLeft.x, br.y-frameTopLeft.y)]; self.layer.transform = transform; } + (CGRect)boundingBoxForQuadTR:(CGPoint)tr tl:(CGPoint)tl bl:(CGPoint)bl br:(CGPoint)br { CGRect boundingBox = CGRectZero; CGFloat xmin = MIN(MIN(MIN(tr.x, tl.x), bl.x),br.x); CGFloat ymin = MIN(MIN(MIN(tr.y, tl.y), bl.y),br.y); CGFloat xmax = MAX(MAX(MAX(tr.x, tl.x), bl.x),br.x); CGFloat ymax = MAX(MAX(MAX(tr.y, tl.y), bl.y),br.y); boundingBox.origin.x = xmin; boundingBox.origin.y = ymin; boundingBox.size.width = xmax - xmin; boundingBox.size.height = ymax - ymin; return boundingBox; } + (CATransform3D)rectToQuad:(CGRect)rect quadTL:(CGPoint)topLeft quadTR:(CGPoint)topRight quadBL:(CGPoint)bottomLeft quadBR:(CGPoint)bottomRight { return [self rectToQuad:rect quadTLX:topLeft.x quadTLY:topLeft.y quadTRX:topRight.x quadTRY:topRight.y quadBLX:bottomLeft.x quadBLY:bottomLeft.y quadBRX:bottomRight.x quadBRY:bottomRight.y]; } + (CATransform3D)rectToQuad:(CGRect)rect quadTLX:(CGFloat)x1a quadTLY:(CGFloat)y1a quadTRX:(CGFloat)x2a quadTRY:(CGFloat)y2a quadBLX:(CGFloat)x3a quadBLY:(CGFloat)y3a quadBRX:(CGFloat)x4a quadBRY:(CGFloat)y4a { CGFloat X = rect.origin.x; CGFloat Y = rect.origin.y; CGFloat W = rect.size.width; CGFloat H = rect.size.height; CGFloat y21 = y2a - y1a; CGFloat y32 = y3a - y2a; CGFloat y43 = y4a - y3a; CGFloat y14 = y1a - y4a; CGFloat y31 = y3a - y1a; CGFloat y42 = y4a - y2a; CGFloat a = -H*(x2a*x3a*y14 + x2a*x4a*y31 - x1a*x4a*y32 + x1a*x3a*y42); CGFloat b = W*(x2a*x3a*y14 + x3a*x4a*y21 + x1a*x4a*y32 + x1a*x2a*y43); CGFloat c = H*X*(x2a*x3a*y14 + x2a*x4a*y31 - x1a*x4a*y32 + x1a*x3a*y42) - H*W*x1a*(x4a*y32 - x3a*y42 + x2a*y43) - W*Y*(x2a*x3a*y14 + x3a*x4a*y21 + x1a*x4a*y32 + x1a*x2a*y43); CGFloat d = H*(-x4a*y21*y3a + x2a*y1a*y43 - x1a*y2a*y43 - x3a*y1a*y4a + x3a*y2a*y4a); CGFloat e = W*(x4a*y2a*y31 - x3a*y1a*y42 - x2a*y31*y4a + x1a*y3a*y42); CGFloat f = -(W*(x4a*(Y*y2a*y31 + H*y1a*y32) - x3a*(H + Y)*y1a*y42 + H*x2a*y1a*y43 + x2a*Y*(y1a - y3a)*y4a + x1a*Y*y3a*(-y2a + y4a)) - H*X*(x4a*y21*y3a - x2a*y1a*y43 + x3a*(y1a - y2a)*y4a + x1a*y2a*(-y3a + y4a))); CGFloat g = H*(x3a*y21 - x4a*y21 + (-x1a + x2a)*y43); CGFloat h = W*(-x2a*y31 + x4a*y31 + (x1a - x3a)*y42); CGFloat i = W*Y*(x2a*y31 - x4a*y31 - x1a*y42 + x3a*y42) + H*(X*(-(x3a*y21) + x4a*y21 + x1a*y43 - x2a*y43) + W*(-(x3a*y2a) + x4a*y2a + x2a*y3a - x4a*y3a - x2a*y4a + x3a*y4a)); const double kEpsilon = 0.0001; if(fabs(i) < kEpsilon) { i = kEpsilon* (i > 0 ? 1.0 : -1.0); } CATransform3D transform = {a/i, d/i, 0, g/i, b/i, e/i, 0, h/i, 0, 0, 1, 0, c/i, f/i, 0, 1.0}; return transform; } @end 

यहां छवि विवरण दर्ज करें

जोशआरएल के लिए 100% धन्यवाद के साथ, यहां जोशआरएल की कक्षा का स्विफ्ट संस्करण है।

यह पूरी तरह से और पूरी तरह से डीबग किया गया है। "स्विफ्ट" मुद्दे में "बहुत लंबा" ग्रस्त लाइनों को पुनर्संचित और विनाश परीक्षण किया गया है

यह उच्च मात्रा के उत्पादन में flawlessly काम कर रहा है। आशा है कि यह किसी को मदद करता है, कहीं न कहीं

उपयोग करना आसान नहीं हो सका। उदाहरण नीचे स्विफ्ट में कैसे उपयोग करना दिखा रहा है

2016 स्विफ्ट संस्करण … पूर्ण, काम, कॉपी और पेस्ट समाधान

 // JoshQuadView in Swift // from: https://stackoverflow.com/a/18606029/294884 // NB: JoshRL uses the ordering convention // "topleft, topright, bottomleft, bottomright" // which is different from "clockwise from topleft". // Note: is not meant to handle concave. import UIKit class JoshQuadView:UIView { func transformToFitQuadTopLeft(tl:CGPoint,tr:CGPoint,bl:CGPoint,br:CGPoint) { guard CGPointEqualToPoint(self.layer.anchorPoint, CGPointZero) else { print("suck");return } let b:CGRect = boundingBoxForQuadTR(tl, tr, bl, br) self.frame = b self.layer.transform = rectToQuad( self.bounds, CGPointMake(tl.xb.origin.x, tl.yb.origin.y), CGPointMake(tr.xb.origin.x, tr.yb.origin.y), CGPointMake(bl.xb.origin.x, bl.yb.origin.y), CGPointMake(br.xb.origin.x, br.yb.origin.y) ) } func boundingBoxForQuadTR( tl:CGPoint, _ tr:CGPoint, _ bl:CGPoint, _ br:CGPoint )->(CGRect) { var b:CGRect = CGRectZero let xmin:CGFloat = min(min(min(tr.x, tl.x), bl.x),br.x); let ymin:CGFloat = min(min(min(tr.y, tl.y), bl.y),br.y); let xmax:CGFloat = max(max(max(tr.x, tl.x), bl.x),br.x); let ymax:CGFloat = max(max(max(tr.y, tl.y), bl.y),br.y); b.origin.x = xmin b.origin.y = ymin b.size.width = xmax - xmin b.size.height = ymax - ymin return b; } func rectToQuad( rect:CGRect, _ topLeft:CGPoint, _ topRight:CGPoint, _ bottomLeft:CGPoint, _ bottomRight:CGPoint )->(CATransform3D) { return rectToQuad(rect, topLeft.x, topLeft.y, topRight.x, topRight.y, bottomLeft.x, bottomLeft.y, bottomRight.x, bottomRight.y) } func rectToQuad( rect:CGRect, _ x1a:CGFloat, _ y1a:CGFloat, _ x2a:CGFloat, _ y2a:CGFloat, _ x3a:CGFloat, _ y3a:CGFloat, _ x4a:CGFloat, _ y4a:CGFloat )->(CATransform3D) { let X = rect.origin.x; let Y = rect.origin.y; let W = rect.size.width; let H = 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 = -H*(x2a*x3a*y14 + x2a*x4a*y31 - x1a*x4a*y32 + x1a*x3a*y42); let b = W*(x2a*x3a*y14 + x3a*x4a*y21 + x1a*x4a*y32 + x1a*x2a*y43); // let c = H*X*(x2a*x3a*y14 + x2a*x4a*y31 - x1a*x4a*y32 + x1a*x3a*y42) - H*W*x1a*(x4a*y32 - x3a*y42 + x2a*y43) - W*Y*(x2a*x3a*y14 + x3a*x4a*y21 + x1a*x4a*y32 + x1a*x2a*y43); // Could be too long for Swift. Replaced with four lines: let c0 = -H*W*x1a*(x4a*y32 - x3a*y42 + x2a*y43) let cx = H*X*(x2a*x3a*y14 + x2a*x4a*y31 - x1a*x4a*y32 + x1a*x3a*y42) let cy = -W*Y*(x2a*x3a*y14 + x3a*x4a*y21 + x1a*x4a*y32 + x1a*x2a*y43) let c = c0 + cx + cy let d = H*(-x4a*y21*y3a + x2a*y1a*y43 - x1a*y2a*y43 - x3a*y1a*y4a + x3a*y2a*y4a); let e = W*(x4a*y2a*y31 - x3a*y1a*y42 - x2a*y31*y4a + x1a*y3a*y42); // let f = -(W*(x4a*(Y*y2a*y31 + H*y1a*y32) - x3a*(H + Y)*y1a*y42 + H*x2a*y1a*y43 + x2a*Y*(y1a - y3a)*y4a + x1a*Y*y3a*(-y2a + y4a)) - H*X*(x4a*y21*y3a - x2a*y1a*y43 + x3a*(y1a - y2a)*y4a + x1a*y2a*(-y3a + y4a))); // Is too long for Swift. Replaced with four lines: let f0 = -W*H*(x4a*y1a*y32 - x3a*y1a*y42 + x2a*y1a*y43) let fx = H*X*(x4a*y21*y3a - x2a*y1a*y43 - x3a*y21*y4a + x1a*y2a*y43) let fy = -W*Y*(x4a*y2a*y31 - x3a*y1a*y42 - x2a*y31*y4a + x1a*y3a*y42) let f = f0 + fx + fy let g = H*(x3a*y21 - x4a*y21 + (-x1a + x2a)*y43); let h = W*(-x2a*y31 + x4a*y31 + (x1a - x3a)*y42); // let i = W*Y*(x2a*y31 - x4a*y31 - x1a*y42 + x3a*y42) + H*(X*(-(x3a*y21) + x4a*y21 + x1a*y43 - x2a*y43) + W*(-(x3a*y2a) + x4a*y2a + x2a*y3a - x4a*y3a - x2a*y4a + x3a*y4a)); // Is too long for Swift. Replaced with four lines: let i0 = H*W*(x3a*y42 - x4a*y32 - x2a*y43) let ix = H*X*(x4a*y21 - x3a*y21 + x1a*y43 - x2a*y43) let iy = W*Y*(x2a*y31 - x4a*y31 - x1a*y42 + x3a*y42) var i = i0 + ix + iy let kEpsilon:CGFloat = 0.0001; if(fabs(i) < kEpsilon) { i = kEpsilon * (i > 0 ? 1.0 : -1.0); } 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) } } 

स्विफ्ट में उपयोग करने के लिए:

कहते हैं कि आपके पास एक कंटेनर दृश्य "QuadScreen" है

जिस दृश्य को आप खड़ा करना चाहते हैं उसे छोड़ें इस दृश्य में जोशक्वाड दृश्य होगा। उदाहरण में "jqv" यहां।

इस दृश्य में सीधे चार कॉर्नर-हैंडल (यानी, इमेज) डालकर, अपने हैंडल आइकन के पीएनजीज़ नीचे दिए गए कोड पूरी तरह से इन हैंडल्स को संभालता है; बस स्टोरीबोर्ड में उन्हें आसानी से सेट करने के लिए कोड में टिप्पणियों का पालन करें

खींचने के लिए यह सिर्फ एक कोड है:

 class QuadScreen:UIViewController { // sit your JoshQuadView in this view @IBOutlet var jqv:JoshQuadView! // simply have four small subview views, "handles" // with an icon on them (perhaps a small circle) // and put those over the four corners of the jqv // NOTE numbered CLOCKWISE from top left here: @IBOutlet var handle1:UIView! @IBOutlet var handle2:UIView! @IBOutlet var handle3:UIView! @IBOutlet var handle4:UIView! // put a pan recognizer on each handle, action goes to here // (for the pan recognizers, set cancels-in-view as needed // if you, example, highlight them on touch in their class) @IBAction func dragHandle(p:UIPanGestureRecognizer!) { let tr = p.translationInView(p.view) p.view!.center.x += tr.x p.view!.center.y += tr.y p.setTranslation(CGPointZero, inView: p.view) jqv.transformToFitQuadTopLeft( handle1.center, tr: handle2.center, bl: handle4.center, br: handle3.center ) // it's that simple, there's nothing else to do p.setTranslation(CGPointZero, inView: p.view) } override func viewDidLayoutSubviews() { // don't forget to do this....is critical. jqv.layer.anchorPoint = CGPointMake(0, 0) } 

एक जिज्ञासा के रूप में, और Google की खातिर, यह हास्यास्पद रूप से करने में आसान है

एंड्रॉयड

उनके पास पोलेट्स को नया रूप देने के लिए एक अंतर्निहित कमांड है इस उत्कृष्ट उत्तर में कॉपी और पेस्ट कोड है: https://stackoverflow.com/a/34667015/294884

आनन्द अंक स्वतंत्र समाधान:

मुझे वास्तव में @ जॉशल का जवाब मिलता है जहां वह एक श्रेणी "UIView + Quadrilateral" बनाता है जो ऊपर @ hfossli का सबसे उत्कृष्ट उत्तर का उपयोग करता है हालांकि, वर्ग को बदलने के लिए श्रेणी में कई कॉल विफल हो जाते हैं, और कोड को शीर्ष-बाएं रहने के लिए एंकरपॉइंट की आवश्यकता होती है।

मेरा समाधान (उनकी से प्राप्त):

  • किसी भी एंकरपॉइंट के लिए खाते
  • चतुर्भुज में परिवर्तन की अनुमति देता है

UIView + Quadrilateral.h :

 #import <UIKit/UIKit.h> #import <QuartzCore/QuartzCore.h> @interface UIView (Quadrilateral) //Sets frame to bounding box of quad and applies transform - (void)transformToFitQuadTopLeft:(CGPoint)tl topRight:(CGPoint)tr bottomLeft:(CGPoint)bl bottomRight:(CGPoint)br; @end 

यूआईवी्यू + चतुर्भुज। एम :

 #import "UIView+Quadrilateral.h" @implementation UIView (Quadrilateral) - (void)transformToFitQuadTopLeft:(CGPoint)tl topRight:(CGPoint)tr bottomLeft:(CGPoint)bl bottomRight:(CGPoint)br { CGRect boundingBox = [[self class] boundingBoxForQuadTR:tr tl:tl bl:bl br:br]; self.layer.transform = CATransform3DIdentity; // keeps current transform from interfering self.frame = boundingBox; CGPoint frameTopLeft = boundingBox.origin; CATransform3D transform = [[self class] rectToQuad:self.bounds quadTL:CGPointMake(tl.x-frameTopLeft.x, tl.y-frameTopLeft.y) quadTR:CGPointMake(tr.x-frameTopLeft.x, tr.y-frameTopLeft.y) quadBL:CGPointMake(bl.x-frameTopLeft.x, bl.y-frameTopLeft.y) quadBR:CGPointMake(br.x-frameTopLeft.x, br.y-frameTopLeft.y)]; // To account for anchor point, we must translate, transform, translate CGPoint anchorPoint = self.layer.position; CGPoint anchorOffset = CGPointMake(anchorPoint.x - boundingBox.origin.x, anchorPoint.y - boundingBox.origin.y); CATransform3D transPos = CATransform3DMakeTranslation(anchorOffset.x, anchorOffset.y, 0.); CATransform3D transNeg = CATransform3DMakeTranslation(-anchorOffset.x, -anchorOffset.y, 0.); CATransform3D fullTransform = CATransform3DConcat(CATransform3DConcat(transPos, transform), transNeg); // Now we set our transform self.layer.transform = fullTransform; } + (CGRect)boundingBoxForQuadTR:(CGPoint)tr tl:(CGPoint)tl bl:(CGPoint)bl br:(CGPoint)br { CGRect boundingBox = CGRectZero; CGFloat xmin = MIN(MIN(MIN(tr.x, tl.x), bl.x),br.x); CGFloat ymin = MIN(MIN(MIN(tr.y, tl.y), bl.y),br.y); CGFloat xmax = MAX(MAX(MAX(tr.x, tl.x), bl.x),br.x); CGFloat ymax = MAX(MAX(MAX(tr.y, tl.y), bl.y),br.y); boundingBox.origin.x = xmin; boundingBox.origin.y = ymin; boundingBox.size.width = xmax - xmin; boundingBox.size.height = ymax - ymin; return boundingBox; } + (CATransform3D)rectToQuad:(CGRect)rect quadTL:(CGPoint)topLeft quadTR:(CGPoint)topRight quadBL:(CGPoint)bottomLeft quadBR:(CGPoint)bottomRight { return [self rectToQuad:rect quadTLX:topLeft.x quadTLY:topLeft.y quadTRX:topRight.x quadTRY:topRight.y quadBLX:bottomLeft.x quadBLY:bottomLeft.y quadBRX:bottomRight.x quadBRY:bottomRight.y]; } + (CATransform3D)rectToQuad:(CGRect)rect quadTLX:(CGFloat)x1a quadTLY:(CGFloat)y1a quadTRX:(CGFloat)x2a quadTRY:(CGFloat)y2a quadBLX:(CGFloat)x3a quadBLY:(CGFloat)y3a quadBRX:(CGFloat)x4a quadBRY:(CGFloat)y4a { CGFloat X = rect.origin.x; CGFloat Y = rect.origin.y; CGFloat W = rect.size.width; CGFloat H = rect.size.height; CGFloat y21 = y2a - y1a; CGFloat y32 = y3a - y2a; CGFloat y43 = y4a - y3a; CGFloat y14 = y1a - y4a; CGFloat y31 = y3a - y1a; CGFloat y42 = y4a - y2a; CGFloat a = -H*(x2a*x3a*y14 + x2a*x4a*y31 - x1a*x4a*y32 + x1a*x3a*y42); CGFloat b = W*(x2a*x3a*y14 + x3a*x4a*y21 + x1a*x4a*y32 + x1a*x2a*y43); CGFloat c = H*X*(x2a*x3a*y14 + x2a*x4a*y31 - x1a*x4a*y32 + x1a*x3a*y42) - H*W*x1a*(x4a*y32 - x3a*y42 + x2a*y43) - W*Y*(x2a*x3a*y14 + x3a*x4a*y21 + x1a*x4a*y32 + x1a*x2a*y43); CGFloat d = H*(-x4a*y21*y3a + x2a*y1a*y43 - x1a*y2a*y43 - x3a*y1a*y4a + x3a*y2a*y4a); CGFloat e = W*(x4a*y2a*y31 - x3a*y1a*y42 - x2a*y31*y4a + x1a*y3a*y42); CGFloat f = -(W*(x4a*(Y*y2a*y31 + H*y1a*y32) - x3a*(H + Y)*y1a*y42 + H*x2a*y1a*y43 + x2a*Y*(y1a - y3a)*y4a + x1a*Y*y3a*(-y2a + y4a)) - H*X*(x4a*y21*y3a - x2a*y1a*y43 + x3a*(y1a - y2a)*y4a + x1a*y2a*(-y3a + y4a))); CGFloat g = H*(x3a*y21 - x4a*y21 + (-x1a + x2a)*y43); CGFloat h = W*(-x2a*y31 + x4a*y31 + (x1a - x3a)*y42); CGFloat i = W*Y*(x2a*y31 - x4a*y31 - x1a*y42 + x3a*y42) + H*(X*(-(x3a*y21) + x4a*y21 + x1a*y43 - x2a*y43) + W*(-(x3a*y2a) + x4a*y2a + x2a*y3a - x4a*y3a - x2a*y4a + x3a*y4a)); const double kEpsilon = 0.0001; if(fabs(i) < kEpsilon) { i = kEpsilon* (i > 0 ? 1.0 : -1.0); } CATransform3D transform = {a/i, d/i, 0, g/i, b/i, e/i, 0, h/i, 0, 0, 1, 0, c/i, f/i, 0, 1.0}; return transform; } @end 

उपरोक्त श्रेणी इतनी सरल और सुरुचिपूर्ण है, इसे प्रत्येक टूलबॉक्स में शामिल किया जाना चाहिए। उपरोक्त कोड के परम स्रोतों के लिए धन्यवाद। मुझे कोई क्रेडिट नहीं दिया जाना चाहिए

यदि आपका नया चतुर्भुज एक समानांतर चिन्ह है, तो इसे "कतरनी" कहा जाता है, और इसे सीएजीफीन ट्रांससंसफ़ के साथ सबसे आसानी से किया जा सकता है। जेफ लामर की उत्कृष्ट लेख देखें, सीजीएफ़ीन ट्रांसन्सफ़ॉर्म 1.1 ।

यदि आपका नया चतुर्भुज समांतरलोग्राम नहीं है, तो CATransform3D को लागू करने के लिए निम्न प्रश्न देखें: iPhone छवि खींच (तिरछा)