+ match_x1 = dst[0].x + scene_x; match_y1 = dst[0].y + scene_y;
+ match_x2 = dst[1].x + scene_x; match_y2 = dst[1].y + scene_y;
+ match_x3 = dst[2].x + scene_x; match_y3 = dst[2].y + scene_y;
+ match_x4 = dst[3].x + scene_x; match_y4 = dst[3].y + scene_y;
+}
+
+
+static double area(float x1, float y1, float x2, float y2,
+ float x3, float y3, float x4, float y4)
+{ // quadrelateral area, sign is +ccw,-cw, use abs
+ double dx1 = x3-x1, dy1 = y3-y1;
+ double dx2 = x4-x2, dy2 = y4-y2;
+ return 0.5 * (dx1 * dy2 - dx2 * dy1);
+}
+static double dist(float x1,float y1, float x2, float y2)
+{
+ double dx = x2-x1, dy = y2-y1;
+ return sqrt(dx*dx + dy*dy);
+}
+static int intersects(double x1, double y1, double x2, double y2,
+ double x3, double y3, double x4, double y4)
+{
+ double dx12 = x2 - x1, dy12 = y2 - y1;
+ double dx34 = x4 - x3, dy34 = y4 - y3;
+ double d = dx12*dy34 - dx34*dy12;
+ if( !d ) return 0; // parallel
+ double dx13 = x3 - x1, dy13 = y3 - y1;
+ double u = (dx13*dy34 - dx34*dy13) / d;
+ if( u < 0 || u > 1 ) return 0;
+ double v = (dx13*dy12 - dx12*dy13) / d;
+ if( v < 0 || v > 1 ) return 0;
+ return 1;
+}
+
+/*
+ * 4---------3 1---------2
+ * |0,h w,h| |0,0 w,0|
+ * | + | | + |
+ * |0,0 w,0| |0,h w,h|
+ * 1---------2 1---------2
+ * pt locations screen pts
+ */
+void FindObjMain::reshape()
+{
+ if( config.mode == MODE_NONE ) return;
+ const double pi = M_PI;
+ double x1 = match_x1, y1 = match_y1;
+ double x2 = match_x2, y2 = match_y2;
+ double x3 = match_x3, y3 = match_y3;
+ double x4 = match_x4, y4 = match_y4;
+ double ia = area(x1,y1, x2,y2, x3,y3, x4,y4);
+// centroid
+ double cx = (x1 + x2 + x3 + x4) / 4;
+ double cy = (y1 + y2 + y3 + y4) / 4;
+// centered
+ x1 -= cx; x2 -= cx; x3 -= cx; x4 -= cx;
+ y1 -= cy; y2 -= cy; y3 -= cy; y4 -= cy;
+// bowtied
+ if( intersects(x1,y1, x2,y2, x3,y3, x4,y4) ) {
+ double x = x2, y = y2;
+ x2 = x3; y2 = y3;
+ x3 = x; y3 = y;
+ }
+ else if( intersects(x1,y1, x4,y4, x3,y3, x2,y2) ) {
+ double x = x4, y = y4;
+ x4 = x3; y4 = y3;
+ x3 = x; y3 = y;
+ }
+
+// rotation, if mode is quad: reverse rotate
+ double r = 0;
+ if( (config.mode == MODE_QUADRILATERAL) ^ (config.rotate != 0) ) {
+// edge centers
+ double cx12 = (x1 + x2) / 2, cy12 = (y1 + y2) / 2;
+ double cx23 = (x2 + x3) / 2, cy23 = (y2 + y3) / 2;
+ double cx34 = (x3 + x4) / 2, cy34 = (y3 + y4) / 2;
+ double cx41 = (x4 + x1) / 2, cy41 = (y4 + y1) / 2;
+ double vx = cx34 - cx12, vy = cy34 - cy12;
+ double hx = cx23 - cx41, hy = cy23 - cy41;
+ double v = atan2(vy, vx);
+ double h = atan2(hy, hx);
+ r = (h + v - pi/2) / 2;
+ if( config.mode != MODE_QUADRILATERAL ) r = -r;
+ }
+// diagonal length
+ double a = dist(x1,y1, x3,y3) / 2;
+ double b = dist(x2,y2, x4,y4) / 2;
+ if( config.mode == MODE_SQUARE ||
+ config.mode == MODE_RECTANGLE )
+ a = b = (a + b) / 2;
+// central angles
+ double a1 = atan2(y1, x1);
+ double a2 = atan2(y2, x2);
+ double a3 = atan2(y3, x3);
+ double a4 = atan2(y4, x4);
+// edge angles
+ double a12 = a2 - a1, a23 = a3 - a2;
+ double a34 = a4 - a3, a41 = a1 - a4;
+ double dt = (a12 - a23 + a34 - a41)/4;
+// mirrored
+ if( ia < 0 ) { ia = -ia; dt = -dt; r = -r; }
+ switch( config.mode ) {
+ case MODE_SQUARE:
+ case MODE_RHOMBUS:
+ dt = pi/2;
+ case MODE_RECTANGLE:
+ case MODE_PARALLELOGRAM: {
+ double t = -(pi+dt)/2;
+ x1 = a*cos(t); y1 = a*sin(t); t += dt;
+ x2 = b*cos(t); y2 = b*sin(t); t += pi - dt;
+ x3 = a*cos(t); y3 = a*sin(t); t += dt;
+ x4 = b*cos(t); y4 = b*sin(t); }
+ case MODE_QUADRILATERAL:
+ break;
+ }
+// aspect
+ if( !config.aspect ) {
+ double cx12 = (x1 + x2) / 2, cy12 = (y1 + y2) / 2;
+ double cx23 = (x2 + x3) / 2, cy23 = (y2 + y3) / 2;
+ double cx34 = (x3 + x4) / 2, cy34 = (y3 + y4) / 2;
+ double cx41 = (x4 + x1) / 2, cy41 = (y4 + y1) / 2;
+ double iw = dist(cx41,cy41, cx23,cy23);
+ double ih = dist(cx12,cy12, cx34,cy34);
+ double ow = object_w, oh = object_h;
+ double sx = iw && ih ? sqrt((ih*ow)/(iw*oh)) : 1;
+ double sy = sx ? 1 / sx : 1;
+ x1 *= sx; x2 *= sx; x3 *= sx; x4 *= sx;
+ y1 *= sy; y2 *= sy; y3 *= sy; y4 *= sy;
+ }
+// rotation
+ if( r ) {
+ double ct = cos(r), st = sin(r), x, y;
+ x = x1*ct + y1*st; y = y1*ct - x1*st; x1 = x; y1 = y;
+ x = x2*ct + y2*st; y = y2*ct - x2*st; x2 = x; y2 = y;
+ x = x3*ct + y3*st; y = y3*ct - x3*st; x3 = x; y3 = y;
+ x = x4*ct + y4*st; y = y4*ct - x4*st; x4 = x; y4 = y;
+ }
+// scaling
+ ia = !config.scale ? object_w * object_h : ia;
+ double oa = abs(area(x1,y1, x2,y2, x3,y3, x4,y4));
+ double sf = oa ? sqrt(ia / oa) : 0;
+ x1 *= sf; x2 *= sf; x3 *= sf; x4 *= sf;
+ y1 *= sf; y2 *= sf; y3 *= sf; y4 *= sf;
+// translation
+ double ox = !config.translate ? object_x + object_w/2. : cx;
+ double oy = !config.translate ? object_y + object_h/2. : cy;
+ x1 += ox; x2 += ox; x3 += ox; x4 += ox;
+ y1 += oy; y2 += oy; y3 += oy; y4 += oy;
+
+ shape_x1 = x1; shape_y1 = y1;
+ shape_x2 = x2; shape_y2 = y2;
+ shape_x3 = x3; shape_y3 = y3;
+ shape_x4 = x4; shape_y4 = y4;