Translate VBA map into dart/flutter map - vba
I am trying to translate VBA to dart and am having trouble. I believe it has to do with how I implement my xxMap and wMap. How do I make maps with keys that have two integers, then how do I use it? I have been trying to fix this for a while and just cannot figure it out. I would greatly appreciate any help that anyone can offer me! I truly hope you all have a good day!
Here is the VBA code:
Public Function CBND(X As Double, y As Double, rho As Double) As Double
Dim i As Integer, ISs As Integer, LG As Integer, NG As Integer
Dim XX(10, 3) As Double, W(10, 3) As Double
Dim h As Double, k As Double, hk As Double, hs As Double, BVN As Double, Ass As Double, asr As Double, sn As Double
Dim A As Double, b As Double, bs As Double, c As Double, d As Double
Dim xs As Double, rs As Double
W(1, 1) = 0.17132449237917
XX(1, 1) = -0.932469514203152
W(2, 1) = 0.360761573048138
XX(2, 1) = -0.661209386466265
W(3, 1) = 0.46791393457269
XX(3, 1) = -0.238619186083197
W(1, 2) = 4.71753363865118E-02
XX(1, 2) = -0.981560634246719
W(2, 2) = 0.106939325995318
XX(2, 2) = -0.904117256370475
W(3, 2) = 0.160078328543346
XX(3, 2) = -0.769902674194305
W(4, 2) = 0.203167426723066
XX(4, 2) = -0.587317954286617
W(5, 2) = 0.233492536538355
XX(5, 2) = -0.36783149899818
W(6, 2) = 0.249147045813403
XX(6, 2) = -0.125233408511469
W(1, 3) = 1.76140071391521E-02
XX(1, 3) = -0.993128599185095
W(2, 3) = 4.06014298003869E-02
XX(2, 3) = -0.963971927277914
W(3, 3) = 6.26720483341091E-02
XX(3, 3) = -0.912234428251326
W(4, 3) = 8.32767415767048E-02
XX(4, 3) = -0.839116971822219
W(5, 3) = 0.10193011981724
XX(5, 3) = -0.746331906460151
W(6, 3) = 0.118194531961518
XX(6, 3) = -0.636053680726515
W(7, 3) = 0.131688638449177
XX(7, 3) = -0.510867001950827
W(8, 3) = 0.142096109318382
XX(8, 3) = -0.37370608871542
W(9, 3) = 0.149172986472604
XX(9, 3) = -0.227785851141645
W(10, 3) = 0.152753387130726
XX(10, 3) = -7.65265211334973E-02
If Abs(rho) < 0.3 Then
NG = 1
LG = 3
ElseIf Abs(rho) < 0.75 Then
NG = 2
LG = 6
Else
NG = 3
LG = 10
End If
h = -X
k = -y
hk = h * k
BVN = 0
If Abs(rho) < 0.925 Then
If Abs(rho) > 0 Then
hs = (h * h + k * k) / 2
asr = ArcSin(rho)
For i = 1 To LG
For ISs = -1 To 1 Step 2
sn = Sin(asr * (ISs * XX(i, NG) + 1) / 2)
BVN = BVN + W(i, NG) * Exp((sn * hk - hs) / (1 - sn * sn))
Next ISs
Next i
BVN = BVN * asr / (4 * Pi)
End If
BVN = BVN + CND(-h) * CND(-k)
Else
If rho < 0 Then
k = -k
hk = -hk
End If
If Abs(rho) < 1 Then
Ass = (1 - rho) * (1 + rho)
A = Sqr(Ass)
bs = (h - k) ^ 2
c = (4 - hk) / 8
d = (12 - hk) / 16
asr = -(bs / Ass + hk) / 2
If asr > -100 Then BVN = A * Exp(asr) * (1 - c * (bs - Ass) * (1 - d * bs / 5) / 3 + c * d * Ass * Ass / 5)
If -hk < 100 Then
b = Sqr(bs)
BVN = BVN - Exp(-hk / 2) * Sqr(2 * Pi) * CND(-b / A) * b * (1 - c * bs * (1 - d * bs / 5) / 3)
End If
A = A / 2
For i = 1 To LG
For ISs = -1 To 1 Step 2
xs = (A * (ISs * XX(i, NG) + 1)) ^ 2
rs = Sqr(1 - xs)
asr = -(bs / xs + hk) / 2
If asr > -100 Then
BVN = BVN + A * W(i, NG) * Exp(asr) * (Exp(-hk * (1 - rs) / (2 * (1 + rs))) / rs - (1 + c * xs * (1 + d * xs)))
End If
Next ISs
Next i
BVN = -BVN / (2 * Pi)
End If
If rho > 0 Then
BVN = BVN + CND(-Max(h, k))
Else
BVN = -BVN
If k > h Then BVN = BVN + CND(k) - CND(h)
End If
End If
CBND = BVN
End Function
Here is my dart/flutter translation:
import 'dart:math';
double cbnd (double X, double y, double rho) {
int i;
int iss;
int lg;
int ng;
double h;
double k;
double hk;
double hs;
double bvn;
double ass;
double asr;
double sn;
double a;
double b;
double bs;
double c;
double d;
double xs;
double rs;
Map<List<int>, double> wMap = {
[1, 1] : 0.17132449237917,
[2, 1] : 0.360761573048138,
[3, 1] : 0.46791393457269,
[1, 2] : 0.0471753363865118,
[2, 2] : 0.106939325995318,
[3, 2] : 0.160078328543346,
[4, 2] : 0.203167426723066,
[5, 2] : 0.233492536538355,
[6, 2] : 0.249147045813403,
[1, 3] : 0.0176140071391521,
[2, 3] : 0.0406014298003869,
[3, 3] : 0.0626720483341091,
[4, 3] : 0.0832767415767048,
[5, 3] : 0.10193011981724,
[6, 3] : 0.118194531961518,
[7, 3] : 0.131688638449177,
[8, 3] : 0.142096109318382,
[9, 3] : 0.149172986472604,
[10, 3] : 0.152753387130726,
};
Map<List<int>, double> xxMap = {
[1, 1] : -0.932469514203152,
[2, 1] : -0.661209386466265,
[3, 1] : -0.238619186083197,
[1, 2] : -0.981560634246719,
[2, 2] : -0.904117256370475,
[3, 2] : -0.769902674194305,
[4, 2] : -0.587317954286617,
[5, 2] : -0.36783149899818,
[6, 2] : -0.125233408511469,
[1, 3] : -0.993128599185095,
[2, 3] : -0.963971927277914,
[3, 3] : -0.912234428251326,
[4, 3] : -0.839116971822219,
[5, 3] : -0.746331906460151,
[6, 3] : -0.636053680726515,
[7, 3] : -0.510867001950827,
[8, 3] : -0.37370608871542,
[9, 3] : -0.227785851141645,
[10, 3] : -0.0765265211334973,
};
if (rho.abs() < 0.3) {
ng = 1;
lg = 3;
}
else if (rho.abs() < 0.75) {
ng = 2;
lg = 6;
}
else {
ng = 3;
lg = 10;
}
h = -X;
k = -y;
hk = h * k;
bvn = 0;
if (rho.abs() < 0.925) {
if (rho.abs() > 0) {
hs = (h * h + k * k) / 2;
asr = arcSin(rho);
for(i = 1; i < lg; i++) {
for(iss = -1; iss < 1; iss+=2) {
sn = sin(asr * (iss * xxMap[[i,ng]] + 1) / 2);
bvn = bvn + wMap[[i,ng]] * exp((sn * hk - hs) / (1 - sn * sn));
}
}
bvn = bvn * asr / (4 * pi);
}
bvn = bvn + cnd(-h) * cnd(-k);
}
else{
if (rho < 0) {
k = -k;
hk = -hk;
}
if (rho.abs() < 1) {
ass = (1 - rho) * (1 + rho);
a = sqrt(ass);
bs = pow((h - k), 2);
c = (4 - hk) / 8;
d = (12 - hk) / 16;
asr = -(bs / ass + hk) / 2;
if (asr > -100) {
bvn = a * exp(asr) * (1 - c * (bs - ass)
* (1 - d * bs / 5) / 3 + c * d * ass * ass / 5);
if (-hk < 100) {
b = sqrt(bs);
bvn = bvn - exp(-hk / 2) * sqrt(2 * pi) * cnd(-b / a)
* b * (1 - c * bs * (1 - d * bs / 5) / 3);
}
a = a / 2;
for(i = 1; i < lg; i++) {
for (iss = -1; iss < 1; iss+=2) {
xs = pow(a * (iss * xxMap[{i, ng}] +1), 2);
rs = sqrt(1 - xs);
asr = -(bs / xs + hk) / 2;
if (asr > -100) {
bvn = bvn + a * wMap[{i, ng}] * exp(asr)
* (exp(-hk * (1 - rs) / (2 * (1 + rs))) / rs
- (1 + c * xs * (1 + d * xs)));
}
}
}
bvn = - bvn / (2 * pi);
}
if (rho > 0) {
bvn = bvn + cnd(-max(h, k));
}
else {
bvn = -bvn;
if (k > h) {
bvn = bvn + cnd(k) - cnd(h);
}
}
}
}
print(bvn);
return bvn;
}
Here is the error code:
Performing hot restart...
Syncing files to device Android SDK built for x86...
Restarted application in 135ms.
I/flutter ( 7281): 0.6033458857722407
I/flutter ( 7281): 0.396061477681382
I/flutter ( 7281): 9588.900336837181
I/flutter ( 7281): 0.6066215038705733
I/flutter ( 7281): 0.39322784023367435
I/flutter ( 7281): 21.675664402433934
I/flutter ( 7281): 0.5567942331117398
I/flutter ( 7281): 0.43911123505550037
I/flutter ( 7281): 11.019478064121111
I/flutter ( 7281): 0.6067721597663256
I/flutter ( 7281): 0.3933784961294267
I/flutter ( 7281): 0.2265553776778987
I/flutter ( 7281): 0.5708243206704915
I/flutter ( 7281): 0.4261760665459637
I/flutter ( 7281): 0.1594404921802129
I/flutter ( 7281): 0.5331974688940583
I/flutter ( 7281): 0.4606874160295979
I/flutter ( 7281): 207.2825189948513
I/flutter ( 7281): 0.9045568943023813
E/flutter ( 7281): [ERROR:flutter/lib/ui/ui_dart_state.cc(177)] Unhandled Exception: NoSuchMethodError: The method '_mulFromInteger' was called on null.
E/flutter ( 7281): Receiver: null
E/flutter ( 7281): Tried calling: _mulFromInteger(-1)
E/flutter ( 7281): #0 Object.noSuchMethod (dart:core-patch/object_patch.dart:51:5)
E/flutter ( 7281): #1 int.* (dart:core-patch/integers.dart:16:38)
E/flutter ( 7281): #2 cbnd (package:flutter_apptest/main.dart:280:31)
E/flutter ( 7281): #3 ksi (package:flutter_apptest/main.dart:92:47)
E/flutter ( 7281): #4 bsAmericanCallApprox2002 (package:flutter_apptest/main.dart:57:67)
E/flutter ( 7281): #5 bsAmericanApprox2002 (package:flutter_apptest/main.dart:12:13)
E/flutter ( 7281): #6 main (package:flutter_apptest/main.dart:4:18)
E/flutter ( 7281): #7 _runMainZoned.<anonymous closure>.<anonymous closure> (dart:ui/hooks.dart:231:25)
E/flutter ( 7281): #8 _rootRun (dart:async/zone.dart:1190:13)
E/flutter ( 7281): #9 _CustomZone.run (dart:async/zone.dart:1093:19)
E/flutter ( 7281): #10 _runZoned (dart:async/zone.dart:1630:10)
E/flutter ( 7281): #11 runZonedGuarded (dart:async/zone.dart:1618:12)
E/flutter ( 7281): #12 _runMainZoned.<anonymous closure> (dart:ui/hooks.dart:223:5)
E/flutter ( 7281): #13 _startIsolate.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:301:19)
E/flutter ( 7281): #14 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:168:12)
E/flutter ( 7281):
You have typos in these two lines:
xs = pow(a * (iss * xxMap[{i, ng}] +1), 2);
...
bvn = bvn + a * wMap[{i, ng}] * exp(asr)
You are passing in a Set as the key when you meant to pass a List.
Simply change the {} to [] like so:
xs = pow(a * (iss * xxMap[[i, ng]] +1), 2);
...
bvn = bvn + a * wMap[[i, ng]] * exp(asr)
Related
Conversion ECEF XYZ to LLH (LAT/LONG/HEIGHT) and translation back - not accurate / possible error in IronPython script
I've modeled a 3D earth with gridpoints, as below: The points are represented in 3D space as XYZ coordinates. I then convert XYZ to Lat/Long/Height(elevation) based on the script I took from here: JSFiddle For some reason I got really strange results when trying to find XYZ of LLH not from my set, so I tried to verify the initial script by converting XYZ to LLH and then the same LLH back to XYZ to see if I get the same coordinate. Instead, the resulting coordinate is some XYZ on earth, unrelated to the original XYZ position. XYZ to LLH script: Source: JSFiddle def xyzllh(x,y,z): """ xyz vector to lat,lon,height output: llhvec[3] with components flat geodetic latitude in deg flon longitude in deg altkm altitude in km """ dtr = math.pi/180.0 rrnrm = [0.0] * 3 llhvec = [0.0] * 3 geodGBL() esq = EARTH_Esq rp = math.sqrt( x*x + y*y + z*z ) flatgc = math.asin( z / rp )/dtr testval= abs(x) + abs(y) if ( testval < 1.0e-10): flon = 0.0 else: flon = math.atan2( y,x )/dtr if (flon < 0.0 ): flon = flon + 360.0 p = math.sqrt( x*x + y*y ) # on pole special case if ( p < 1.0e-10 ): flat = 90.0 if ( z < 0.0 ): flat = -90.0 altkm = rp - rearth(flat) llhvec[0] = flat llhvec[1] = flon llhvec[2] = altkm return llhvec # first iteration, use flatgc to get altitude # and alt needed to convert gc to gd lat. rnow = rearth(flatgc) altkm = rp - rnow flat = gc2gd(flatgc,altkm) rrnrm = radcur(flat) rn = rrnrm[1] for x in range(5): slat = math.sin(dtr*flat) tangd = ( z + rn*esq*slat ) / p flatn = math.atan(tangd)/dtr dlat = flatn - flat flat = flatn clat = math.cos( dtr*flat ) rrnrm = radcur(flat) rn = rrnrm[1] altkm = (p/clat) - rn if ( abs(dlat) < 1.0e-12 ): break llhvec[0] = flat llhvec[1] = flon llhvec[2] = altkm return llhvec # globals EARTH_A = 0 EARTH_B = 0 EARTH_F = 0 EARTH_Ecc = 0 EARTH_Esq = 0 # starting function do_llhxyz() CallCount = 0 llh = [0.0] * 3 dtr = math.pi/180 CallCount = CallCount + 1 sans = " \n" llh = xyzllh(x,y,z) latitude = llh[0] longitude= llh[1] hkm = llh[2] height = 1000.0 * hkm latitude = fformat(latitude,5) longitude = fformat(longitude,5) height = fformat(height,1) sans = sans +"Latitude,Longitude, Height (ellipsoidal) from ECEF\n" sans = sans + "\n" sans = sans +"Latitude : " + str(latitude) + " deg N\n" sans = sans +"Longitude : " + str(longitude - 180) + " deg E\n" sans = sans +"Height : " + str(height) + " m\n" lats = [] longs = [] heights = [] lats.append(str(latitude)) longs.append(str(longitude - 180)) heights.append(str(height)) And this is the LLH to XYZ script: Source: www.mathworks.com a = 6378137 t = 8.1819190842622e-2 # (prime vertical radius of curvature) N = a / math.sqrt(1 - (t*t) * (math.sin(lat)*math.sin(lat))) x = [] y = [] z = [] # results: x.append( ((N+height) * math.cos(lat) * math.cos(long))/1000 ) y.append( ((N+height) * math.cos(lat) * math.sin(long))/1000 ) z.append( (((1-t*t) * N + height) * math.sin(lat))/1000 ) Anyone know what I'm doing wrong here? Thanks!
Accurately calculate moon phases
For a new project I like to calculate the moon phases. So far I haven't seen any code that does that. I don't want to rely on online-services for this. I have tried some functions, but they are not 100% reliable. Functions I have tried: NSInteger r = iYear % 100; r %= 19; if (r>9){ r -= 19;} r = ((r * 11) % 30) + iMonth + iDay; if (iMonth<3){r += 2;} r -= ((iYear<2000) ? 4 : 8.3); r = floor(r+0.5); other one: float n = floor(12.37 * (iYear -1900 + ((1.0 * iMonth - 0.5)/12.0))); float RAD = 3.14159265/180.0; float t = n / 1236.85; float t2 = t * t; float as = 359.2242 + 29.105356 * n; float am = 306.0253 + 385.816918 * n + 0.010730 * t2; float xtra = 0.75933 + 1.53058868 * n + ((1.178e-4) - (1.55e-7) * t) * t2; xtra = xtra + (0.1734 - 3.93e-4 * t) * sin(RAD * as) - 0.4068 * sin(RAD * am); float i = (xtra > 0.0 ? floor(xtra) : ceil(xtra - 1.0)); float j1 = [self julday:iYear iMonth:iMonth iDay:iDay]; float jd = (2415020 + 28 * n) + i; jd = fmodf((j1-jd + 30), 30); and last one NSInteger thisJD = [self julday:iYear iMonth:iMonth iDay:iDay]; float degToRad = 3.14159265 / 180; float K0, T, T2, T3, J0, F0, M0, M1, B1, oldJ = 0.0; K0 = floor((iYear-1900)*12.3685); T = (iYear-1899.5) / 100; T2 = T*T; T3 = T*T*T; J0 = 2415020 + 29*K0; F0 = 0.0001178*T2 - 0.000000155*T3 + (0.75933 + 0.53058868*K0) - (0.000837*T + 0.000335*T2); M0 = 360*[self getFrac:((K0*0.08084821133)) + 359.2242 - 0.0000333*T2 - 0.00000347*T3]; M1 = 360*[self getFrac:((K0*0.07171366128)) + 306.0253 + 0.0107306*T2 + 0.00001236*T3]; B1 = 360*[self getFrac:((K0*0.08519585128)) + 21.2964 - (0.0016528*T2) - (0.00000239*T3)]; NSInteger phase = 0; NSInteger jday = 0; while (jday < thisJD) { float F = F0 + 1.530588*phase; float M5 = (M0 + phase*29.10535608)*degToRad; float M6 = (M1 + phase*385.81691806)*degToRad; float B6 = (B1 + phase*390.67050646)*degToRad; F -= 0.4068*sin(M6) + (0.1734 - 0.000393*T)*sin(M5); F += 0.0161*sin(2*M6) + 0.0104*sin(2*B6); F -= 0.0074*sin(M5 - M6) - 0.0051*sin(M5 + M6); F += 0.0021*sin(2*M5) + 0.0010*sin(2*B6-M6); F += 0.5 / 1440; oldJ=jday; jday = J0 + 28*phase + floor(F); phase++; } float jd = fmodf((thisJD-oldJ), 30); All are working more and less, but none is really giving the correct dates of full moon for 2017 and 2018. Does anyone have a function that will calculate the moon phases correctly - also based on time zone? EDIT: I only want the function for the Moonphases. SwiftAA offers a lot more and only produces not needed overhead in the app.
Maya-like camera implementation
I am working on Maya-like camera implementation, and I've done track and dolly functions correctly but I just cannot implement tumble. I am working in PhiloGL engine (WebGL base), so I would really appreciate some help with code in this engine. I've looked at how Maya's camera actually work, but I cannot find out. Here is my code so-far if(mode == "rot") { var angleX = diffx / 150; var angleY = diffy / 150; //var angleZ = sign * Math.sqrt((diffx * diffx)+(diffy * diffy)) / 150; e.stop(); //axe Z //camera.position.x = x * Math.cos(angleX) - y * Math.sin(angleX); //camera.position.y = x * Math.sin(angleX) + y * Math.cos(angleX); //axe X //camera.position.y = y * Math.cos(angleY) - z * Math.sin(angleY); //camera.position.z = y * Math.sin(angleY) + z * Math.cos(angleY); //camera.update(); //axe Y camera.position.z = z * Math.cos(angleX) - x * Math.sin(angleX); camera.position.x = z * Math.sin(angleX) + x * Math.cos(angleX); camera.update(); position.x = e.x; position.y = e.y; position.z = e.z; } This isn't working nor do I know what am I doing wrong. Any clues?
I use this in inka3d (www.inka3d.com) but it does not depend on inka3d. The output is a 4x4 matrix. Can you make use of that? // turntable like camera, y is up-vector // tx, ty and tz are camera target position // rx, ry and rz are camera rotation angles (rad) // di is camera distance from target // fr is an array where the resulting view matrix is written into (16 values, row major) control.cameraY = function(tx, ty, tz, rx, ry, rz, di, fr) { var a = rx * 0.5; var b = ry * 0.5; var c = rz * 0.5; var d = Math.cos(a); var e = Math.sin(a); var f = Math.cos(b); var g = Math.sin(b); var h = Math.cos(c); var i = Math.sin(c); var j = f * e * h + g * d * i; var k = f * -e * i + g * d * h; var l = f * d * i - g * e * h; var m = f * d * h - g * -e * i; var n = j * j; var o = k * k; var p = l * l; var q = m * m; var r = j * k; var s = k * l; var t = j * l; var u = m * j; var v = m * k; var w = m * l; var x = q + n - o - p; var y = (r + w) * 2.0; var z = (t - v) * 2.0; var A = (r - w) * 2.0; var B = q - n + o - p; var C = (s + u) * 2.0; var D = (t + v) * 2.0; var E = (s - u) * 2.0; var F = q - n - o + p; var G = di; var H = -(tx + D * G); var I = -(ty + E * G); var J = -(tz + F * G); fr[0] = x; fr[1] = A; fr[2] = D; fr[3] = 0.0; fr[4] = y; fr[5] = B; fr[6] = E; fr[7] = 0.0; fr[8] = z; fr[9] = C; fr[10] = F; fr[11] = 0.0; fr[12] = x * H + y * I + z * J; fr[13] = A * H + B * I + C * J; fr[14] = D * H + E * I + F * J; fr[15] = 1.0; };
missing value where TRUE/FALSE needed
I'm working on pairs trading data and following function should give total.profit with value "k". optimal.k = function (k) { u = m + k * s l = m - k * s profit = 0 profit = 0 total.profit = 0 i = 1 p = 0.001 while ( i <= length(r) ) { if ( r[i] >= u ) { buy.unit = 1/East$Close[i] sell.unit = 1/South$Close[i] if ( i == length(r) ) { buy.price = buy.unit * East$Close[i] sell.price = sell.unit * South$Close[i] profit = sell.price - buy.price costs = (sell.price + buy.price) * p total.profit = total.profit + profit - costs break } while ( r[i] > m ) { #################################### here i = i + 1 } buy.price = buy.unit * East$Close[i] sell.price = sell.unit * South$Close[i] profit = sell.price - buy.price costs = (sell.price + buy.price) * p total.profit = total.profit + profit - costs } if ( r[i] <= l ) { buy.unit = 1/South$Close[i] sell.unit = 1/East$Close[i] if ( i == length(r) ) { buy.price = buy.unit * South$Close[i] sell.price = sell.unit * East$Close[i] profit = sell.price - buy.price costs = (sell.price + buy.price) * p total.profit = total.profit + profit - costs break } while ( r[i] < m ) { i = i + 1 } buy.price = buy.unit * East$Close[i] sell.price = sell.unit * South$Close[i] profit = sell.price - buy.price costs = (sell.price + buy.price) * p total.profit = total.profit + profit - costs } if ( i == length(r) ) stop i = i + 1 } print(total.profit) } If I run the function, I get this error message. optimal.k(1) Error in while (r[i] > m) { : missing value where TRUE/FALSE needed I don't get it why (r[i] > m) is NA Does anyone know why it occurs?
Return CATransform3D to map quadrilateral to quadrilateral
I'm trying to derive a CATransform3D that will map a quad with 4 corner points to another quad with 4 new corner points. I've spent a little bit of time researching this and it seems the steps involve converting the original Quad to a Square, and then converting that Square to the new Quad. My methods look like this (code borrowed from here): - (CATransform3D)quadFromSquare_x0:(float)x0 y0:(float)y0 x1:(float)x1 y1:(float)y1 x2:(float)x2 y2:(float)y2 x3:(float)x3 y3:(float)y3 { float dx1 = x1 - x2, dy1 = y1 - y2; float dx2 = x3 - x2, dy2 = y3 - y2; float sx = x0 - x1 + x2 - x3; float sy = y0 - y1 + y2 - y3; float g = (sx * dy2 - dx2 * sy) / (dx1 * dy2 - dx2 * dy1); float h = (dx1 * sy - sx * dy1) / (dx1 * dy2 - dx2 * dy1); float a = x1 - x0 + g * x1; float b = x3 - x0 + h * x3; float c = x0; float d = y1 - y0 + g * y1; float e = y3 - y0 + h * y3; float f = y0; CATransform3D mat; mat.m11 = a; mat.m12 = b; mat.m13 = 0; mat.m14 = c; mat.m21 = d; mat.m22 = e; mat.m23 = 0; mat.m24 = f; mat.m31 = 0; mat.m32 = 0; mat.m33 = 1; mat.m34 = 0; mat.m41 = g; mat.m42 = h; mat.m43 = 0; mat.m44 = 1; return mat; } - (CATransform3D)squareFromQuad_x0:(float)x0 y0:(float)y0 x1:(float)x1 y1:(float)y1 x2:(float)x2 y2:(float)y2 x3:(float)x3 y3:(float)y3 { CATransform3D mat = [self quadFromSquare_x0:x0 y0:y0 x1:x1 y1:y1 x2:x2 y2:y2 x3:x3 y3:y3]; // invert through adjoint float a = mat.m11, d = mat.m21, /* ignore */ g = mat.m41; float b = mat.m12, e = mat.m22, /* 3rd col*/ h = mat.m42; /* ignore 3rd row */ float c = mat.m14, f = mat.m24; float A = e - f * h; float B = c * h - b; float C = b * f - c * e; float D = f * g - d; float E = a - c * g; float F = c * d - a * f; float G = d * h - e * g; float H = b * g - a * h; float I = a * e - b * d; // Probably unnecessary since 'I' is also scaled by the determinant, // and 'I' scales the homogeneous coordinate, which, in turn, // scales the X,Y coordinates. // Determinant = a * (e - f * h) + b * (f * g - d) + c * (d * h - e * g); float idet = 1.0f / (a * A + b * D + c * G); mat.m11 = A * idet; mat.m21 = D * idet; mat.m31 = 0; mat.m41 = G * idet; mat.m12 = B * idet; mat.m22 = E * idet; mat.m32 = 0; mat.m42 = H * idet; mat.m13 = 0 ; mat.m23 = 0 ; mat.m33 = 1; mat.m43 = 0 ; mat.m14 = C * idet; mat.m24 = F * idet; mat.m34 = 0; mat.m44 = I * idet; return mat; } After calculating both matrices, multiplying them together, and assigning to the view in question, I end up with a transformed view, but it is wildly incorrect. In fact, it seems to be sheared like a parallelogram no matter what I do. What am I missing? UPDATE 2/1/12 It seems the reason I'm running into issues may be that I need to accommodate for FOV and focal length into the model view matrix (which is the only matrix I can alter directly in Quartz.) I'm not having any luck finding documentation online on how to calculate the proper matrix, though.
I was able to achieve this by porting and combining the quad warping and homography code from these two URLs: http://forum.openframeworks.cc/index.php/topic,509.30.html http://forum.openframeworks.cc/index.php?topic=3121.15 UPDATE: I've open sourced a small class that does this: https://github.com/dominikhofmann/DHWarpView