예제 #1
0
void ossimNitfProjectionFactory::computeScaleInMeters(
   const ossimNitfImageHeader* hdr,
   const std::vector<ossimDpt>& dpts,
   ossimDpt& scale) const
{
   if ( !hdr || isSkewed(dpts))
   {
      scale.makeNan();
      return;
   }
   ossimIrect imageRect = hdr->getImageRect();

   //---
   // Calculate the scale.  This assumes that the corner points are for the
   // edge of the corner pixels, not the center of the corner pixels.
   //---
   double eastingSize  = 0.0;
   double northingSize = 0.0;
   
   eastingSize  = fabs(dpts[1].x - dpts[0].x);
   northingSize = fabs(dpts[0].y - dpts[3].y);

   double rows = imageRect.height();//hdr->getNumberOfRows();
   double cols = imageRect.width();//hdr->getNumberOfCols();

   if (!rows || !cols)
   {
      scale.makeNan();
      return;
   }
   scale.y = northingSize / rows;
   scale.x = eastingSize  / cols;
}
예제 #2
0
//*****************************************************************************
//  METHOD: ossimRpcModel::lineSampleToWorld()
//
//  Overrides base class implementation. Performs DEM intersection.
//*****************************************************************************
void  ossimRpcModel::lineSampleToWorld(const ossimDpt& imagePoint,
                                       ossimGpt&       worldPoint) const
{

//---
// Under debate... (drb 20130610)
// this seems to be more accurate for the round trip
//---
#if 0
    if(!imagePoint.hasNans())
    {

        lineSampleHeightToWorld(imagePoint,
                                worldPoint.height(),
                                worldPoint);
    }
    else
    {
        worldPoint.makeNan();
    }
#else
    if(!imagePoint.hasNans())
    {
        ossimEcefRay ray;
        imagingRay(imagePoint, ray);
        ossimElevManager::instance()->intersectRay(ray, worldPoint);
    }
    else
    {
        worldPoint.makeNan();
    }
#endif
}
예제 #3
0
//*******************************************************************
// Public Method: ossimDrect::clip
//*******************************************************************
bool ossimDrect::clip(ossimDpt &p1, ossimDpt &p2)const
{
    if(p1.isNan() || p2.isNan())
    {
        return false;
    }
    ossimDpt shift(-theUlCorner.x,
                   -theUlCorner.y);

    ossimDpt tempShiftP1 = p1+shift;
    ossimDpt tempShiftP2 = p2+shift;
    double maxW = width()-1;
    double maxH = height()-1;
    if (clip_1d (&tempShiftP1.x, &tempShiftP1.y,
                 &tempShiftP2.x, &tempShiftP2.y,
                 maxW) == 0)
    {
        return false;
    }
    if(clip_1d (&tempShiftP1.y,
                &tempShiftP1.x,
                &tempShiftP2.y,
                &tempShiftP2.x, maxH) == 0)
    {
        return false;
    }
    p1 = tempShiftP1-shift;
    p2 = tempShiftP2-shift;
    return true;
}
예제 #4
0
ossimDrect::ossimDrect(const ossimDpt& p1,
                       const ossimDpt& p2,
                       const ossimDpt& p3,
                       const ossimDpt& p4,
                       ossimCoordSysOrientMode mode)
    : theOrientMode(mode)
{
    if(p1.hasNans()||p2.hasNans()||p3.hasNans()||p4.hasNans())
    {
        makeNan();
    }
    else
    {
        double minx, miny;
        double maxx, maxy;

        minx = std::min( p1.x, std::min(p2.x, std::min(p3.x, p4.x)));
        miny = std::min( p1.y, std::min(p2.y, std::min(p3.y, p4.y)));
        maxx = std::max( p1.x, std::max(p2.x, std::max(p3.x, p4.x)));
        maxy = std::max( p1.y, std::max(p2.y, std::max(p3.y, p4.y)));

        if(mode == OSSIM_LEFT_HANDED)
        {
            *this = ossimDrect(minx, miny, maxx, maxy, mode);
        }
        else
        {
            *this = ossimDrect(minx,maxy, maxx, miny, mode);
        }
    }
}
예제 #5
0
void ossimImageChain::getDecimationFactor(ossim_uint32 resLevel,
                                          ossimDpt& result) const
{
   if((theImageChainList.size() > 0)&&(isSourceEnabled()))
   {
      ossimImageSource* interface = PTR_CAST(ossimImageSource,
                                                      theImageChainList[0].get());
      if(interface)
      {
         interface->getDecimationFactor(resLevel,
                                        result);
         return;
      }
   }
   else
   {
      if(getInput(0))
      {
         ossimImageSource* interface = PTR_CAST(ossimImageSource,
                                                         getInput(0));
         if(interface)
         {
            interface->getDecimationFactor(resLevel, result);
            return;
         }
      }
   }

   result.makeNan();
}
예제 #6
0
   ossimDpt ImageViewManipulator::sceneToLocal(const ossimDpt& scenePoint)
   {
      ossimDpt result;
      result.makeNan();
      ossimImageGeometry* geom = asGeometry();
      if(geom)
      {
         ossimGpt wpt;
         geom->localToWorld(scenePoint, wpt);
         result = wpt;
      }
      else
      {
         ossimImageViewAffineTransform* ivat = getObjectAs<ossimImageViewAffineTransform>();
         if(ivat)
         {
            if(!scenePoint.hasNans())
            {
               ivat->viewToImage(scenePoint, result);
            }
         }
      }

      return result;
   }
예제 #7
0
void ossimBuckeyeSensor::lineSampleToWorld(const ossimDpt& image_point,
	ossimGpt&       gpt) const
{
	if (traceDebug())  ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimBuckeyeSensor::lineSampleToWorld:entering..." << std::endl;

	if(image_point.hasNans())
	{
		gpt.makeNan();
		return;
	}

	//***
	// Determine imaging ray and invoke elevation source object's services to
	// intersect ray with terrain model:
	//***

	ossimEcefRay ray;
	imagingRay(image_point, ray);
	ossimElevManager::instance()->intersectRay(ray, gpt);

	if (traceDebug())
	{
		ossimNotify(ossimNotifyLevel_DEBUG) << "image_point = " << image_point << std::endl;
		ossimNotify(ossimNotifyLevel_DEBUG) << "ray = " << ray << std::endl;
		ossimNotify(ossimNotifyLevel_DEBUG) << "gpt = " << gpt << std::endl;
	}

	if (traceDebug())  ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimBuckeyeSensor::lineSampleToWorld: returning..." << std::endl;
	return;
}
예제 #8
0
bool ossimGpkgTileMatrixRecord::init( ossim_int32 zoom_level,
                                      const ossimIpt& matrixSize,
                                      const ossimIpt& tileSize,
                                      const ossimDpt& gsd )
{
   bool status = false;

   if ( (matrixSize.hasNans() == false) && (tileSize.hasNans() == false) &&
        (gsd.hasNans() == false) )
   {
      m_table_name = "tiles";
      m_zoom_level = zoom_level;
      m_matrix_width = matrixSize.x;
      m_matrix_height = matrixSize.y;
      m_tile_width = tileSize.x;
      m_tile_height = tileSize.y;
      m_pixel_x_size = gsd.x;
      m_pixel_y_size = gsd.y;
      
      status = true;
   }
   
   return status;
   
} // End: ossimGpkgTileMatrixRecord::init( zoom_level, ... )
예제 #9
0
void ossimNitfProjectionFactory::computeScaleInDecimalDegrees(
   const ossimNitfImageHeader* hdr,
   const std::vector<ossimGpt>& gpts,
   ossimDpt& scale) const
{
   if ( !hdr || isSkewed(gpts))
   {
      scale.makeNan();
      return;
   }
   ossimIrect imageRect = hdr->getImageRect();

   //---
   // Calculate the scale.  This assumes that the corner points are for the
   // edge of the corner pixels, not the center of the corner pixels.
   //---
   double longitudeSize  = 0.0;
   double latitudeSize = 0.0;
   if ( (gpts[1].lond() < 0.0) && (gpts[0].lond() >= 0) )
   {
      //---
      // Upper right negative(Western), upper left positive (Eastern).
      // Crossing date line maybe???
      //---
      longitudeSize = (gpts[1].lond() + 360.0) - gpts[0].lond();
   }
   else
   {
      longitudeSize = gpts[1].lond() - gpts[0].lond();
   }

   latitudeSize = gpts[0].latd() - gpts[2].latd();

   double rows = imageRect.height();
   double cols = imageRect.width();
//   double rows = hdr->getNumberOfRows();
//   double cols = hdr->getNumberOfCols();
       
   if (!rows || !cols)
   {
      scale.makeNan();
      return;
   }
   scale.y = latitudeSize  / rows;
   scale.x = longitudeSize / cols;
}
bool ossimGpkgTileMatrixSetRecord::init(
   const std::string& tableName,ossim_int32 srs_id,
   const ossimDpt& minPt, const ossimDpt& maxPt )
{
   bool status = false;
   if ( (minPt.hasNans() == false) && (maxPt.hasNans() == false) )
   {
      m_table_name = tableName;
      m_srs_id = srs_id;
      m_min_x  = minPt.x;
      m_min_y  = minPt.y;
      m_max_x  = maxPt.x;
      m_max_y  = maxPt.y;
      status   = true;
   }
   return status;
}
예제 #11
0
void ossimIvtGeomXform::imageToView(const ossimDpt& ipt, ossimDpt& viewPt)
{
  viewPt.makeNan();
  if(m_ivt.valid())
  {
    m_ivt->imageToView(ipt, viewPt);
  }
}
예제 #12
0
void ossimIvtGeomXform::groundToImage(const ossimGpt& gpt, ossimDpt& ipt)
{
  ipt.makeNan();
  if(m_geom.valid())
  {
    m_geom->worldToLocal(gpt, ipt);
  }
}
예제 #13
0
void ossimIvtGeomXform::viewToImage(const ossimDpt& viewPt, ossimDpt& ipt)
{
  ipt.makeNan();
  if(m_ivt.valid())
  {
    m_ivt->viewToImage(viewPt, ipt);
  }
}
예제 #14
0
//*****************************************************************************
//  METHOD: ossimRpcProjection::worldToLineSample()
//  
//  Overrides base class implementation. Directly computes line-sample from
//  the polynomials.
//*****************************************************************************
void ossimRpcProjection::worldToLineSample(const ossimGpt& ground_point,
                                      ossimDpt&       imgPt) const
{
   if (traceExec())  ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimRpcProjection::worldToLineSample(): entering..." << std::endl;

   if(ground_point.isLatNan() ||
      ground_point.isLonNan() )
     {
       imgPt.makeNan();
       return;
     }
         
   //*
   // Normalize the lat, lon, hgt:
   //*
   double nlat = (ground_point.lat - theLatOffset) / theLatScale;
   double nlon = (ground_point.lon - theLonOffset) / theLonScale;
   double nhgt;

   if(ossim::isnan(ground_point.hgt))
   {
      nhgt = (theHgtScale - theHgtOffset) / theHgtScale;
   }
   else
   {
      nhgt = (ground_point.hgt - theHgtOffset) / theHgtScale;
   }

   
   //***
   // Compute the adjusted, normalized line (U) and sample (V):
   //***
   double Pu = polynomial(nlat, nlon, nhgt, theLineNumCoef);
   double Qu = polynomial(nlat, nlon, nhgt, theLineDenCoef);
   double Pv = polynomial(nlat, nlon, nhgt, theSampNumCoef);
   double Qv = polynomial(nlat, nlon, nhgt, theSampDenCoef);
   double U_rot  = Pu / Qu;
   double V_rot  = Pv / Qv;

   //***
   // U, V are normalized quantities. Need now to establish the image file
   // line and sample. First, back out the adjustable parameter effects
   // starting with rotation:
   //***
   double U = U_rot*theCosMapRot + V_rot*theSinMapRot;
   double V = V_rot*theCosMapRot - U_rot*theSinMapRot;

   //***
   // Now back out skew, scale, and offset adjustments:
   //***
   imgPt.line = U*(theLineScale+theIntrackScale) + theLineOffset + theIntrackOffset;
   imgPt.samp = V*(theSampScale+theCrtrackScale) + theSampOffset + theCrtrackOffset;


   if (traceExec())  ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimRpcProjection::worldToLineSample(): returning..." << std::endl;

   return;
}
예제 #15
0
//*******************************************************************
// Public Constructor:
//*******************************************************************
ossimFpt::ossimFpt(const ossimDpt& pt)
   :
      x(pt.x), y(pt.y)
{
   if(pt.hasNans())
   {
      makeNan();
   }
}
void ossimImageSourceSequencer::getDecimationFactor(ossim_uint32 resLevel,
                                                    ossimDpt& result) const
{
   if(theInputConnection)
   {
      theInputConnection->getDecimationFactor(resLevel, result);
   }
   result.makeNan();
}
예제 #17
0
void ossimIvtGeomXform::groundToView(const ossimGpt& gpt, ossimDpt& viewPt)
{
  ossimDpt ipt;
  viewPt.makeNan();

  groundToImage(gpt, ipt);
  if(!ipt.hasNans())
  {
    imageToView(ipt, viewPt);
  }
}
//*****************************************************************************
//  Other workhorse of the object. Converts view-space to image-space.
//*****************************************************************************
void ossimImageViewProjectionTransform::viewToImage(const ossimDpt& vp, ossimDpt& ip) const
{
   // Check for same geometries on input and output (this includes NULL geoms):
   if (m_imageGeometry == m_viewGeometry)
   {
      ip = vp;
      return;
   }
   
   // Otherwise we need access to good geoms. Check for a bad geometry object:
   if (!m_imageGeometry || !m_viewGeometry)
   {
      ip.makeNan();
      return;
   }
   
   // Check for same projection on input and output sides to save projection to ground:
   const ossimProjection* iproj = m_imageGeometry->getProjection();
   const ossimProjection* vproj = m_viewGeometry->getProjection();
   if ((iproj && vproj && iproj->isEqualTo(*vproj)) || (iproj == vproj))
   {
      // Check for possible same 2D transforms as well:
      const ossim2dTo2dTransform* ixform = m_imageGeometry->getTransform();
      const ossim2dTo2dTransform* vxform = m_viewGeometry->getTransform();
      if (((ixform && vxform && ixform->isEqualTo(*vxform)) || (ixform == vxform)) &&
          (m_imageGeometry->decimationFactor(0) == m_viewGeometry->decimationFactor(0)))
      {
         ip = vp;
         return;
      }
      
      // Not the same 2D transform, so just perform local-image -> full-image -> local-view:
      ossimDpt fp;
      m_viewGeometry->rnToFull(vp, 0, fp);
      m_imageGeometry->fullToRn(fp, 0, ip);
      return;
   }
   
   //---
   // Completely different left and right side geoms (typical situation).
   // Need to project to ground.
   //---
   ossimGpt gp;
   m_viewGeometry->localToWorld(vp, gp);
   m_imageGeometry->worldToLocal(gp, ip);

#if 0 /* Please leave for debug. */
   cout <<"DEBUG ossimImageViewProjectionTransform::viewToImage:"
        <<"\n    vp: "<<vp
        <<"\n    gp: "<<gp
        <<"\n    ip: "<<ip
        <<std::endl;
#endif
}
예제 #19
0
void ossimMrSidReader::getDecimationFactor(ossim_uint32 resLevel,
                                           ossimDpt& result) const
{
   if (theGeometry.valid())
   {
      theGeometry->decimationFactor(resLevel, result);
   }
   else
   {
      result.makeNan();
   }
}
예제 #20
0
void ossimGui::ImageScrollWidget::setTrackPoint(const ossimDpt& position)
{
   if(position.hasNans())
   {
      m_trackPoint.makeNan();
   }
   else 
   {
      ossimDpt pt;
      m_viewToScroll.map(position.x, position.y, &pt.x, &pt.y);
      m_scrollToLocal.map(pt.x, pt.y, &m_trackPoint.x, &m_trackPoint.y);
      m_widget->update();
   }
}
예제 #21
0
void ossimQuadTreeWarp::findAllNodes(std::vector<const ossimQuadTreeWarpNode*>& result,
                                     const ossimDpt& pt)const
{
   if(!pt.hasNans()&&(!isEmpty()))
   {
      if(theTree->theBoundingRect.pointWithin(pt))
      {
         findAllNodes(result,
                      theTree,
                      pt);
      }
   }
   
}
예제 #22
0
void  ossimRpcProjection::lineSampleToWorld(const ossimDpt& imagePoint,
                                            ossimGpt&       worldPoint) const
{
   if(!imagePoint.hasNans())
   {
      
      lineSampleHeightToWorld(imagePoint,
                              worldPoint.height(),
                              worldPoint);
   }
   else
   {
      worldPoint.makeNan();
   }
}
void ossimCsmSensorModel::lineSampleToWorld(const ossimDpt& image_point,
                                            ossimGpt&       gpt) const
{
   if(image_point.hasNans())
   {
      gpt.makeNan();
      return;
   }
   //***
   // Determine imaging ray and invoke elevation source object's services to
   // intersect ray with terrain model:
   //***
   ossimEcefRay ray;
   imagingRay(image_point, ray);
   ossimElevManager::instance()->intersectRay(ray, gpt);   
}
예제 #24
0
 void ossimTileMapModel::lineSampleHeightToWorld(const ossimDpt& image_point,
                                                 const double&   /* height */,
                                                 ossimGpt&       gpt) const
 {
    if(!image_point.hasNans())
    {
       gpt.lon = static_cast<double>(image_point.samp)/(1 << qDepth)/256 *360.0-180.0;
       double y = static_cast<double>(image_point.line)/(1 << qDepth)/256;
       double ex = exp(4*M_PI*(y-0.5));
       gpt.lat = -180.0/M_PI*asin((ex-1)/(ex+1));
    }
    else
    {
       gpt.makeNan();
    }
    return;
 }
예제 #25
0
//*****************************************************************************
//  METHOD: ossimRpcModel::lineSampleToWorld()
//  
//  Overrides base class implementation. Performs DEM intersection.
//*****************************************************************************
void  ossimRpcModel::lineSampleToWorld(const ossimDpt& imagePoint,
                                       ossimGpt&       worldPoint) const
{

	//lineSampleHeightToWorld(imagePoint, theHgtOffset, worldPoint);
	//worldPoint.hgt = ossimElevManager::instance()->getHeightAboveEllipsoid(worldPoint);
	//if(!worldPoint.hasNans()) return;

   if(!imagePoint.hasNans())
   {
      ossimEcefRay ray;
	  imagingRay(imagePoint, ray);
	  if (m_proj) worldPoint.datum(m_proj->getDatum());	//loong
      ossimElevManager::instance()->intersectRay(ray, worldPoint);
   }
   else
   {
      worldPoint.makeNan();
   }
}
예제 #26
0
void ossimBuckeyeSensor::worldToLineSample(const ossimGpt& world_point,
	ossimDpt&       image_point) const
{
	if (traceDebug())  ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimBuckeyeSensor::worldToLineSample: entering..." << std::endl;
	if((theBoundGndPolygon.getNumberOfVertices() > 0)&&
		(!theBoundGndPolygon.hasNans()))
	{
		if (!(theBoundGndPolygon.pointWithin(world_point)))
		{
			image_point.makeNan();
			return;
		}         
	}
	ossimEcefPoint g_ecf(world_point);
	ossimEcefVector ecfRayDir(g_ecf - theAdjEcefPlatformPosition);
	ossimColumnVector3d camRayDir (theCompositeMatrixInverse*ecfRayDir.data());


	double scale = -theFocalLength/camRayDir[2];
	ossimDpt film (scale*camRayDir[0], scale*camRayDir[1]);

	if (theLensDistortion.valid())
	{
		ossimDpt filmOut;
		theLensDistortion->distort(film, filmOut);
		film = filmOut;
	}

	ossimDpt f1(film + thePrincipalPoint);
	ossimDpt p1(f1.x/thePixelSize.x,
		-f1.y/thePixelSize.y);

	ossimDpt p0 (p1.x + theRefImgPt.x,
		p1.y + theRefImgPt.y);

	image_point = p0;
	if (traceDebug())  ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimBuckeyeSensor::worldToLineSample: returning..." << std::endl;
}
void ossimSpectraboticsRedEdgeModel::lineSampleToWorld(const ossimDpt& image_point,
                                               ossimGpt&       gpt) const
{
   if (traceDebug())  ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimSpectraboticsRedEdgeModel::lineSampleToWorld:entering..." << std::endl;
   
   if(image_point.hasNans())
   {
      gpt.makeNan();
      return;
   }
   //***
   // Extrapolate if image point is outside image:
   //***
//   if (!insideImage(image_point))
//   {
//      gpt.makeNan();
//       gpt = extrapolate(image_point);
//      return;
//   }

   //***
   // Determine imaging ray and invoke elevation source object's services to
   // intersect ray with terrain model:
   //***
   ossimEcefRay ray;
   imagingRay(image_point, ray);
   ossimElevManager::instance()->intersectRay(ray, gpt);

   if (traceDebug())
   {
      ossimNotify(ossimNotifyLevel_DEBUG) << "image_point = " << image_point << std::endl;
      ossimNotify(ossimNotifyLevel_DEBUG) << "ray = " << ray << std::endl;
      ossimNotify(ossimNotifyLevel_DEBUG) << "gpt = " << gpt << std::endl;
   }

   if (traceDebug())  ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimSensorModel::lineSampleToWorld: returning..." << std::endl;
   return;
}
예제 #28
0
   void ossimTileMapModel::worldToLineSample(const ossimGpt& ground_point,
                                             ossimDpt&       img_pt) const
   {
      // if (traceExec())  ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG ossimTileMapModel::worldToLineSample(): entering..." << std::endl;

      if(ground_point.isLatNan() || ground_point.isLonNan() )
      {
         img_pt.makeNan();
         return;
      }

      double x = (180.0 + ground_point.lon) / 360.0;
      double y = - ground_point.lat * M_PI / 180; // convert to radians
      y = 0.5 * log((1+sin(y)) / (1 - sin(y)));
      y *= 1.0/(2 * M_PI); // scale factor from radians to normalized
      y += 0.5; // and make y range from 0 - 1

      img_pt.samp = floor(x*pow(2.,static_cast<double>(qDepth))*256);

      img_pt.line = floor(y*pow(2.,static_cast<double>(qDepth))*256);

      return;
   }
예제 #29
0
void ossimApplanixUtmModel::worldToLineSample(const ossimGpt& world_point,
                                           ossimDpt&       image_point) const
{
   if((theBoundGndPolygon.getNumberOfVertices() > 0)&&
      (!theBoundGndPolygon.hasNans()))
   {
      if (!(theBoundGndPolygon.pointWithin(world_point)))
      {
         image_point.makeNan();
//          image_point = extrapolate(world_point);
         return;
      }         
   }
   ossimEcefPoint g_ecf(world_point);
   ossimEcefVector ecfRayDir(g_ecf - theAdjEcefPlatformPosition);
   ossimColumnVector3d camRayDir (theCompositeMatrixInverse*ecfRayDir.data());
   
      
   double scale = -theFocalLength/camRayDir[2];
   ossimDpt film (scale*camRayDir[0], scale*camRayDir[1]);
      
   if (theLensDistortion.valid())
   {
      ossimDpt filmOut;
      theLensDistortion->distort(film, filmOut);
      film = filmOut;
    }
   
     ossimDpt f1(film + thePrincipalPoint);
    ossimDpt p1(f1.x/thePixelSize.x,
                -f1.y/thePixelSize.y);

    ossimDpt p0 (p1.x + theRefImgPt.x,
                 p1.y + theRefImgPt.y);
    
    image_point = p0;
}
예제 #30
0
void ossimImageViewTransform::getScaleChangeImageToView(ossimDpt& result,
        const ossimDrect& imageRect)
{
    result.makeNan();
    if(!imageRect.hasNans())
    {
        ossimDpt vul;
        ossimDpt vur;
        ossimDpt vlr;
        ossimDpt vll;

        imageToView(imageRect.ul(),
                    vul);
        imageToView(imageRect.ur(),
                    vur);
        imageToView(imageRect.lr(),
                    vlr);
        imageToView(imageRect.ll(),
                    vll);

        if(!vul.hasNans()&&
                !vur.hasNans()&&
                !vlr.hasNans()&&
                !vll.hasNans())
        {

            double deltaTop    = (vul - vur).length();
            double deltaBottom = (vll - vlr).length();
            double deltaRight  = (vur - vlr).length();

            double w = imageRect.width();
            double h = imageRect.height();
            result.x = (deltaTop/w + deltaBottom/w)*.5;
            result.y = (deltaRight/h + deltaRight/h)*.5;
        }
    }
}