/******************* TO DO 5 ********************* * BlendImages: * INPUT: * ipv: list of input images and their relative positions in the mosaic * blendWidth: width of the blending function * OUTPUT: * create & return final mosaic by blending all images * and correcting for any vertical drift */ CByteImage BlendImages(CImagePositionV& ipv, float blendWidth) { // Assume all the images are of the same shape (for now) CByteImage& img0 = ipv[0].img; CShape sh = img0.Shape(); int width = sh.width; int height = sh.height; int nBands = sh.nBands; int dim[2] = {width, height}; // Compute the bounding box for the mosaic int n = ipv.size(); float min_x = 0, min_y = 0; float max_x = 0, max_y = 0; int i; float dy = 0; for (i = 0; i < n; i++) { CTransform3x3 &pos = ipv[i].position; CVector3 corners[4];//表示图片的4个角的坐标,分别为左下,右下,左上,右上 corners[0][0] = 0.0; corners[0][1] = 0.0; corners[0][2] = 1.0; corners[1][0] = width - 1; corners[1][1] = 0.0; corners[1][2] = 1.0; corners[2][0] = 0.0; corners[2][1] = height - 1; corners[2][2] = 1.0; corners[3][0] = width - 1; corners[3][1] = height - 1; corners[3][2] = 1.0; corners[0] = pos * corners[0]; corners[1] = pos * corners[1]; corners[2] = pos * corners[2]; corners[3] = pos * corners[3]; corners[0][0] /= corners[0][2]; corners[0][1] /= corners[0][2]; corners[1][0] /= corners[0][2]; corners[1][1] /= corners[0][2]; corners[2][0] /= corners[0][2]; corners[2][1] /= corners[0][2]; corners[3][0] /= corners[0][2]; corners[3][1] /= corners[0][2]; // *** BEGIN TODO #1 *** // add some code here to update min_x, ..., max_y //Use c0 and c3 to get the range of x and y. int iminx, iminy, imaxx, imaxy; ImageBoundingBox(img0, pos, iminx, iminy, imaxx, imaxy); if (i == 0) { dy += imaxy; } if (i == n - 1) { dy -= imaxy; } /*if (min_x > corners[0][0]) { min_x = corners[0][0]; } if (max_x < corners[3][0]) { max_x = corners[3][0]; } if (min_y > corners[0][1]) { min_y = corners[0][1]; } if (max_y < corners[3][1]) { max_y = corners[3][1]; } */ min_x = min(min_x, float(iminx)); min_y = min(min_y, float(iminy)); max_x = max(max_x, float(imaxx)); max_y = max(max_y, float(imaxy)); // *** END TODO #1 *** } // Create a floating point accumulation image CShape mShape((int)(ceil(max_x) - floor(min_x)), (int)(ceil(max_y) - floor(min_y)), nBands); CFloatImage accumulator(mShape); accumulator.ClearPixels(); double x_init, x_final; double y_init, y_final; // Add in all of the images for (i = 0; i < n; i++) { CTransform3x3 &M = ipv[i].position; CTransform3x3 M_t = CTransform3x3::Translation(-min_x, -min_y) * M; CByteImage& img = ipv[i].img; // Perform the accumulation AccumulateBlend(img, accumulator, M_t, blendWidth); if (i == 0) { CVector3 p; p[0] = 0.5 * width; p[1] = 0.0; p[2] = 1.0; p = M_t * p; x_init = p[0]; y_init = p[1]; } else if (i == n - 1) { CVector3 p; p[0] = 0.5 * width; p[1] = 0.0; p[2] = 1.0; p = M_t * p; x_final = p[0]; y_final = p[1]; } } // Normalize the results CByteImage compImage(mShape); NormalizeBlend(accumulator, compImage); bool debug_comp = false; if (debug_comp) WriteFile(compImage, "tmp_comp.tga"); // Allocate the final image shape CShape cShape(mShape.width - width, height, nBands); CByteImage croppedImage(cShape); // Compute the affine deformation CTransform3x3 A = CTransform3x3(); // *** BEGIN TODO #2 *** // fill in the right entries in A to trim the left edge and // to take out the vertical drift A[0][2] = width /2; A[1][0] = dy / (mShape.width - width); // *** END TODO #2 *** // Warp and crop the composite WarpGlobal(compImage, croppedImage, A, eWarpInterpLinear); // WarpGlobal(compImage, croppedImage, A, eWarpInterpNearest); //similar as linear // WarpGlobal(compImage, croppedImage, A, eWarpInterpCubic); //all pixels are black return croppedImage; }
void BeamContact2Dp::ComputeB(void) // this function computes the finite element equation vectors Bn and Bs { double Ka1n; double Kb1n; double Ka1g; double Kb1g; Vector a1(BC2D_NUM_DIM); Vector b1(BC2D_NUM_DIM); // initialize Bn and Bs mBn.Zero(); mBs.Zero(); // get tangent vectors a1 = Geta1(); b1 = Getb1(); // compute terms for vector Bn Ka1n = (mEyeS*a1)^mNormal; Kb1n = (mEyeS*b1)^mNormal; mBn(0) = -mShape(0)*mNormal(0); mBn(1) = -mShape(0)*mNormal(1); mBn(2) = -mShape(1)*mLength*Ka1n; mBn(3) = -mShape(2)*mNormal(0); mBn(4) = -mShape(2)*mNormal(1); mBn(5) = -mShape(3)*mLength*Kb1n; mBn(6) = mNormal(0); mBn(7) = mNormal(1); // compute terms for vector Bs Ka1g = (mEyeS*a1)^mg_xi; Kb1g = (mEyeS*b1)^mg_xi; mBs(0) = -mg_xi(0)*(mShape(0) + mRadius*mDshape(0)); mBs(1) = -mg_xi(1)*(mShape(0) + mRadius*mDshape(0)); mBs(2) = -Ka1g*mLength*(mShape(1) + mRadius*mDshape(1)); mBs(3) = -mg_xi(0)*(mShape(2) + mRadius*mDshape(2)); mBs(4) = -mg_xi(1)*(mShape(2) + mRadius*mDshape(2)); mBs(5) = -Kb1g*mLength*(mShape(3) + mRadius*mDshape(3)); mBs(6) = mg_xi(0); mBs(7) = mg_xi(1); return; }
double BeamContact2Dp::Project(double xi) // this function computes the centerline projection for the current step { double xi_p; double H1; double H2; double H3; double H4; double dH1; double dH2; double dH3; double dH4; double R; double DR; double dxi; Vector a1(BC2D_NUM_DIM); Vector b1(BC2D_NUM_DIM); Vector x_c_p(BC2D_NUM_DIM); Vector t_c(BC2D_NUM_DIM); Vector ddx_c(BC2D_NUM_DIM); // initialize to previous projection location xi_p = xi; // update end point tangents UpdateEndFrames(); // set tangent vectors a1 = Geta1(); b1 = Getb1(); // Hermitian basis functions and first derivatives H1 = 1.0 - 3.0*xi_p*xi_p + 2.0*xi_p*xi_p*xi_p; H2 = xi_p - 2.0*xi_p*xi_p + xi_p*xi_p*xi_p; H3 = 3.0*xi_p*xi_p - 2*xi_p*xi_p*xi_p; H4 = -xi_p*xi_p + xi_p*xi_p*xi_p; dH1 = -6.0*xi_p + 6.0*xi_p*xi_p; dH2 = 1.0 - 4.0*xi_p + 3.0*xi_p*xi_p; dH3 = 6.0*xi_p - 6.0*xi_p*xi_p; dH4 = -2.0*xi_p + 3.0*xi_p*xi_p; // compute current projection coordinate and tangent x_c_p = mDcrd_a*H1 + a1*mLength*H2 + mDcrd_b*H3 + b1*mLength*H4; t_c = mDcrd_a*dH1 + a1*mLength*dH2 + mDcrd_b*dH3 + b1*mLength*dH4; // compute initial value of residual R = (mDcrd_s - x_c_p)^t_c; // iterate to determine new value of xi int Gapcount = 0; while (fabs(R/mLength) > 1.0e-10 && Gapcount < 50) { // compute current curvature vector ddx_c = Get_dxc_xixi(xi_p); // increment projection location DR = ((mDcrd_s - x_c_p)^ddx_c) - (t_c^t_c); dxi = -R/DR; xi_p = xi_p + dxi; // Hermitian basis functions and first derivatives H1 = 1.0 - 3.0*xi_p*xi_p + 2.0*xi_p*xi_p*xi_p; H2 = xi_p - 2.0*xi_p*xi_p + xi_p*xi_p*xi_p; H3 = 3.0*xi_p*xi_p - 2*xi_p*xi_p*xi_p; H4 = -xi_p*xi_p + xi_p*xi_p*xi_p; dH1 = -6.0*xi_p + 6.0*xi_p*xi_p; dH2 = 1.0 - 4.0*xi_p + 3.0*xi_p*xi_p; dH3 = 6.0*xi_p - 6.0*xi_p*xi_p; dH4 = -2.0*xi_p + 3.0*xi_p*xi_p; // update projection coordinate and tangent x_c_p = mDcrd_a*H1 + a1*mLength*H2 + mDcrd_b*H3 + b1*mLength*H4; t_c = mDcrd_a*dH1 + a1*mLength*dH2 + mDcrd_b*dH3 + b1*mLength*dH4; // compute residual R = (mDcrd_s - x_c_p)^t_c; Gapcount += 1; } // update normal vector for current projection mNormal = (mDcrd_s - x_c_p)/((mDcrd_s - x_c_p).Norm()); // update Hermitian basis functions and derivatives mShape(0) = H1; mShape(1) = H2; mShape(2) = H3; mShape(3) = H4; mDshape(0) = dH1; mDshape(1) = dH2; mDshape(2) = dH3; mDshape(3) = dH4; return xi_p; }
int BeamContact2Dp::update(void) // this function updates variables for an incremental step n to n+1 { double tensileStrength; Vector a1(BC2D_NUM_DIM); Vector b1(BC2D_NUM_DIM); Vector a1_n(BC2D_NUM_DIM); Vector b1_n(BC2D_NUM_DIM); Vector disp_a(3); Vector disp_b(3); Vector disp_L(BC2D_NUM_DIM); double rot_a; double rot_b; Vector x_c(BC2D_NUM_DIM); // update slave node coordinates mDcrd_s = mIcrd_s + theNodes[2]->getTrialDisp(); // update nodal coordinates disp_a = theNodes[0]->getTrialDisp(); disp_b = theNodes[1]->getTrialDisp(); for (int i = 0; i < 2; i++) { mDcrd_a(i) = mIcrd_a(i) + disp_a(i); mDcrd_b(i) = mIcrd_b(i) + disp_b(i); } // compute incremental rotation from step n to step n+1 rot_a = disp_a(2) - mDisp_a_n(2); rot_b = disp_b(2) - mDisp_b_n(2); // get tangent vectors from last converged step a1_n = Geta1(); b1_n = Getb1(); // linear update of tangent vectors a1 = a1_n + rot_a*mEyeS*a1_n; b1 = b1_n + rot_b*mEyeS*b1_n; // update centerline projection coordinate x_c = mDcrd_a*mShape(0) + a1*mLength*mShape(1) + mDcrd_b*mShape(2) + b1*mLength*mShape(3); // update penetration function mGap = (mNormal^(mDcrd_s - x_c)) - mRadius; if (mGap < 0.0 && in_bounds) { inContact = true; } else { mGap = 0.0; inContact = false; } // update normal contact force if (was_inContact) { mLambda = mPenalty*mGap; } else { mLambda = 0.0; } // get tensile strength from contact material tensileStrength = theMaterial->getTensileStrength(); // determine trial strain vector based on contact state if (inContact) { Vector strain(3); double slip; Vector c1n1(2); Vector c2n1(2); // tangent at the centerline projection in step n+1 c1n1 = mDshape(0)*mDcrd_a + mDshape(1)*mLength*ma_1 + mDshape(2)*mDcrd_b + mDshape(3)*mLength*mb_1; // update vector c2 for step n+1 c2n1 = (mDcrd_s - x_c)/((mDcrd_s - x_c).Norm()); // update vector c2 for step n+1 c2n1(0) = -c1n1(1); c2n1(1) = c1n1(0); // compute the slip slip = mg_xi^(mDcrd_s - x_c - mrho*c2n1); // set the strain vector strain(0) = mGap; strain(1) = slip; strain(2) = -mLambda; theMaterial->setTrialStrain(strain); } else { Vector strain(3); // set the strain vector strain(0) = mGap; strain(1) = 0.0; strain(2) = -mLambda; theMaterial->setTrialStrain(strain); } return 0; }
void BeamContact2Dp::setDomain(Domain *theDomain) { Vector x_c(BC2D_NUM_DIM); mEye1.Zero(); mEye1(0,0) = 1.0; mEye1(1,1) = 1.0; mEyeS.Zero(); mEyeS(0,1) = -1.0; mEyeS(1,0) = 1.0; theNodes[0] = theDomain->getNode(mExternalNodes(0)); theNodes[1] = theDomain->getNode(mExternalNodes(1)); theNodes[2] = theDomain->getNode(mExternalNodes(2)); for (int i = 0; i < 3; i++) { if (theNodes[i] == 0) return; // don't go any further - otherwise segmentation fault } // initialize coordinate vectors mIcrd_a = theNodes[0]->getCrds(); mIcrd_b = theNodes[1]->getCrds(); mIcrd_s = theNodes[2]->getCrds(); mDcrd_a = mIcrd_a; mDcrd_b = mIcrd_b; mDcrd_s = mIcrd_s; mDisp_a_n.Zero(); mDisp_b_n.Zero(); // length of beam element mLength = (mDcrd_b - mDcrd_a).Norm(); // initialize tangent vectors at beam nodes ma_1 = (mDcrd_b - mDcrd_a)/mLength; mb_1 = ma_1; // perform projection of slave node to beam centerline mXi = ((mDcrd_b - mDcrd_s)^(mDcrd_b - mDcrd_a))/mLength; // initial assumption mXi = Project(mXi); // actual location // update contact state based on projection in_bounds = ((mXi > 0.000) && (mXi < 1.000)); inContact = (was_inContact && in_bounds); // centerline projection coordinate x_c = mDcrd_a*mShape(0) + ma_1*mLength*mShape(1) + mDcrd_b*mShape(2) + mb_1*mLength*mShape(3); // update surface tangent vector, g_xi UpdateBase(mXi); // adjust cohesion force theMaterial->ScaleCohesion(mLength); theMaterial->ScaleTensileStrength(mLength); // compute vectors Bn and Bs ComputeB(); // call the base class method this->DomainComponent::setDomain(theDomain); }
/******************* TO DO 5 ********************* * BlendImages: * INPUT: * ipv: list of input images and their relative positions in the mosaic * blendWidth: width of the blending function * OUTPUT: * create & return final mosaic by blending all images * and correcting for any vertical drift */ CByteImage BlendImages(CImagePositionV& ipv, float blendWidth) { // Assume all the images are of the same shape (for now) CByteImage& img0 = ipv[0].img; CShape sh = img0.Shape(); int width = sh.width; int height = sh.height; int nBands = sh.nBands; // int dim[2] = {width, height}; int n = ipv.size(); if (n == 0) return CByteImage(0,0,1); bool is360 = false; // Hack to detect if this is a 360 panorama if (ipv[0].imgName == ipv[n-1].imgName) is360 = true; // Compute the bounding box for the mosaic float min_x = FLT_MAX, min_y = FLT_MAX; float max_x = 0, max_y = 0; int i; for (i = 0; i < n; i++) { CTransform3x3 &T = ipv[i].position; // BEGIN TODO // add some code here to update min_x, ..., max_y printf("TODO: %s:%d\n", __FILE__, __LINE__); // END TODO } // Create a floating point accumulation image CShape mShape((int)(ceil(max_x) - floor(min_x)), (int)(ceil(max_y) - floor(min_y)), nBands + 1); CFloatImage accumulator(mShape); accumulator.ClearPixels(); double x_init, x_final; double y_init, y_final; // Add in all of the images for (i = 0; i < n; i++) { // Compute the sub-image involved CTransform3x3 &M = ipv[i].position; CTransform3x3 M_t = CTransform3x3::Translation(-min_x, -min_y) * M; CByteImage& img = ipv[i].img; // Perform the accumulation AccumulateBlend(img, accumulator, M_t, blendWidth); if (i == 0) { CVector3 p; p[0] = 0.5 * width; p[1] = 0.0; p[2] = 1.0; p = M_t * p; x_init = p[0]; y_init = p[1]; } else if (i == n - 1) { CVector3 p; p[0] = 0.5 * width; p[1] = 0.0; p[2] = 1.0; p = M_t * p; x_final = p[0]; y_final = p[1]; } } // Normalize the results mShape = CShape((int)(ceil(max_x) - floor(min_x)), (int)(ceil(max_y) - floor(min_y)), nBands); CByteImage compImage(mShape); NormalizeBlend(accumulator, compImage); bool debug_comp = false; if (debug_comp) WriteFile(compImage, "tmp_comp.tga"); // Allocate the final image shape int outputWidth = 0; if (is360) { outputWidth = mShape.width - width; } else { outputWidth = mShape.width; } CShape cShape(outputWidth, mShape.height, nBands); CByteImage croppedImage(cShape); // Compute the affine transformation CTransform3x3 A = CTransform3x3(); // identify transform to initialize // BEGIN TODO // fill in appropriate entries in A to trim the left edge and // to take out the vertical drift if this is a 360 panorama // (i.e. is360 is true) printf("TODO: %s:%d\n", __FILE__, __LINE__); // END TODO // Warp and crop the composite WarpGlobal(compImage, croppedImage, A, eWarpInterpLinear); return croppedImage; }