Helpful Posts Helpful Posts:  0
Results 1 to 20 of 20

Thread: EquiRectangular Projection Help

  1. #1
    New Member
    Join Date
    Feb 2012
    Posts
    9

    EquiRectangular Projection Help

    Hi all,
    I am in process of making equirectangular panorama as a part of my project, by following some steps of panoramic Mosaic generation. Until now, I am able to generate panorama when it is wrapped in cylindrical coordinates. But in that, we can't get top and bottom portion. I want full view 360x180 panorama which is possible through spherical coordinates. I have looked in many resources and papers but I didn't find formulas which converts wrap images in those coordinates. Also I have used PTGui, and other commercial software in which they allow to move , rotate an image on sphere and unwrap it.(a.k.a Equirectangular projection), but source code is not available. In the case of libPano which is open source, it is not understandable why they have used specific formulas..

    So is there any one, who atleast can give me some hint..
    Any kind of help will be appreciated.

    Thank you.

  2. #2
    inkista's Avatar
    Join Date
    Nov 2009
    Location
    San Diego, California
    Posts
    1,409
    Real Name
    Kathy Li

    Re: EquiRectangular Projection Help

    I'm not quite sure what you're asking. Are you having an issue with finding a free stitcher that can create equirectangulars? If so, try the open source package, Hugin. Are you having issues with shooting the coverage for an equirectangular? If so, consider getting a panohead like a Nodal Ninja or Panosaurus that will allow you to take multiple rows, as well as rotate around the no-parallax point to shoot the zenith (straight up) and nadir (straight down) shots.

    You actually have to cover the sphere photographically, either by shooting more images, or by using a very wide angle lens. I have a fisheye lens (Sigma 8mm f/3.5 circular) that gives me 180 degree vertical coverage across the frame if my camera is in portrait orientation. I will shoot a zenith and nadir anyway for additional patching material, in case my alignment is off.

    EquiRectangular Projection Help

    Note how the last two images are the zenith and nadir shots to do full coverage. I then used PTMac (today, I use PTGui) to stitch together the equirectangular, and I use Photoshop layers and masks to patch in the floor from the handheld zenith shot to cover where the tripod was.

    EquiRectangular Projection Help

    You can't just take a cylindrical pano and make an equirectangular out of it, because you have no polar coverage.

  3. #3
    New Member
    Join Date
    Feb 2012
    Posts
    9

    Re: EquiRectangular Projection Help

    hey inkista ,
    thanks a lot for help. Well, let me explain you a bit more. I am not looking for any free readymade available stitchers. As this is my own project, I am in the way of implementing one on my own. Till date, it is working good with cylinder projection only. And as you said we can't cover zenith/nadir with that projection, I have to use full spherical projection. Now look at the attached images. This has nothing to do with stitching, it just requires a bit of maths related to projections. I gave two images to PTGui, and one can change the projection in the editor window of it. Note that currently I have selected the equirectangular projection. Now see how the photos become curved.

    In the pics you uploaded, see the last one. It has got extreme distortion near poles. I need a mathematical formula of that. I want to understand, given any image and its theta,phi angles, how to distort it(as PTGui does).

    Steps:

    Image in normal projection:
    EquiRectangular Projection Help

    Now in equirectangular :
    EquiRectangular Projection Help

    Now I moved image a bit upwards:
    EquiRectangular Projection Help

    Even more:
    EquiRectangular Projection Help

    On pole:
    EquiRectangular Projection Help

    I want to understand this. Want a mathematical formula or algorithm or code for this.

  4. #4

    Join Date
    Jul 2010
    Location
    Philadelphia, PA USA
    Posts
    12
    Real Name
    Kirk Thibault

    Re: EquiRectangular Projection Help

    hugin and PTGui are based on the panotools set of utilities - panotools is a free, open source collection of utilities, so you can download the code and take a look:

    http://panotools.sourceforge.net/

    Good luck!

    kirk

  5. #5
    New Member
    Join Date
    Feb 2012
    Posts
    9

    Re: EquiRectangular Projection Help

    Ya i told in my first post that for panotools (as the call the library libPano), i didn't find any documentation about code. They have used some random math function without even mentioning what does it mean. If you find and documentation, pls give me a link..

  6. #6
    inkista's Avatar
    Join Date
    Nov 2009
    Location
    San Diego, California
    Posts
    1,409
    Real Name
    Kathy Li

    Re: EquiRectangular Projection Help

    Ok, you're in over my head. All I know is that an equirectangular mapping is a simple spherical->cartesian translation of θ -> y, and φ -> x. I assume that just shifting the POV around is basically rotating and remapping the sphere.

  7. #7
    Photon Hacker's Avatar
    Join Date
    Dec 2011
    Location
    Veracruz, México
    Posts
    126
    Real Name
    Mario

    Re: EquiRectangular Projection Help

    Hello.

    I understood that you want to write yet another panoramic image integration program but I don't understand your query. What are you asking for?. A mathematical formula with which meaning?.

    If it is the formula used in a specific program then here is a suggestion from the personal experience of your fellow enthusiast programmer (Me): If you can't understand a program's source code then recreating it may help to understand it. However, if you are unable to modify the existing program to fit for a specific task because you don't understand it you will fail short of writing one to do the task from scratch. Search for the reasons than impede to you understanding the existing program and work on these. Informatics and general society would be much better if we follow the attitude of (Paraphrasing Scheme's R5RS Introduction) not working around over our shortcomings but rather addressing the underlying shortcoming than appears to make the reimplementation, bloating feature or otherwise workaround necessary. Maybe you just need to study basic trigonometry.

    Quote Originally Posted by inkista View Post
    You can't just take a cylindrical pano and make an equirectangular out of it, because you have no polar coverage.
    There don't exists a projection named "cylindrical". That's a class of projections. The equirrectangular projection is a cylindrical projection [I assumed Mercator projection was meant and subsequently modified the message when I realized the mistake. The previous paragraph has been preserved as a quote below for consistency purpose]

    It is possible to transform between these projections, it's just than there won't be full coverage. like with the common perspective adjust function in most image editors. How to deal artistically with the void space depends on the image and the artistic sense of the photographer.
    Regards and good luck.
    Last edited by Photon Hacker; 8th February 2012 at 11:55 PM.

  8. #8
    New Member
    Join Date
    Feb 2012
    Posts
    9

    Re: EquiRectangular Projection Help

    What are you asking for?. A mathematical formula with which meaning?.
    For the projection itself. The formula which TELLS me how to DISTORT the given image. In simple term :
    a function which takes an image and some other params and give the distorted image(as i have attached).

    Maybe you just need to study basic trigonometry.
    Well, i think i did. But the problem is how to apply that in image processing? Especially in this problem.

    There don't exists a projection named "cylindrical". That's a class of projections. The equirrectangular projection is a cylindrical projection [I assumed Mercator projection was meant and subsequently modified the message
    Exactly , the equirectagular is also called equidistant cylinder. Even mercator will be helpful ..

  9. #9
    New Member
    Join Date
    Feb 2012
    Posts
    9

    Re: EquiRectangular Projection Help

    I assume that just shifting the POV around is basically rotating and remapping the sphere.
    Yes that's what i want to do. But how??

    an equirectangular mapping is a simple spherical->cartesian translation of θ -> y, and φ -> x
    Ok then..what is the way to get theta, phi of each pixel from an image?

  10. #10
    inkista's Avatar
    Join Date
    Nov 2009
    Location
    San Diego, California
    Posts
    1,409
    Real Name
    Kathy Li

    Re: EquiRectangular Projection Help

    Quote Originally Posted by dan19 View Post
    ... Ok then..what is the way to get theta, phi of each pixel from an image?
    From the x,y coordinate of the pixel and the dimensions of the equirectangular.

    Say, that your equirectangular is 1000x500 pixels.

    y=250 is your horizon. y=0 is the south pole. y=500 is the north pole.

    x=0=1000 is phi=0, x=500 is phi = 180 degrees = pi (rho) [And you can probably make rho however big you want]

    So, my guess is (factoring out rho) theta = (y-y/2)/height * pi/2 and phi= x/width * pi

    right? (maybe. My basic math is really weak these days. I haven't done geometry/trig/polar since middle school).

  11. #11

  12. #12
    New Member
    Join Date
    Feb 2012
    Posts
    9

    Re: EquiRectangular Projection Help

    So, my guess is (factoring out rho) theta = (y-y/2)/height * pi/2 and phi= x/width * pi
    Ya that's correct. But that would give theta and phi OF the equirectangular image, isn't it? And that are all varying linearly. I want the theta and phi OF the original image(which is to be projected).

    (maybe. My basic math is really weak these days. I haven't done geometry/trig/polar since middle school).
    No it isn't. Even i thought the same trick.

  13. #13
    New Member
    Join Date
    Feb 2012
    Posts
    9

    Re: EquiRectangular Projection Help

    This has very good theory. Thanks..

    Still wondering, can you find any code or algorithm for applying on images?

  14. #14
    New Member
    Join Date
    Feb 2012
    Posts
    9

    Re: EquiRectangular Projection Help

    This video http://www.youtube.com/watch?v=3Ic5ZIf74Ls is explaining what's happening. But isn't there atleast one open source program which just do the distortion ?

  15. #15

    Join Date
    Jul 2010
    Location
    Philadelphia, PA USA
    Posts
    12
    Real Name
    Kirk Thibault

    Re: EquiRectangular Projection Help

    From: http://www.lroc.asu.edu/data/LRO-L-L...ALOG/DSMAP.CAT

    Code:
    LABEL_REVISION_NOTE               = "Ernest Bowman-Cisneros, 2011-03-08"
    RECORD_TYPE                       = STREAM
    SPACECRAFT_NAME                   = "LUNAR RECONNAISSANCE ORBITER"
    TARGET_NAME                       = "MOON"
    
    OBJECT                            = DATA_SET_MAP_PROJECTION
      DATA_SET_ID                     = "LRO-L-LROC-5-RDR-V1.0"
    
      OBJECT                          = DATA_SET_MAP_PROJECTION_INFO
        MAP_PROJECTION_TYPE           = "EQUIRECTANGULAR"
        MAP_PROJECTION_DESC           = "
    
        The EQUIRECTANGULAR projection is based on the formula for a
        sphere.  To eliminate confusion in the IMAGE_MAP_PROJECTION
        object we have set all three values, A_AXIS_RADIUS, B_AXIS_RADIUS,
        and C_AXIS_RADIUS to the same number, which is R below.
    
        The Equirectangular projection is a simple projection providing a
        linear relationship between the geographic coordinates of latitude
        and longitude and the Cartesian space of the map. In continuous
        form, the equations relating map coordinates (x, y) to geographic
        coordinates (Lat, Lon) are:
    
           x = R * (Lon - LonP) * COS(LatP)
           y = R * Lat
    
        where LonP is the center longitude of the map projection,
        LatP is the center latitude of the projection at which scale
        is given, and R the radius of the body at the center latitude.
        For the Moon R is assumed to be 1734.4 km.
    
        The inverse formulas for Lat and Lon from x and y position in the
        projection are:
    
           Lat = y / R
           Lon = LonP + x / (R * COS(LatP))
    
        The Conversion from (x, y) map coordinates to image array
        coordinates (sample, line) is standard for all map projections and
        is:
    
           x = (Sample - S0) * Scale
           y = (-L0 - Line) * Scale
    
        where Scale is the map resolution in km/pixel (located at the
        center planetocentric latitude of the projection). Line and
        Sample are the coordinates of the image array, and line (L0)
        and sample offsets (S0) are the respective image coordinate
        displacements from pixel (1,1) to the origin of the projection
        (x,y) = (0,0).  Please note, pixel (1,1) is spatially located
        in the upper-left corner of the image array.
    
        The equations from (x, y) to (Sample, Line) are:
    
           Sample =  x / Scale + S0 + 1
           Line   = -y / Scale - L0 + 1
    
        The equation from (Sample, Line) to (Lat, Lon) is:
    
           Lat = y / R
           y   = (1 - L0 - Line) * Scale
           Lat = (1 - L0 - Line) * Scale / R
    
           Lon = LonP + x / (R * COS(LatP))
           x   = (Sample - S0 - 1) * Scale
           Lon = LonP + (Sample - S0 - 1) * Scale/ (R * COS(LatP))
    
        The keywords corresponding to the Equirectangular projection
        parameters are located in the IMAGE_MAP_PROJECTION object found
        in the PDS labels. The keywords for each equation parameter are
        shown below:
    
           LonP  | CENTER_LONGITUDE
           LatP  | CENTER_LATITUDE
           L0    | LINE_PROJECTION_OFFSET
           S0    | SAMPLE_PROJECTION_OFFSET
           Scale | MAP_SCALE
           R     | A_AXIS_RADIUS (same as B_AXIS_RADIUS and
                 | C_AXIS_RADIUS) 
         "
      END_OBJECT                      = DATA_SET_MAP_PROJECTION_INFO
    
    
      OBJECT                          = DATA_SET_MAP_PROJECTION_INFO
        MAP_PROJECTION_TYPE           = "POLAR STEREOGRAPHIC"
        MAP_PROJECTION_DESC           = "
    
        The Polar Stereographic projection, used for observations
        acquired at higher latitudes, is ideally suited for observations
        near the poles as shape and scale distortion are minimized. The
        LROC derived products in Polar Stereographic projection use the
        ellipsoid form of the equations.  
    
        In continuous form, the spherical equations relating map
        coordinates (x, y) to planetocentric coordinates (Lat, Lon)
        are:
    
        North Polar Stereographic
           x =  2 * Rp * TAN(Pi / 4 - Lat / 2) * SIN(Lon - LonP)
           y = -2 * Rp * TAN(Pi / 4 - Lat / 2) * COS(Lon - LonP)
    
        South Polar Stereographic
           x =  2 * Rp * TAN(Pi / 4 + Lat / 2) * SIN(Lon - LonP)
           y =  2 * Rp * TAN(Pi / 4 + Lat / 2) * COS(Lon - LonP)
    
        Where LonP is the central longitude, LatP is the latitude of
        true scale and is always 90 or -90, and Rp is the polar radius of
        the Moon or 1,737.4 km.
    
        The spherical inverse formulas for Lat and Lon from X and Y
        position in the image array are:
    
           Lat = ARCSIN[COS(C) * SIN(LatP) + y * SIN(C) * COS(LatP) / P]
    
        North Polar Stereographic
           Lon = LonP + ARCTAN[x / (-y)]
    
        South Polar Stereographic
           Lon = LonP + ARCTAN[x / y]
    
        where:
           P = SQRT(x^2 + y^2)
           C = 2 * ARCTAN(P / 2 * Rp)
    
       recall:
    
           x = (Sample - S0 - 1) * Scale
           y = (1 - L0 - Line) * Scale
    
         The keywords corresponding to the equation parameters for the
         Polar Stereographic projection are located in the
         IMAGE_MAP_PROJECTION object found in the PDS labels. The
         keywords for each equation parameter are shown below.
    
           LonP  | CENTER_LONGITUDE
           LatP  | CENTER_LATITUDE
           L0    | LINE_PROJECTION_OFFSET
           S0    | SAMPLE_PROJECTION_OFFSET
           Scale | MAP_SCALE
           R     | A_AXIS_RADIUS (same as B_AXIS_RADIUS and
                 | C_AXIS_RADIUS) 
         "
       END_OBJECT                     = DATA_SET_MAP_PROJECTION_INFO
    
      OBJECT                          = DATA_SET_MAP_PROJECTION_INFO
        MAP_PROJECTION_TYPE           = "ORTHOGRAPHIC"
        MAP_PROJECTION_DESC           = "
    
         The ORTHOGRAPHIC projection preserves neither area nor angle and 
         is a perspective projection from an infinite distance.  Is also
         referred to a view from space.
         
         In continuous form, the spherical equations relating map coordinates
         (x, y) to planetocentric geographic coordinates (Lat, Lon) are:
    
            x  = R * COS(Lat) * SIN(Lon - LonP)
            y  = R * [(COS(LatP) * SIN(Lat)) - (SIN(LatP) * COS(Lat) * 
                 COS(Lon - LonP))]
         
         where LonP is the center longitude of the map projection, LatP is the
         center latitude of the projection at which the scale is given, and R
         is the radius of the body at the center latitude.  For the Moon, R is
         given as 1737.4 km.
         
         For the Orthographic projection, there are three special instances
         where the equation for solving for y is modified, while finding x is
         still found by the first equation:
         
         1. North Polar Orthographic, where LatP = 90:
    
            y = -R * COS(Lat) * COS(Lon - LonP)
         
         2. South Polar Orthographic, where LatP = -90:
    
            y = R * COS(Lat) * COS(Lon - LonP)
         
         3. Equatorial Orthographic, where LatP = 0:
    
            y = R * SIN(Lat)
         
         
         The spherical inverse formulas to derive Lat and Lon from a given x
         and y position in the projection are:
         
            Lat = ARCSIN[COS(C) * SIN(LatP) + (y * SIN(C) * COS(LatP)/P)]
            Lon = LonP + ARCTAN * [ (x * SIN(C)) / ((P * COS(LatP) * COS(C))
                  - (y * SIN(LatP) * SIN(C))]
         
         If LatP = 90:
    
            Lon = LonP + ARCTAN[x / (-y)]
         
         If LatP = -90:
    
            Lon = LonP + ARCTAN[x / y]
         
         where:
    
            P = SQRT(x2 + y2)
            C = ARCSIN(P/R)
         
         
         
         Standard map coordinates (x, y) to image array coordinates (Sample,
         Line):
    
            x = (Sample - S0 - 1) * Scale
            y = (1 - L0 - Line) * Scale
         
         where scale is...
              
              NOTE: if Scale is negative, the point value is NULL (the feature
                    is beyond the curvature of the body)
         
         
         The keywords corresponding to the Orthographic projection...
         
            LonP  | CENTER_LONGITUDE
            LatP  | CENTER_LATITUDE
            L0    | LINE_PROJECTION_OFFSET
            S0    | SAMPLE_PROJECTION_OFFSET
            Scale | MAP_SCALE
            R     | A_AXIS_RADIUS (same as B_AXIS_RADIUS and C_AXIS_RADIUS)
    
         "
       END_OBJECT                     = DATA_SET_MAP_PROJECTION_INFO
    
       OBJECT                         = DS_MAP_PROJECTION_REF_INFO
         REFERENCE_KEY_ID             = "SNYDER1987"
       END_OBJECT                     = DS_MAP_PROJECTION_REF_INFO
    
    END_OBJECT                        = DATA_SET_MAP_PROJECTION
    
    END

  16. #16

    Join Date
    Jul 2010
    Location
    Philadelphia, PA USA
    Posts
    12
    Real Name
    Kirk Thibault

    Re: EquiRectangular Projection Help

    And this is from the libpano source, in the file perspect.c

    Code:
    /* Panorama_Tools	-	Generate, Edit and Convert Panoramic Images
       Copyright (C) 1998,1999 - Helmut Dersch  der@fh-furtwangen.de
       
       This program is free software; you can redistribute it and/or modify
       it under the terms of the GNU General Public License as published by
       the Free Software Foundation; either version 2, or (at your option)
       any later version.
    
       This program is distributed in the hope that it will be useful,
       but WITHOUT ANY WARRANTY; without even the implied warranty of
       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
       GNU General Public License for more details.
    
       You should have received a copy of the GNU General Public License
       along with this program; if not, write to the Free Software
       Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
    
    /*------------------------------------------------------------*/
    
    #include "filter.h"
    
    
    // -------------------------- Functions ------------------------------------------------------
    
    void perspective(TrformStr *TrPtr, pPrefs *prefs) 	
    {
    	double 		v[3];										// auxilliary vector
    	double 		points_per_degree;							
    	double 		mt[3][3];
    	double  	alpha, beta, gammar; 				// Angles in rad
    	double		x_off, y_off, d;
    	double		a;
    	pt_int32	destwidth, destheight;
    	fDesc		fD;
    
    	void		*params[4];		// Parameters for perspective control functions
    	
    	params[0] = (void*)mt;
    	params[1] = (void*)&d;
    	params[2] = (void*)&x_off;
    	params[3] = (void*)&y_off;	
    
    
    
    	// Set destination image parameters
    
    
    	destwidth 		= prefs->width;
    	destheight 		= prefs->height;
    
    	if( destwidth <= 0 || destheight <= 0 )
    	{
    		TrPtr->success = 0;
    		PrintError( "Zero Destination Image Size" );
    		return;
    	}
    
    
    	if( SetDestImage(TrPtr, destwidth, destheight) != 0 ) 
    	{
    		TrPtr->success = 0;
    		PrintError( "Not enough Memory.");
    		return;
    	}
    	
    	
    	// Set parameters for perspective transformation
    	
    	
    	a = DEG_TO_RAD( prefs->hfov );
    	
    	alpha 	=  DEG_TO_RAD( prefs->y_beta );
    	beta  	=  DEG_TO_RAD( prefs->x_alpha );
    	gammar 	=  DEG_TO_RAD( prefs->gamma   );
    	
    	fD.func =(trfn)NULL; 
    
    	switch(prefs->format)
    	{
    		case _rectilinear:
    			if( a >= PI )
    			{
    				TrPtr->success = 0;
    				PrintError("HFOV must be smaller than 180 degrees");
    				return;
    			}
    			d = TrPtr->src->width / ( 2.0 * tan( a/2.0 ) );
    			if( prefs->unit_is_cart )
    			{
    				alpha =  atan( (prefs->y_beta - TrPtr->src->height/2.0 ) / d );
    				beta  = - atan( (prefs->x_alpha - TrPtr->src->width/2.0 ) / d );
    			}
    			fD.func = persp_rect;
    			break;
    		case _spherical_tp:
    			d = TrPtr->src->width / a;
    			if( prefs->unit_is_cart )
    			{
    				points_per_degree 		= ((double) TrPtr->src->width) / (a * 360 / (2 * PI)) ;
    				alpha	= ((TrPtr->src->height/2.0 - prefs->y_beta)/ points_per_degree) * 2 * PI / 360;
    				beta	= -((TrPtr->src->width/2.0  - prefs->x_alpha)/ points_per_degree) * 2 * PI / 360;
    
    			}
    			fD.func = persp_sphere;
    			break;
    	}
    
    	SetMatrix( alpha, beta, gammar , mt, 1 );
    
    		// Offset
    	
    	v[0] = 0.0; 
    	v[1] = 0.0;
    	v[2] = d;
    	matrix_mult( mt, v );
    	x_off =  v[0]*d/v[2];
    	y_off =  v[1]*d/v[2];
    
    
    	// Do transformation
    
    
    	if( fD.func != NULL)
    	{
    		fD.param = params;
    		//transFormEx( TrPtr, &fD, &fD, 0, 1 );
            transForm( TrPtr, &fD, 0 );
    	}
    	else
    		TrPtr->success = 0;
    
    	if( TrPtr->success == 0 && ! (TrPtr->mode & _destSupplied))	// Moved here
    			myfree( (void**)TrPtr->dest->data );
    
    }
    
    
    
    
    void 	SetPerspectiveDefaults( pPrefs *pP )
    {
    	pP->magic 			= 40;
    	pP->format			= _rectilinear;
    	pP->hfov			= 60; 
    	pP->x_alpha 		= 0.0;
    	pP->y_beta			= 0.0;
    	pP->gamma			= 0.0;
    	pP->unit_is_cart	= FALSE;
    	pP->width			= 500;
    	pP->height 			= 300;
    
    }

  17. #17

    Join Date
    Jul 2010
    Location
    Philadelphia, PA USA
    Posts
    12
    Real Name
    Kirk Thibault

    Re: EquiRectangular Projection Help

    And this from the libpano source, remap.c:

    Code:
    /* Panorama_Tools - Generate, Edit and Convert Panoramic Images
       Copyright (C) 1998,1999 - Helmut Dersch  der@fh-furtwangen.de
       
       This program is free software; you can redistribute it and/or modify
       it under the terms of the GNU General Public License as published by
       the Free Software Foundation; either version 2, or (at your option)
       any later version.
    
       This program is distributed in the hope that it will be useful,
       but WITHOUT ANY WARRANTY; without even the implied warranty of
       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
       GNU General Public License for more details.
    
       You should have received a copy of the GNU General Public License
       along with this program; if not, write to the Free Software
       Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
    
    /*------------------------------------------------------------*/
    
    #include "filter.h"
    
    
      
    
    void remap(TrformStr *TrPtr, rPrefs *r_prefs)
    {
      fDesc fD;                 // remapping function
      double  vars[3];          // variables required for calculation
                                  // vars[0] = distance d
                                  // vars[1] 
                                  // vars[2] 
      double  a,b;              // horizontal/vertical field of view in 'rad'
      int   destwidth=0, destheight=0;
    
      
      fD.param  = (void*) vars;
      fD.func   = (trfn)NULL;
      
      
      // Check for inconsistent values (should be extended!)
      
      if( r_prefs->hfov <= 0.0  )
      {
        TrPtr->success = 0;
        PrintError("Parameter Error");
        return;
      }
    
      
      // Set destination image parameters and parameters for remapping
      
      a = DEG_TO_RAD( r_prefs->hfov );
      
      switch(r_prefs->from)
      {
        case _rectilinear:  
          if( a >= PI )
          {
            TrPtr->success = 0;
            PrintError("Wrong FOV: Must be smaller than 180 degrees");
            return;
          }
          vars[0] = TrPtr->src->width / ( 2.0 * tan( a/2.0 ) );
          switch(r_prefs->to)
          {
            case _rectilinear:  TrPtr->success = 0;
                  PrintError("Same Mapping!");
                  return;
                  break;
            case _panorama   :  
                  destheight = TrPtr->src->height;
                  destwidth = (int)(a * vars[0] + 0.5);
                  fD.func = rect_pano;
                  break;
            case _equirectangular:
                  destheight  = (int)(2.0 * vars[0] * atan( TrPtr->src->height/(2*vars[0]) ) + 0.5);
                  destwidth = (int)(a * vars[0] + 0.5);
                  fD.func = rect_erect;
                  break;
            case _spherical_cp:TrPtr->success = 0;
                  PrintError("Use Fisheye Horizontal and Perspective");
                  return;
                  break;
            case _spherical_tp:
                  destheight  = (int)(2.0 * vars[0] * atan( TrPtr->src->height/(2*vars[0]) ) + 0.5);
                  destwidth   =  (int)(a * vars[0] + 0.5);
                  fD.func = rect_sphere_tp;
                  break;
            case _mirror:TrPtr->success = 0;
                  PrintError("Sorry, not yet available");
                  return;
                  break;
            default: break;
          }
          break;
        case _panorama:
          vars[0] = TrPtr->src->width / a;
          switch(r_prefs->to)
          {
            case _rectilinear: 
                  if( a >= PI )
                  {
                    TrPtr->success = 0;
                    PrintError("Wrong FOV: Must be smaller than 180 degrees");
                    return;
                  }
                  destheight = TrPtr->src->height;
                  destwidth = (int)(2.0 * tan( a/2.0 ) * vars[0] + 0.5);
                  fD.func = pano_rect;
                  break;
            case _panorama   :  TrPtr->success = 0;
                  PrintError("Same Mapping!");
                  return;
                  break;
            case _equirectangular:
                  destheight =  (int)(2 * vars[0] * atan( TrPtr->src->height/ (2*vars[0]) ));
                  destwidth = TrPtr->src->width;
                  fD.func = pano_erect;
                  break;
            case _spherical_cp:
                  TrPtr->success = 0;
                  PrintError("Sorry, not yet available");
                  return;
                  break;
            case _spherical_tp:             
                  destheight =  TrPtr->src->width ;//2 * vars[0] * atan( TrPtr->src->height/ (2*vars[0]) );
                  destwidth = TrPtr->src->width;
                  fD.func = pano_sphere_tp;
                  break;
            case _mirror:TrPtr->success = 0;
                  PrintError("Sorry, not yet available");
                  return;
                  break;
            default: break;
          }
          break;
        case _equirectangular:
          vars[0] = TrPtr->src->width / a;
          b       = TrPtr->src->height/ vars[0];
          switch(r_prefs->to)
          {
            case _rectilinear:
                  if( a >= PI || b >= PI )
                  {
                    TrPtr->success = 0;
                    PrintError("Wrong FOV: Must be smaller than 180 degrees");
                    return;
                  }
                  destheight = (int)(2 * vars[0] * tan( TrPtr->src->height/(2*vars[0]) ));
                  destwidth  = (int)(2 * vars[0] * tan( TrPtr->src->width/(2*vars[0]) ));
                  fD.func = erect_rect;
                  break;
            case _panorama   :
                  if( b >= PI )
                  {
                    TrPtr->success = 0;
                    PrintError("Wrong VFOV: Must be smaller than 180 degrees");
                    return;
                  }
                  destheight = (int)(2 * vars[0] * tan( TrPtr->src->height/(2*vars[0]) ));
                  destwidth = TrPtr->src->width;
                  fD.func = erect_pano;
                  break;
            case _equirectangular:TrPtr->success = 0;
                  PrintError("Same Mapping!");
                  return;
                  break;
            case _spherical_cp: 
                  destwidth   = 2 * TrPtr->src->height;
                  destheight  = 2 * TrPtr->src->height;
                  vars[1] = TrPtr->src->height/2; // vars[1] is midpoint
                  fD.func = erect_sphere_cp;
                  break;
            case _spherical_tp:
                  destwidth   = TrPtr->src->width;
                  destheight  = TrPtr->src->width;
                  fD.func = erect_sphere_tp;
                  break;
            case _mirror:TrPtr->success = 0;
                  PrintError("Sorry, not yet available");
                  return;
                  break;
            default: break;
          }
          break;
        case _spherical_cp:
          if( r_prefs->hfov > MAX_FISHEYE_FOV && r_prefs->vfov > MAX_FISHEYE_FOV ){
            TrPtr->success = 0;
            PrintError("Fisheye lens processing limited to fov <= %lg", MAX_FISHEYE_FOV);
            return;
          }
          vars[0] = TrPtr->src->width / a;
          switch(r_prefs->to)
          {
            case _rectilinear:TrPtr->success = 0;
                  PrintError("Sorry, not yet available");
                  return; 
                  break;
            case _panorama   :
                  if(r_prefs->vfov >= 180.0 )
                  {
                    TrPtr->success = 0;
                    PrintError("Wrong VFOV: Must be smaller than 180 degrees");
                    return;
                  }
                  destheight = (int)(PI * vars[0] * tan(r_prefs->vfov * PI / 360.0));
                  destwidth  = (int)(PI * vars[0] * PI);
                  fD.func    = sphere_cp_pano;
                  break;
            case _equirectangular:
                  destheight = (int)((TrPtr->src->width > TrPtr->src->height ? 
                                 TrPtr->src->width/2: TrPtr->src->height/2) * PI / 2.0);
                  destwidth  = (int)(vars[0] *  PI * PI);
                  vars[1]    = destheight / 2;
    
                  fD.func = sphere_cp_erect;
                  break;
            case _spherical_cp:TrPtr->success = 0;
                  PrintError("Same Mapping!");
                  return;
                  break;
            case _spherical_tp:TrPtr->success = 0;
                  PrintError("Use tool perspective.");
                  return;
                  break;
            case _mirror:
                  vars[1] = TrPtr->src->width / (2 * sin(a/4.0)) ; // Radius of mirror
                  destwidth  = TrPtr->src->width ;
                  destheight = TrPtr->src->height ;
                  fD.func = sphere_cp_mirror;
                  break;
            default: break;
          }
          break;
        case _spherical_tp:
          if( r_prefs->hfov > MAX_FISHEYE_FOV && r_prefs->vfov > MAX_FISHEYE_FOV ){
            TrPtr->success = 0;
            PrintError("Fisheye lens processing limited to fov <= %lg", MAX_FISHEYE_FOV);
            return;
          }
          vars[0] = TrPtr->src->width / a;
          b = TrPtr->src->height / vars[0]; 
          switch(r_prefs->to)
          {
            case _rectilinear:
                  if( a >= PI || b >= PI )
                  {
                    TrPtr->success = 0;
                    PrintError("Wrong FOV: Must be smaller than 180 degrees");
                    return;
                  }
                  destheight    = (int)(2.0 * vars[0] * tan( TrPtr->src->height / (2.0*vars[0]) ) + 0.5);
                  destwidth     = (int)(2.0 * tan( a/2.0 ) * vars[0] + 0.5);
                  fD.func = sphere_tp_rect;
                  break;
            case _panorama   :
                  if(  b >= PI )
                  {
                    TrPtr->success = 0;
                    PrintError("Wrong VFOV: Must be smaller than 180 degrees");
                    return;
                  }
                  destheight  = (int)(2.0 * vars[0] * tan( TrPtr->src->height / (2.0*vars[0]) ) + 0.5);
                  destwidth   = TrPtr->src->width;
                  fD.func = sphere_tp_pano;
                  break;
            case _equirectangular:
                  destheight  = TrPtr->src->height ;
                  destwidth   = TrPtr->src->width;
                  vars[1]             = destheight / 2;
                  fD.func = sphere_tp_erect;
                  break;
            case _spherical_cp:TrPtr->success = 0;
                  PrintError("Use tool perspective.");
                  return;
                  break;
            case _spherical_tp:TrPtr->success = 0;
                  PrintError( "Same Mapping!");
                  return;
                  break;
            case _mirror:TrPtr->success = 0;
                  PrintError( "Sorry, not yet available");
                  return;
                  break;
            default: break;
          }
          break;
        case _mirror:
          vars[1] = TrPtr->src->width / (2 * sin(a/4.0)) ; // Radius of mirror
          vars[0] = TrPtr->src->width / a;
          switch(r_prefs->to)
          {
            case _rectilinear:TrPtr->success = 0;
                  PrintError("Sorry, not yet available");
                  return;
                  break;
            case _panorama   :              
                  if(r_prefs->vfov >= 180.0 )
                  {
                    TrPtr->success = 0;
                    PrintError("Wrong VFOV: Must be smaller than 180 degrees");
                    return;
                  }
                  destheight = (int)(PI * vars[0] * tan(r_prefs->vfov * PI / 360.0));
                  destwidth  = (int)(PI * vars[0] *  PI);
                  fD.func = mirror_pano;
                  break;
            case _equirectangular:
                  destwidth  = (int)(vars[0] *  PI * PI);
                  destheight = (int)(PI * vars[0] * a / 4.0);
                  vars[2] = destheight / 2.0;
                  fD.func = mirror_erect;
                  break;
            case _spherical_cp:
                  destwidth  = TrPtr->src->width ;
                  destheight = TrPtr->src->height ;
                  fD.func = mirror_sphere_cp;
                  break;
            case _spherical_tp:TrPtr->success = 0;
                  PrintError( "Sorry, not yet available");
                  return;
                  break;
            case _mirror:TrPtr->success = 0;
                  PrintError( "Same Mapping!");
                  return;
                  break;
            default: break;
          }
          break;
        default: break;
      }
    
    
      
      if( SetDestImage(TrPtr, destwidth, destheight) != 0 ) 
      {
        TrPtr->success = 0;
        PrintError( "Not enough Memory.");
        return; 
      }
      
      // Do transformation
    
      if( fD.func != NULL)
      {
        transFormEx( TrPtr, &fD, &fD, 0, 1 );
        //transForm( TrPtr, &fD, 0 );
      }
      else
        TrPtr->success = 0;
    
      if( TrPtr->success == 0 && ! (TrPtr->mode & _destSupplied)) // Moved here
              myfree( (void**)TrPtr->dest->data );
    
    }
    
    void SetRemapDefaults( rPrefs *rP )
    {
      rP->magic   = 30;       // Magic number for file validity check
      rP->from  = _rectilinear;
      rP->to    = _panorama;
      rP->hfov  = 60.0;
      rP->vfov  = 60.0;
    
    }

  18. #18
    New Member
    Join Date
    Feb 2012
    Posts
    9

    Re: EquiRectangular Projection Help

    hey kirkt , first of all thanks a lot for helping..
    I have came across those before. The first one you posted, I saw that a few days ago,
    but i didnt understand why they have defined following relationship :
    Code:
        The Equirectangular projection is a simple projection providing a
        linear relationship between the geographic coordinates of latitude
        and longitude and the Cartesian space of the map. In continuous
        form, the equations relating map coordinates (x, y) to geographic
        coordinates (Lat, Lon) are:
    
           x = R * (Lon - LonP) * COS(LatP)
           y = R * Lat
    because it should be linear relation from lat/lon to x,y then why introduced the cos factor?
    and for last two i have seen over 10 times, and +1 as you posted in hope that I understand something but all in all, it seems very cryptic to me. I don't think so the perspect.c is responsible for the equirectangular projection(i may be wrong). Remap.c attracted a lot of my attention but the lines
    Code:
     double  vars[3];          // variables required for calculation
                                  // vars[0] = distance d
                                  // vars[1] 
                                  // vars[2]
    and..
    Code:
    destheight  = (int)(2.0 * vars[0] * atan( TrPtr->src->height/(2*vars[0]) ) + 0.5);
                  destwidth = (int)(a * vars[0] + 0.5);
    were beyond my understanding. Can you? and the biggest nonsense thing i believe is why in the hell didn't they include enough comments so that the code doesn't look alien to others !

  19. #19
    New Member
    Join Date
    Sep 2012
    Posts
    1

    Re: EquiRectangular Projection Help

    Hi there,

    I'd like to write or find a javascript or php converter: Equirectangular to cube faces.

    Any help?
    Thanks

  20. #20

    Re: EquiRectangular Projection Help

    As you climb up the Lat the Long will change according to Cos(Lat)

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •