Logo Search packages:      
Sourcecode: magics++ version File versions  Download package

Transformation.cc

/******************************** LICENSE ********************************

  Copyright 2007 European Centre for Medium-Range Weather Forecasts (ECMWF) 

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.

 ******************************** LICENSE ********************************/

// File Transformation.cc
// Magics Team - ECMWF 2004

#include "BasicGraphicsObject.h"
#include "Transformation.h"
#include "Layout.h"
#include "PolyCoast.h"
#include "Clipper.h" 
#include <iomanip>
#include "MatrixHandler.h"
#include "PointsHandler.h"
#include "MetaData.h"



using namespace magics;


Transformation::Transformation() : 
      dataMinX_(int_MAX), dataMaxX_(int_MIN),
      dataMinY_(int_MAX), dataMaxY_(int_MIN)
{
}

Transformation::~Transformation() 
{
}

void Transformation::print(ostream& out)  const
{
      out << "Transformation";
}

void Transformation::forceNewArea(double xpcmin, double ypmin, double xpcmax, double ypcmax, double& width, double& height)
{
      
}
void Transformation::fill(double& width, double& height)
{
      init();
      // with and height will only 
      double w = getAbsoluteMaxPCX() - getAbsoluteMinPCX();
      double h = getAbsoluteMaxPCY() - getAbsoluteMinPCY();
      
      double minx =  getAbsoluteMinPCX();
      double maxx =  getAbsoluteMaxPCX();
      
      double miny =  getAbsoluteMinPCY();
      double maxy =  getAbsoluteMaxPCY();
      
      
            
      
      
                  double nw = (width/height) *h;            
                  if ( nw > w) {
                  // we need to extend in the x direction
                        double more = (nw-w)/2;
                        maxx = maxx + more;
                        minx = minx - more;                 
                  }
                  else { 
                        double nh = (height/width)*w;                   
                        double more = (nh-h)/2;                                     
                        maxy = maxy + more;
                        miny = miny - more;                       
                  }
            
            
      
            setNewPCBox(minx, miny, maxx, maxy); 
            
      //    aspectRatio(width, height);
      
}

void Transformation::aspectRatio(double& width, double& height)
{
      double w = getAbsoluteMaxPCX() - getAbsoluteMinPCX();
      double h = getAbsoluteMaxPCY() - getAbsoluteMinPCY();
      if ( w/h >= width/height) {
            double nh = (h/w) * width;
            if ( nh <= height) {
                  height = nh;
            }
            else {
                  width = (w/h) * height;             
            }
      }
      else 
            width = (w/h) * height;
}



template <class P>
bool inArea(double left, double right, double bottom, double top, const Polyline& poly)
{
      return (top >= poly.getMaxY() &&
                  left <= poly.getMinX() &&
                  bottom <= poly.getMinY() &&
                  right >= poly.getMaxX());
} 

bool Transformation::out(const Polyline& poly) const
{
      return ( poly.getMaxX() < getMinX() || 
                  poly.getMinX() > getMaxX() ||
                  poly.getMaxY() < getMinY() ||
                  poly.getMinY() > getMaxY() );
}


bool Transformation::in(const Polyline& poly) const
{
      return (getMaxY() >= poly.getMaxY() &&
                  getMinX() <= poly.getMinX() &&
                  getMinY() <= poly.getMinY() &&
                  getMaxX() >= poly.getMaxX());
} 


void Transformation::rotate(vector<GeoPoint>& poly) const
{
      if ( poly.empty() ) return;
      if  ( poly.back() != poly.front() ) return;



      for ( vector<GeoPoint>::iterator point = poly.begin(); point != poly.end(); ++point)
      {
            if ( !in(*point) )
            {
                  // First point out ... Rotate
                  std::rotate(poly.begin(), point, poly.end());
                  break;
            } 
      }
      //poly.push_back(poly.front());
} 




      template <class P>
void rotate(double left, double right, double bottom, double top, Polyline& poly)
{
      bool toclose = poly.isClosed();
      for ( typename Polyline::iterator point = poly.begin(); point != poly.end(); ++point)
      {
            if ( !((*point).y() < top && (*point).y() > bottom && (*point).x() > left && (*point).x() < right))
            {
                  // First point out ... Rotate
                  std::rotate(poly.begin(), point, poly.end());
                  break;
            } 
      } 
      if ( toclose) poly.push_back(poly.front());
} 




void Transformation::thin(MatrixHandler<GeoPoint>& matrix, double x, double y, vector<GeoPoint>& out) const
{
      int xfactor = (int) ceil((float) x);
      int yfactor = (int) ceil((float) y);
      ThinningMatrixHandler<GeoPoint> thin_matrix(matrix, xfactor , yfactor);
      BoxMatrixHandler<GeoPoint> box_matrix(thin_matrix, *this);

      int columns =box_matrix.columns();
      int rows = box_matrix.rows();

      for ( int lon = 0; lon < columns; lon++) 
            for ( int lat = 0; lat < rows; lat++)           
                  if ( in(box_matrix.column(lat, lon), box_matrix.row(lat, lon)) )
                        out.push_back(GeoPoint(box_matrix.column(lat, lon), box_matrix.row(lat, lon), box_matrix(lat, lon)));
      columns = matrix.columns();
      rows = matrix.rows();



}



ViewFilter::ViewFilter(double xmin, double xmax, double ymin, double ymax, double xres, double yres) : 
      xmin_(xmin), xmax_(xmax), ymin_(ymin), ymax_(ymax), 
      xres_(xres), yres_(yres) 
{
      xdim_ = (int) (xmax_-xmin_)/xres_;
      ydim_ = (int) (ymax_-ymin_)/yres_;

      for (int y = 0; y < ydim_; y++)
            for ( int x = 0; x < xdim_; x++)
                  done.push_back(false);

}

/*
   bool ViewFilter::in(const PaperPoint& xy)  {

   int x = (xy.x()-xmin_)/xres_;
   int y = (xy.y()-ymin_)/yres_;

   if ( x < 0 ) return false;
   if ( y < 0 ) return false;
   if ( x >= xdim_) return false;
   if ( y >= ydim_) return false;
   bool info = !done[y*xdim_+x];
   done[y*xdim_+x] = true;
   return info;
   }
 */
bool ViewFilter::in(const PaperPoint& xy){
      if ( xy.x() < xmin_ ) return false;
      if ( xy.x() > xmax_ ) return false;
      if ( xy.y() < ymin_ ) return false;
      if ( xy.y() < ymin_ ) return false;
      return true;
}





void Transformation::setDataMinX(double minx, const string& ref) const
{ 
      // WE will have to take into acount the date!
      dataMinX_ = std::min(minx, dataMinX_); 
      dataReferenceX_ = ref;
}

void Transformation::setDataMaxX(double maxx, const string& ref) const 
{ 
      dataMaxX_ = std::max(maxx, dataMaxX_); 
      dataReferenceX_ = ref;
}

void Transformation::setDataMinY(double miny, const string& ref) const
{ 
      dataMinY_ = std::min(miny, dataMinY_);
      dataReferenceY_ = ref; 
}

void Transformation::setDataMaxY(double maxy, const string& ref) const 
{ 
      dataMaxY_ = std::max(maxy, dataMaxY_); 
      dataReferenceY_ = ref; 
}


void Transformation::visit(MetaDataVisitor& visitor, double left, double top, double width, double height)
{
      ostringstream java;
      double w = getMaxPCX() - getMinPCX();
      double h = getMaxPCY() - getMinPCY();
      java << "{";
      java << "\"name\" : \"cylindrical\",";          

      java << "\"top\" : \"" << top <<  "\",";        
      java << "\"left\" : \"" << left <<  "\",";            
      java << "\"width\" : \"" << width <<  "\",";    
      java << "\"height\" : \"" << height <<  "\",";  

      java << "\"pcxmin\" : \"" << getMinPCX() <<  "\",";         
      java << "\"pcymin\" : \"" << getMinPCY() <<  "\",";         
      java << "\"pcwidth\" : \"" << w <<  "\",";      
      java << "\"pcheight\" : \"" << h <<  "\"";      

      java << "}";      
      visitor.add("projection", java.str());

}


void Transformation::operator()(const Polyline& from, BasicGraphicsObjectContainer& out) const
{     
      Clipper<BasicGraphicsObjectContainer> clipper(*this); 
      clipper.ignoreMissing(false);
      clipper(from); 
      clipper.feed(out);
}



void Transformation::boundingBox(double& minx, double& miny, double&maxx, double& maxy) const
{
      // Return exactly the box ... Perhaps could return a bit more to avoid side effect.
      minx= getMinX();
      miny= getMinY();
      maxx= getMaxX();
      maxy= getMaxY();
}



bool Transformation::in(const GeoPoint& point) const
{
      return ( getAbsoluteMinX() <= point.x() && 
                  point.x() <=  getAbsoluteMaxX() && 
                  getAbsoluteMinY() <= point.y() && 
                  point.y() <= getAbsoluteMaxY()); 
}

bool Transformation::in(const UserPoint& point) const
{
      return ( getAbsoluteMinX() <= point.x() && 
                  point.x() <=  getAbsoluteMaxX() && 
                  getAbsoluteMinY() <= point.y() && 
                  point.y() <= getAbsoluteMaxY()); 
}

bool Transformation::in(const PaperPoint& point) const
{
      return ( getAbsoluteMinPCX() <= point.x() && 
                  point.x() <=  getAbsoluteMaxPCX() && 
                  getAbsoluteMinPCY() <= point.y() && 
                  point.y() <= getAbsoluteMaxPCY());
} 

bool Transformation::clip(PaperPoint& point) const
{
      bool done = false;
      if ( point.x() < getAbsoluteMinPCX() ) {
            done = true;
            point.x(getAbsoluteMinPCX());
      }
      if ( point.y() < getAbsoluteMinPCY() ) {
            done = true;
            point.y(getAbsoluteMinPCY());
      }

      if ( point.x() > getAbsoluteMaxPCX() ) {
            done = true;
            point.x(getAbsoluteMaxPCX());
      }
      if ( point.y() > getAbsoluteMaxPCY() ) {
            done= true;
            point.y(getAbsoluteMaxPCY());
      }
      return  done;


}

void Transformation::thin(PointsHandler<GeoPoint>& points, vector<PaperPoint>& thin,  vector<PaperPoint>& all) const
{     

      BoxPointsHandler<GeoPoint> box(points, *this);
      box.setToFirst();
      while (box.more()) {                      
            PaperPoint xy = (*this)(box.current());
            if ( view_.in(xy) ) {
                  thin.push_back(xy);
            }
            all.push_back(xy);

            box.advance();          
      }  

}

void Transformation::thin(MatrixHandler<UserPoint>& points, vector<PaperPoint>& thin,  vector<PaperPoint>& all) const
{

}

void Transformation::thin(MatrixHandler<GeoPoint>& points, vector<PaperPoint>& thin,  vector<PaperPoint>& all) const
{     

      BoxMatrixHandler<GeoPoint> box(points, *this);
      int row = std::max(int(view_.yres_/abs(box.YResolution())), 1);
      int column = std::max(int(view_.xres_/abs(box.XResolution())), 1);
      ThinningMatrixHandler<GeoPoint> sample(box, row, column);

      box.setToFirst();
      while (box.more()) {                      
            PaperPoint xy = (*this)(box.current());                      
            if ( view_.in(xy) ) 
                  all.push_back(xy);                 
            box.advance();          
      }  
      sample.setToFirst();
      while (sample.more()) {                         
            PaperPoint xy = (*this)(sample.current());                 
            if ( view_.in(xy) ) 
                  thin.push_back(xy);                

            sample.advance();       
      }  







}
void Transformation::operator()(PolyCoast& coast, BasicGraphicsObjectContainer& list) const
{
      // Special case for the south pole! 
      // Add to point to ease the Shading!
      vector<GeoPoint>& geo =  coast.coastlines();

      if ( coast.level() == 0 ) {

            GeoPoint front = geo.front();
            GeoPoint back = geo.back();
            front.latitude(-90.);
            back.latitude(-90.);
            geo.insert(geo.begin(), front);
            geo.push_back(back);
      }

      Clipper<BasicGraphicsObjectContainer> clipper(*this);

      rotate(geo);


      clipper.close(coast);
      clipper.feed(list);

}
double Transformation::unitToCm(double width, double height) const
{
      
      return height/(getMaxY() -getMinY()); 
}

void Transformation::operator()(const GeoPoint& geo, vector<PaperPoint>& out) const
{
      PaperPoint pp = (*this)(geo);
            if ( in(pp) ) 
                  out.push_back(pp);
            pp = (*this)(geo.left());
                  if ( in(pp) ) 
                        out.push_back(pp);
            pp = (*this)(geo.right());
                        if ( in(pp) ) 
                              out.push_back(pp);
}

void Transformation::operator()(const UserPoint& xy, vector<PaperPoint>& out) const
{
      PaperPoint pp = (*this)(xy);
      if ( in(pp) ) 
            out.push_back(pp);
}

void Transformation::reprojectComponents(const GeoPoint&, pair<double, double>&) const
{
      
}

void Transformation::reprojectSpeedDirection(const PaperPoint& point, pair<double, double>&) const
{
      
}



Generated by  Doxygen 1.6.0   Back to index