head	8.7;
access;
symbols;
locks; strict;
comment	@ * @;


8.7
date	2026.05.11.12.01.10;	author mcalabre;	state Exp;
branches;
next	8.6;

8.6
date	2026.03.29.13.53.56;	author mcalabre;	state Exp;
branches
	8.6.1.1;
next	8.5;

8.5
date	2025.12.06.13.47.41;	author mcalabre;	state Exp;
branches
	8.5.1.1;
next	8.4;

8.4
date	2024.10.28.13.56.16;	author mcalabre;	state Exp;
branches
	8.4.1.1;
next	8.3;

8.3
date	2024.05.13.16.33.00;	author mcalabre;	state Exp;
branches
	8.3.1.1;
next	8.2;

8.2
date	2023.11.16.10.00.29;	author mcalabre;	state Exp;
branches
	8.2.1.1;
next	8.1;

8.1
date	2023.07.05.17.12.07;	author mcalabre;	state Exp;
branches
	8.1.1.1;
next	8.0;

8.0
date	2023.07.01.06.15.04;	author mcalabre;	state Exp;
branches
	8.0.1.1;
next	7.13;

7.13
date	2022.10.07.03.43.35;	author mcalabre;	state Exp;
branches
	7.13.1.1;
next	7.12;

7.12
date	2022.09.09.04.57.58;	author mcalabre;	state Exp;
branches
	7.12.1.1;
next	7.11;

7.11
date	2022.04.26.06.13.52;	author mcalabre;	state Exp;
branches
	7.11.1.1;
next	7.10;

7.10
date	2022.04.23.14.25.15;	author mcalabre;	state Exp;
branches
	7.10.1.1;
next	7.9;

7.9
date	2022.03.25.15.14.48;	author mcalabre;	state Exp;
branches
	7.9.1.1;
next	7.8;

7.8
date	2022.03.25.06.11.49;	author mcalabre;	state Exp;
branches
	7.8.1.1;
next	7.7;

7.7
date	2021.07.12.06.36.49;	author mcalabre;	state Exp;
branches
	7.7.1.1;
next	7.6;

7.6
date	2021.04.13.12.57.01;	author mcalabre;	state Exp;
branches
	7.6.1.1;
next	7.5;

7.5
date	2021.03.20.05.54.58;	author mcalabre;	state Exp;
branches
	7.5.1.1;
next	7.4;

7.4
date	2021.01.31.02.24.51;	author mcalabre;	state Exp;
branches
	7.4.1.1;
next	7.3;

7.3
date	2020.06.03.03.37.02;	author mcalabre;	state Exp;
branches
	7.3.1.1;
next	7.2;

7.2
date	2020.03.09.07.31.23;	author mcalabre;	state Exp;
branches
	7.2.1.1;
next	7.1;

7.1
date	2019.12.31.13.25.19;	author mcalabre;	state Exp;
branches
	7.1.1.1;
next	6.4;

6.4
date	2019.08.15.09.30.18;	author mcalabre;	state Exp;
branches
	6.4.1.1;
next	6.3;

6.3
date	2019.07.12.07.33.39;	author mcalabre;	state Exp;
branches
	6.3.1.1;
next	6.2;

6.2
date	2018.10.20.10.03.13;	author mcalabre;	state Exp;
branches
	6.2.1.1;
next	6.1;

6.1
date	2018.10.19.08.35.17;	author mcalabre;	state Exp;
branches
	6.1.1.1;
next	5.20;

5.20
date	2018.10.05.05.32.41;	author mcalabre;	state Exp;
branches
	5.20.1.1;
next	5.19;

5.19
date	2018.07.26.15.37.04;	author mcalabre;	state Exp;
branches
	5.19.1.1;
next	5.18;

5.18
date	2018.01.10.08.32.14;	author mcalabre;	state Exp;
branches
	5.18.1.1;
next	5.17;

5.17
date	2017.09.18.08.44.23;	author mcalabre;	state Exp;
branches
	5.17.1.1;
next	5.16;

5.16
date	2017.01.15.04.25.01;	author mcalabre;	state Exp;
branches
	5.16.1.1;
next	5.15;

5.15
date	2016.04.05.12.55.10;	author mcalabre;	state Exp;
branches
	5.15.1.1;
next	5.14;

5.14
date	2016.02.07.10.49.31;	author mcalabre;	state Exp;
branches
	5.14.1.1;
next	5.13;

5.13
date	2016.01.26.08.51.13;	author mcalabre;	state Exp;
branches
	5.13.1.1;
next	5.12;

5.12
date	2015.11.15.02.13.00;	author mcalabre;	state Exp;
branches
	5.12.1.1;
next	5.11;

5.11
date	2015.10.18.09.13.05;	author mcalabre;	state Exp;
branches
	5.11.1.1;
next	5.10;

5.10
date	2015.10.09.08.19.15;	author mcalabre;	state Exp;
branches
	5.10.1.1;
next	5.9;

5.9
date	2015.07.21.09.20.01;	author mcalabre;	state Exp;
branches
	5.9.1.1;
next	5.8;

5.8
date	2015.07.08.11.03.59;	author mcalabre;	state Exp;
branches
	5.8.1.1;
next	5.7;

5.7
date	2015.06.29.02.44.16;	author mcalabre;	state Exp;
branches
	5.7.1.1;
next	5.6;

5.6
date	2015.06.14.07.11.24;	author mcalabre;	state Exp;
branches
	5.6.1.1;
next	5.5;

5.5
date	2015.05.05.13.16.31;	author mcalabre;	state Exp;
branches
	5.5.1.1;
next	5.4;

5.4
date	2015.04.21.14.41.05;	author mcalabre;	state Exp;
branches
	5.4.1.1;
next	5.3;

5.3
date	2015.04.21.02.50.51;	author mcalabre;	state Exp;
branches
	5.3.1.1;
next	5.2;

5.2
date	2015.04.15.12.35.07;	author mcalabre;	state Exp;
branches
	5.2.1.1;
next	5.1;

5.1
date	2015.04.07.10.56.36;	author mcalabre;	state Exp;
branches
	5.1.1.1;
next	5.0;

5.0
date	2015.04.05.12.24.59;	author mcalabre;	state Exp;
branches
	5.0.1.1;
next	4.25;

4.25
date	2014.12.14.14.29.36;	author mcalabre;	state Exp;
branches
	4.25.1.1;
next	4.24;

4.24
date	2014.09.18.15.25.00;	author mcalabre;	state Exp;
branches
	4.24.1.1;
next	4.23;

4.23
date	2014.05.13.05.50.51;	author mcalabre;	state Exp;
branches
	4.23.1.1;
next	4.22;

4.22
date	2014.04.12.15.03.52;	author mcalabre;	state Exp;
branches
	4.22.1.1;
next	4.21;

4.21
date	2014.03.24.05.12.27;	author mcalabre;	state Exp;
branches
	4.21.1.1;
next	4.20;

4.20
date	2013.12.18.05.42.49;	author mcalabre;	state Exp;
branches
	4.20.1.1;
next	4.19;

4.19
date	2013.09.29.14.17.51;	author mcalabre;	state Exp;
branches
	4.19.1.1;
next	4.18;

4.18
date	2013.07.13.10.00.04;	author mcalabre;	state Exp;
branches
	4.18.1.1;
next	4.17;

4.17
date	2013.01.29.05.29.20;	author cal103;	state Exp;
branches
	4.17.1.1;
next	4.16;

4.16
date	2012.11.07.04.42.44;	author cal103;	state Exp;
branches
	4.16.1.1;
next	4.15;

4.15
date	2012.09.26.14.26.05;	author cal103;	state Exp;
branches
	4.15.1.1;
next	4.14;

4.14
date	2012.07.13.10.02.27;	author cal103;	state Exp;
branches
	4.14.1.1;
next	4.13;

4.13
date	2012.03.14.07.39.30;	author cal103;	state Exp;
branches
	4.13.1.1;
next	4.12;

4.12
date	2012.02.29.07.57.56;	author cal103;	state Exp;
branches
	4.12.1.1;
next	4.11;

4.11
date	2012.02.20.23.30.02;	author cal103;	state Exp;
branches
	4.11.1.1;
next	4.10;

4.10
date	2012.02.05.23.41.44;	author cal103;	state Exp;
branches
	4.10.1.1;
next	4.9;

4.9
date	2012.01.24.05.40.29;	author cal103;	state Exp;
branches
	4.9.1.1;
next	4.8;

4.8
date	2011.08.15.08.05.53;	author cal103;	state Exp;
branches
	4.8.1.1;
next	4.7;

4.7
date	2011.02.07.07.03.42;	author cal103;	state Exp;
branches
	4.7.1.1;
next	4.6;

4.6
date	2010.11.16.06.15.31;	author cal103;	state Exp;
branches
	4.6.1.1;
next	4.5;

4.5
date	2010.07.16.07.01.25;	author cal103;	state Exp;
branches
	4.5.1.1;
next	4.4;

4.4
date	2009.08.06.07.41.33;	author cal103;	state Exp;
branches
	4.4.1.1;
next	4.3;

4.3
date	2007.12.27.05.41.36;	author cal103;	state Exp;
branches
	4.3.1.1;
next	4.2;

4.2
date	2005.09.21.13.21.57;	author cal103;	state Exp;
branches
	4.2.1.1;
next	4.1;

4.1
date	2005.08.25.07.48.36;	author cal103;	state Exp;
branches;
next	4.0;

4.0
date	2005.02.04.05.10.22;	author cal103;	state Exp;
branches;
next	3.6;

3.6
date	2004.08.25.04.07.22;	author cal103;	state Exp;
branches;
next	3.5;

3.5
date	2004.06.28.02.06.59;	author mcalabre;	state Exp;
branches;
next	3.4;

3.4
date	2004.02.11.00.15.03;	author mcalabre;	state Exp;
branches;
next	3.3;

3.3
date	2003.10.21.08.52.49;	author mcalabre;	state Exp;
branches;
next	3.2;

3.2
date	2003.09.09.04.04.04;	author mcalabre;	state Exp;
branches;
next	3.1;

3.1
date	2003.04.28.03.50.41;	author mcalabre;	state Exp;
branches;
next	3.0;

3.0
date	2003.04.01.04.10.53;	author mcalabre;	state Exp;
branches;
next	2.20;

2.20
date	2002.04.03.01.25.29;	author mcalabre;	state Exp;
branches;
next	2.19;

2.19
date	2001.11.16.02.58.31;	author mcalabre;	state Exp;
branches;
next	2.18;

2.18
date	2000.12.06.00.56.16;	author mcalabre;	state Exp;
branches;
next	2.17;

2.17
date	2000.05.10.04.44.05;	author mcalabre;	state Exp;
branches;
next	2.16;

2.16
date	2000.02.01.04.16.40;	author mcalabre;	state Exp;
branches;
next	2.15;

2.15
date	99.12.13.07.27.05;	author mcalabre;	state Exp;
branches;
next	2.14;

2.14
date	99.11.19.05.50.05;	author mcalabre;	state Exp;
branches;
next	2.13;

2.13
date	99.11.19.00.20.18;	author mcalabre;	state Exp;
branches;
next	2.12;

2.12
date	99.11.19.00.14.19;	author mcalabre;	state Exp;
branches;
next	2.11;

2.11
date	99.04.09.05.05.56;	author mcalabre;	state Exp;
branches;
next	2.10;

2.10
date	99.04.06.07.57.37;	author mcalabre;	state Exp;
branches;
next	2.9;

2.9
date	98.02.25.07.05.50;	author mcalabre;	state Exp;
branches;
next	2.8;

2.8
date	98.01.30.00.27.49;	author mcalabre;	state Exp;
branches;
next	2.7;

2.7
date	97.03.19.05.33.01;	author mcalabre;	state Exp;
branches;
next	2.6;

2.6
date	97.01.02.22.08.43;	author mcalabre;	state Exp;
branches;
next	2.5;

2.5
date	96.09.10.06.33.59;	author mcalabre;	state Exp;
branches;
next	2.4;

2.4
date	96.05.24.07.25.36;	author mcalabre;	state Exp;
branches;
next	2.3;

2.3
date	96.05.07.20.13.50;	author mcalabre;	state Exp;
branches;
next	2.2;

2.2
date	95.12.22.02.38.33;	author mcalabre;	state Exp;
branches;
next	2.1;

2.1
date	95.11.09.03.15.35;	author mcalabre;	state Exp;
branches;
next	2.0;

2.0
date	95.09.11.09.06.43;	author mcalabre;	state Exp;
branches;
next	1.3;

1.3
date	95.09.11.09.06.18;	author mcalabre;	state Exp;
branches;
next	1.2;

1.2
date	95.09.11.08.31.21;	author mcalabre;	state Exp;
branches;
next	1.1;

1.1
date	95.01.31.03.13.15;	author mcalabre;	state Exp;
branches;
next	;

4.2.1.1
date	2005.12.05.02.39.43;	author cal103;	state Exp;
branches;
next	4.2.1.2;

4.2.1.2
date	2006.06.01.07.34.15;	author cal103;	state Exp;
branches;
next	4.2.1.3;

4.2.1.3
date	2007.06.29.01.45.55;	author cal103;	state Exp;
branches;
next	4.2.1.4;

4.2.1.4
date	2007.07.11.02.01.30;	author cal103;	state Exp;
branches;
next	4.2.1.5;

4.2.1.5
date	2007.07.27.00.44.21;	author cal103;	state Exp;
branches;
next	4.2.1.6;

4.2.1.6
date	2007.07.27.05.50.38;	author cal103;	state Exp;
branches;
next	4.2.1.7;

4.2.1.7
date	2007.08.08.07.20.03;	author cal103;	state Exp;
branches;
next	4.2.1.8;

4.2.1.8
date	2007.12.03.05.02.17;	author cal103;	state Exp;
branches;
next	4.2.1.9;

4.2.1.9
date	2007.12.26.03.00.45;	author cal103;	state Exp;
branches;
next	;

4.3.1.1
date	2007.12.27.13.23.47;	author cal103;	state Exp;
branches;
next	4.3.1.2;

4.3.1.2
date	2009.07.22.04.28.39;	author cal103;	state Exp;
branches;
next	4.3.1.3;

4.3.1.3
date	2009.07.27.06.05.48;	author cal103;	state Exp;
branches;
next	4.3.1.4;

4.3.1.4
date	2009.07.28.07.34.19;	author cal103;	state Exp;
branches;
next	4.3.1.5;

4.3.1.5
date	2009.08.05.05.21.01;	author cal103;	state Exp;
branches;
next	;

4.4.1.1
date	2009.08.10.08.52.49;	author cal103;	state Exp;
branches;
next	4.4.1.2;

4.4.1.2
date	2010.01.19.03.42.50;	author cal103;	state Exp;
branches;
next	;

4.5.1.1
date	2010.07.16.07.05.31;	author cal103;	state Exp;
branches;
next	;

4.6.1.1
date	2010.11.16.06.16.19;	author cal103;	state Exp;
branches;
next	4.6.1.2;

4.6.1.2
date	2011.01.14.06.33.16;	author cal103;	state Exp;
branches;
next	4.6.1.3;

4.6.1.3
date	2011.01.19.23.49.02;	author cal103;	state Exp;
branches;
next	4.6.1.4;

4.6.1.4
date	2011.01.25.00.04.13;	author cal103;	state Exp;
branches;
next	4.6.1.5;

4.6.1.5
date	2011.01.25.00.35.11;	author cal103;	state Exp;
branches;
next	;

4.7.1.1
date	2011.02.07.07.04.22;	author cal103;	state Exp;
branches;
next	4.7.1.2;

4.7.1.2
date	2011.07.21.03.43.08;	author cal103;	state Exp;
branches;
next	4.7.1.3;

4.7.1.3
date	2011.08.09.02.43.50;	author cal103;	state Exp;
branches;
next	4.7.1.4;

4.7.1.4
date	2011.08.10.04.24.32;	author cal103;	state Exp;
branches;
next	4.7.1.5;

4.7.1.5
date	2011.08.12.05.42.29;	author cal103;	state Exp;
branches;
next	;

4.8.1.1
date	2011.08.15.08.07.06;	author cal103;	state Exp;
branches;
next	4.8.1.2;

4.8.1.2
date	2011.11.17.03.08.29;	author cal103;	state Exp;
branches;
next	4.8.1.3;

4.8.1.3
date	2012.01.24.05.23.06;	author cal103;	state Exp;
branches;
next	;

4.9.1.1
date	2012.01.24.05.41.45;	author cal103;	state Exp;
branches;
next	;

4.10.1.1
date	2012.02.05.23.42.46;	author cal103;	state Exp;
branches;
next	;

4.11.1.1
date	2012.02.20.23.31.13;	author cal103;	state Exp;
branches;
next	;

4.12.1.1
date	2012.02.29.07.59.10;	author cal103;	state Exp;
branches;
next	4.12.1.2;

4.12.1.2
date	2012.03.14.06.38.34;	author cal103;	state Exp;
branches;
next	;

4.13.1.1
date	2012.03.14.07.40.37;	author cal103;	state Exp;
branches;
next	4.13.1.2;

4.13.1.2
date	2012.07.12.15.31.21;	author cal103;	state Exp;
branches;
next	4.13.1.3;

4.13.1.3
date	2012.07.13.03.34.20;	author cal103;	state Exp;
branches;
next	;

4.14.1.1
date	2012.07.13.10.04.44;	author cal103;	state Exp;
branches;
next	;

4.15.1.1
date	2012.09.26.14.27.51;	author cal103;	state Exp;
branches;
next	;

4.16.1.1
date	2012.11.07.04.45.56;	author cal103;	state Exp;
branches;
next	4.16.1.2;

4.16.1.2
date	2013.01.29.05.09.44;	author cal103;	state Exp;
branches;
next	;

4.17.1.1
date	2013.01.29.05.32.32;	author cal103;	state Exp;
branches;
next	4.17.1.2;

4.17.1.2
date	2013.07.12.04.05.47;	author mcalabre;	state Exp;
branches;
next	;

4.18.1.1
date	2013.07.13.10.02.37;	author mcalabre;	state Exp;
branches;
next	4.18.1.2;

4.18.1.2
date	2013.09.29.08.52.42;	author mcalabre;	state Exp;
branches;
next	;

4.19.1.1
date	2013.09.29.14.20.38;	author mcalabre;	state Exp;
branches;
next	4.19.1.2;

4.19.1.2
date	2013.10.06.04.01.53;	author mcalabre;	state Exp;
branches;
next	;

4.20.1.1
date	2013.12.18.05.46.55;	author mcalabre;	state Exp;
branches;
next	4.20.1.2;

4.20.1.2
date	2014.03.21.06.32.19;	author mcalabre;	state Exp;
branches;
next	4.20.1.3;

4.20.1.3
date	2014.03.22.05.37.04;	author mcalabre;	state Exp;
branches;
next	4.20.1.4;

4.20.1.4
date	2014.03.24.03.13.46;	author mcalabre;	state Exp;
branches;
next	;

4.21.1.1
date	2014.03.24.05.15.28;	author mcalabre;	state Exp;
branches;
next	4.21.1.2;

4.21.1.2
date	2014.04.12.14.39.52;	author mcalabre;	state Exp;
branches;
next	;

4.22.1.1
date	2014.04.12.15.06.32;	author mcalabre;	state Exp;
branches;
next	;

4.23.1.1
date	2014.05.13.05.53.49;	author mcalabre;	state Exp;
branches;
next	;

4.24.1.1
date	2014.09.18.15.28.09;	author mcalabre;	state Exp;
branches;
next	;

4.25.1.1
date	2014.12.14.14.32.45;	author mcalabre;	state Exp;
branches;
next	4.25.1.2;

4.25.1.2
date	2015.01.06.01.01.06;	author mcalabre;	state Exp;
branches;
next	4.25.1.3;

4.25.1.3
date	2015.03.05.14.39.08;	author mcalabre;	state Exp;
branches;
next	4.25.1.4;

4.25.1.4
date	2015.04.03.01.51.43;	author mcalabre;	state Exp;
branches;
next	;

5.0.1.1
date	2015.04.05.12.28.00;	author mcalabre;	state Exp;
branches;
next	;

5.1.1.1
date	2015.04.07.11.01.10;	author mcalabre;	state Exp;
branches;
next	;

5.2.1.1
date	2015.04.15.12.39.14;	author mcalabre;	state Exp;
branches;
next	;

5.3.1.1
date	2015.04.21.02.54.02;	author mcalabre;	state Exp;
branches;
next	;

5.4.1.1
date	2015.04.21.14.44.28;	author mcalabre;	state Exp;
branches;
next	;

5.5.1.1
date	2015.05.05.13.21.00;	author mcalabre;	state Exp;
branches;
next	;

5.6.1.1
date	2015.06.14.07.14.44;	author mcalabre;	state Exp;
branches;
next	5.6.1.2;

5.6.1.2
date	2015.06.18.08.12.20;	author mcalabre;	state Exp;
branches;
next	;

5.7.1.1
date	2015.06.29.02.47.24;	author mcalabre;	state Exp;
branches;
next	5.7.1.2;

5.7.1.2
date	2015.07.08.07.12.41;	author mcalabre;	state Exp;
branches;
next	;

5.8.1.1
date	2015.07.08.11.07.18;	author mcalabre;	state Exp;
branches;
next	;

5.9.1.1
date	2015.07.21.09.28.07;	author mcalabre;	state Exp;
branches;
next	;

5.10.1.1
date	2015.10.09.08.22.35;	author mcalabre;	state Exp;
branches;
next	;

5.11.1.1
date	2015.10.18.09.16.27;	author mcalabre;	state Exp;
branches;
next	;

5.12.1.1
date	2015.11.15.02.16.14;	author mcalabre;	state Exp;
branches;
next	5.12.1.2;

5.12.1.2
date	2016.01.25.05.17.04;	author mcalabre;	state Exp;
branches;
next	;

5.13.1.1
date	2016.01.26.08.54.32;	author mcalabre;	state Exp;
branches;
next	;

5.14.1.1
date	2016.02.07.10.52.44;	author mcalabre;	state Exp;
branches;
next	;

5.15.1.1
date	2016.04.05.12.58.35;	author mcalabre;	state Exp;
branches;
next	5.15.1.2;

5.15.1.2
date	2017.01.15.04.13.33;	author mcalabre;	state Exp;
branches;
next	;

5.16.1.1
date	2017.01.15.04.28.59;	author mcalabre;	state Exp;
branches;
next	;

5.17.1.1
date	2017.09.18.08.45.59;	author mcalabre;	state Exp;
branches;
next	5.17.1.2;

5.17.1.2
date	2018.01.10.08.25.34;	author mcalabre;	state Exp;
branches;
next	;

5.18.1.1
date	2018.01.10.08.33.04;	author mcalabre;	state Exp;
branches;
next	5.18.1.2;

5.18.1.2
date	2018.07.25.00.22.45;	author mcalabre;	state Exp;
branches;
next	;

5.19.1.1
date	2018.07.26.15.41.40;	author mcalabre;	state Exp;
branches;
next	;

5.20.1.1
date	2018.10.05.05.33.33;	author mcalabre;	state Exp;
branches;
next	;

6.1.1.1
date	2018.10.19.08.36.15;	author mcalabre;	state Exp;
branches;
next	;

6.2.1.1
date	2018.10.20.10.04.15;	author mcalabre;	state Exp;
branches;
next	6.2.1.2;

6.2.1.2
date	2019.05.10.01.56.50;	author mcalabre;	state Exp;
branches;
next	6.2.1.3;

6.2.1.3
date	2019.07.08.03.29.49;	author mcalabre;	state Exp;
branches;
next	6.2.1.4;

6.2.1.4
date	2019.07.08.04.54.14;	author mcalabre;	state Exp;
branches;
next	;

6.3.1.1
date	2019.07.12.07.34.37;	author mcalabre;	state Exp;
branches;
next	;

6.4.1.1
date	2019.08.15.09.31.29;	author mcalabre;	state Exp;
branches;
next	6.4.1.2;

6.4.1.2
date	2019.12.16.04.21.05;	author mcalabre;	state Exp;
branches;
next	6.4.1.3;

6.4.1.3
date	2019.12.31.03.28.03;	author mcalabre;	state Exp;
branches;
next	;

7.1.1.1
date	2019.12.31.13.28.19;	author mcalabre;	state Exp;
branches;
next	;

7.2.1.1
date	2020.03.09.07.34.50;	author mcalabre;	state Exp;
branches;
next	;

7.3.1.1
date	2020.06.03.03.38.10;	author mcalabre;	state Exp;
branches;
next	7.3.1.2;

7.3.1.2
date	2020.08.17.11.19.09;	author mcalabre;	state Exp;
branches;
next	7.3.1.3;

7.3.1.3
date	2021.01.19.14.09.10;	author mcalabre;	state Exp;
branches;
next	7.3.1.4;

7.3.1.4
date	2021.01.28.12.29.30;	author mcalabre;	state Exp;
branches;
next	;

7.4.1.1
date	2021.01.31.02.26.24;	author mcalabre;	state Exp;
branches;
next	;

7.5.1.1
date	2021.03.20.05.56.42;	author mcalabre;	state Exp;
branches;
next	7.5.1.2;

7.5.1.2
date	2021.04.13.09.21.05;	author mcalabre;	state Exp;
branches;
next	;

7.6.1.1
date	2021.04.13.13.00.35;	author mcalabre;	state Exp;
branches;
next	;

7.7.1.1
date	2021.07.12.06.38.27;	author mcalabre;	state Exp;
branches;
next	7.7.1.2;

7.7.1.2
date	2022.03.25.06.05.59;	author mcalabre;	state Exp;
branches;
next	;

7.8.1.1
date	2022.03.25.06.14.14;	author mcalabre;	state Exp;
branches;
next	;

7.9.1.1
date	2022.03.25.15.16.40;	author mcalabre;	state Exp;
branches;
next	;

7.10.1.1
date	2022.04.23.14.26.54;	author mcalabre;	state Exp;
branches;
next	;

7.11.1.1
date	2022.04.26.06.15.32;	author mcalabre;	state Exp;
branches;
next	7.11.1.2;

7.11.1.2
date	2022.09.04.07.16.21;	author mcalabre;	state Exp;
branches;
next	;

7.12.1.1
date	2022.09.09.05.00.36;	author mcalabre;	state Exp;
branches;
next	;

7.13.1.1
date	2022.10.07.03.45.47;	author mcalabre;	state Exp;
branches;
next	7.13.1.2;

7.13.1.2
date	2023.06.15.04.17.19;	author mcalabre;	state Exp;
branches;
next	;

8.0.1.1
date	2023.07.01.06.22.44;	author mcalabre;	state Exp;
branches;
next	;

8.1.1.1
date	2023.07.05.17.15.00;	author mcalabre;	state Exp;
branches;
next	;

8.2.1.1
date	2023.11.16.10.05.57;	author mcalabre;	state Exp;
branches;
next	8.2.1.2;

8.2.1.2
date	2023.11.29.07.39.01;	author mcalabre;	state Exp;
branches;
next	8.2.1.3;

8.2.1.3
date	2024.04.02.14.01.58;	author mcalabre;	state Exp;
branches;
next	8.2.1.4;

8.2.1.4
date	2024.05.07.12.15.44;	author mcalabre;	state Exp;
branches;
next	8.2.1.5;

8.2.1.5
date	2024.05.08.08.47.50;	author mcalabre;	state Exp;
branches;
next	8.2.1.6;

8.2.1.6
date	2024.05.08.15.14.58;	author mcalabre;	state Exp;
branches;
next	8.2.1.7;

8.2.1.7
date	2024.05.08.15.39.34;	author mcalabre;	state Exp;
branches;
next	8.2.1.8;

8.2.1.8
date	2024.05.10.14.34.04;	author mcalabre;	state Exp;
branches;
next	;

8.3.1.1
date	2024.05.13.16.35.39;	author mcalabre;	state Exp;
branches;
next	8.3.1.2;

8.3.1.2
date	2024.07.09.09.03.22;	author mcalabre;	state Exp;
branches;
next	;

8.4.1.1
date	2024.10.28.13.58.41;	author mcalabre;	state Exp;
branches;
next	8.4.1.2;

8.4.1.2
date	2025.12.06.13.37.15;	author mcalabre;	state Exp;
branches;
next	;

8.5.1.1
date	2025.12.06.14.05.15;	author mcalabre;	state Exp;
branches;
next	8.5.1.2;

8.5.1.2
date	2026.03.29.13.36.16;	author mcalabre;	state Exp;
branches;
next	;

8.6.1.1
date	2026.03.29.14.19.26;	author mcalabre;	state Exp;
branches;
next	8.6.1.2;

8.6.1.2
date	2026.04.05.14.03.29;	author mcalabre;	state Exp;
branches;
next	8.6.1.3;

8.6.1.3
date	2026.04.21.13.07.15;	author mcalabre;	state Exp;
branches;
next	8.6.1.4;

8.6.1.4
date	2026.04.26.08.59.55;	author mcalabre;	state Exp;
branches;
next	;


desc
@Implementation of the WCS spherical projection equations.
@


8.7
log
@WCSLIB 8.7
@
text
@/*============================================================================
  WCSLIB 8.7 - an implementation of the FITS WCS standard.
  Copyright (C) 1995-2026, Mark Calabretta

  This file is part of WCSLIB.

  WCSLIB is free software: you can redistribute it and/or modify it under the
  terms of the GNU Lesser General Public License as published by the Free
  Software Foundation, either version 3 of the License, or (at your option)
  any later version.

  WCSLIB 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 Lesser General Public License for
  more details.

  You should have received a copy of the GNU Lesser General Public License
  along with WCSLIB.  If not, see http://www.gnu.org/licenses.

  Author: Mark Calabretta, Australia Telescope National Facility, CSIRO.
  http://www.atnf.csiro.au/computing/software/wcs
  $Id: prj.c,v 8.6.1.4 2026/04/26 08:59:55 mcalabre Exp mcalabre $
*===========================================================================*/

#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "wcserr.h"
#include "wcsmath.h"
#include "wcsprintf.h"
#include "wcstrig.h"
#include "wcsutil.h"
#include "prj.h"


// Projection categories.
const int ZENITHAL          = 1;
const int CYLINDRICAL       = 2;
const int PSEUDOCYLINDRICAL = 3;
const int CONVENTIONAL      = 4;
const int CONIC             = 5;
const int POLYCONIC         = 6;
const int QUADCUBE          = 7;
const int HEALPIX           = 8;

const char prj_categories[9][32] =
  {"undefined", "zenithal", "cylindrical", "pseudocylindrical",
  "conventional", "conic", "polyconic", "quadcube", "HEALPix"};


// Projection codes.
const int  prj_ncode = 28;
const char prj_codes[28][4] =
  {"AZP", "SZP", "TAN", "STG", "SIN", "ARC", "ZPN", "ZEA", "AIR", "CYP",
   "CEA", "CAR", "MER", "COP", "COE", "COD", "COO", "SFL", "PAR", "MOL",
   "AIT", "BON", "PCO", "TSC", "CSC", "QSC", "HPX", "XPH"};

// Map status return value to message.
const char *prj_errmsg[] = {
  "Success",
  "Null prjprm pointer passed",
  "Invalid projection parameters",
  "One or more of the (x,y) coordinates were invalid",
  "One or more of the (phi,theta) coordinates were invalid"};

static const int AZP = 101;
static const int SZP = 102;
static const int TAN = 103;
static const int STG = 104;
static const int SIN = 105;
static const int ARC = 106;
static const int ZPN = 107;
static const int ZEA = 108;
static const int AIR = 109;
static const int CYP = 201;
static const int CEA = 202;
static const int CAR = 203;
static const int MER = 204;
static const int SFL = 301;
static const int PAR = 302;
static const int MOL = 303;
static const int AIT = 401;
static const int COP = 501;
static const int COE = 502;
static const int COD = 503;
static const int COO = 504;
static const int BON = 601;
static const int PCO = 602;
static const int TSC = 701;
static const int CSC = 702;
static const int QSC = 703;
static const int HPX = 801;
static const int XPH = 802;

// Convenience macros for generating common error messages.
#define PRJERR_BAD_PARAM_SET(function) \
  wcserr_set(&(prj->err), PRJERR_BAD_PARAM, function, __FILE__, __LINE__, \
    "Invalid parameters for %s projection", prj->name);

#define PRJERR_BAD_PIX_SET(function) \
  wcserr_set(&(prj->err), PRJERR_BAD_PIX, function, __FILE__, __LINE__, \
    "One or more of the (x, y) coordinates were invalid for %s projection", \
    prj->name);

#define PRJERR_BAD_WORLD_SET(function) \
  wcserr_set(&(prj->err), PRJERR_BAD_WORLD, function, __FILE__, __LINE__, \
    "One or more of the (lat, lng) coordinates were invalid for " \
    "%s projection", prj->name);


/*============================================================================
* Generic routines:
*
* prjini initializes a prjprm struct to default values.
*
* prjfree frees any memory that may have been allocated to store an error
*        message in the prjprm struct.
*
* prjsize computes the size of a prjprm struct.
*
* prjprt prints the contents of a prjprm struct.
*
* prjbchk performs bounds checking on the native coordinates returned by the
*        *x2s() routines.
*
* prjset invokes the specific initialization routine based on the projection
*        code in the prjprm struct.
*
* prjx2s invokes the specific deprojection routine based on the pointer-to-
*        function stored in the prjprm struct.
*
* prjs2x invokes the specific projection routine based on the pointer-to-
*        function stored in the prjprm struct.
*
*---------------------------------------------------------------------------*/

int prjini(struct prjprm *prj)

{
  if (prj == 0x0) return PRJERR_NULL_POINTER;

  strncpy(prj->code, "   ", 4);
  prj->pv[0]  = 0.0;
  prj->pv[1]  = UNDEFINED;
  prj->pv[2]  = UNDEFINED;
  prj->pv[3]  = UNDEFINED;
  for (int k = 4; k < PVN; prj->pv[k++] = 0.0);
  prj->r0     = 0.0;
  prj->phi0   = UNDEFINED;
  prj->theta0 = UNDEFINED;
  prj->bounds = 7;

  strncpy(prj->name, "undefined", 40);
  for (int k = 9; k < 40; prj->name[k++] = '\0');
  prj->category  = 0;
  prj->pvrange   = 0;
  prj->simplezen = 0;
  prj->equiareal = 0;
  prj->conformal = 0;
  prj->global    = 0;
  prj->divergent = 0;
  prj->x0 = 0.0;
  prj->y0 = 0.0;

  prj->err = 0x0;

  prj->padding = 0x0;
  for (int k = 0; k < 10; prj->w[k++] = 0.0);
  prj->m = 0;
  prj->n = 0;
  prj->prjx2s = 0x0;
  prj->prjs2x = 0x0;

  prj->flag = 0;

  return 0;
}

//----------------------------------------------------------------------------

int prjfree(struct prjprm *prj)

{
  if (prj == 0x0) return PRJERR_NULL_POINTER;

  wcserr_clear(&(prj->err));

  return 0;
}

//----------------------------------------------------------------------------

int prjsize(const struct prjprm *prj, int sizes[2])

{
  if (prj == 0x0) {
    sizes[0] = sizes[1] = 0;
    return 0;
  }

  // Base size, in bytes.
  sizes[0] = sizeof(struct prjprm);

  // Total size of allocated memory, in bytes.
  sizes[1] = 0;

  // prjprm::err.
  int exsizes[2];
  wcserr_size(prj->err, exsizes);
  sizes[1] += exsizes[0] + exsizes[1];

  return 0;
}

//----------------------------------------------------------------------------

int prjenq(const struct prjprm *prj, int enquiry)

{
  // Initialize.
  if (prj == 0x0) return PRJERR_NULL_POINTER;

  int answer = 0;
  int absflag = abs(prj->flag);

  if (enquiry & PRJENQ_SET) {
    if (absflag < 100 || 1000 < absflag) return 0;
    answer = 1;
  }

  if (enquiry & PRJENQ_BYP) {
    if (prj->flag != 1 && !(-1000 < prj->flag && prj->flag < -100)) return 0;
    answer = 1;
  }

  return answer;
}

//----------------------------------------------------------------------------

int prjprt(const struct prjprm *prj)

{
  if (prj == 0x0) return PRJERR_NULL_POINTER;

  // Parameters supplied.
  wcsprintf("       flag: %d\n",  prj->flag);
  wcsprintf("       code: \"%s\"\n", prj->code);
  wcsprintf("         r0: %9f\n", prj->r0);
  wcsprintf("         pv:");
  if (prj->pvrange) {
    int n = (prj->pvrange)%100;

    if (prj->pvrange/100) {
      wcsprintf(" (0)");
    } else {
      wcsprintf(" %#- 11.5g", prj->pv[0]);
      n--;
    }

    for (int i = 1; i <= n; i++) {
      if (i%5 == 1) {
        wcsprintf("\n           ");
      }

      if (undefined(prj->pv[i])) {
        wcsprintf("  UNDEFINED   ");
      } else {
        wcsprintf("  %#- 11.5g", prj->pv[i]);
      }
    }
    wcsprintf("\n");
  } else {
    wcsprintf(" (not used)\n");
  }
  if (undefined(prj->phi0)) {
    wcsprintf("       phi0: UNDEFINED\n");
  } else {
    wcsprintf("       phi0: %9f\n", prj->phi0);
  }
  if (undefined(prj->theta0)) {
    wcsprintf("     theta0: UNDEFINED\n");
  } else {
    wcsprintf("     theta0: %9f\n", prj->theta0);
  }
  wcsprintf("     bounds: %d\n",  prj->bounds);

  // Derived values.
  wcsprintf("\n");
  wcsprintf("       name: \"%s\"\n", prj->name);
  wcsprintf("   category: %d (%s)\n", prj->category,
                                      prj_categories[prj->category]);
  wcsprintf("    pvrange: %d\n", prj->pvrange);
  wcsprintf("  simplezen: %d\n", prj->simplezen);
  wcsprintf("  equiareal: %d\n", prj->equiareal);
  wcsprintf("  conformal: %d\n", prj->conformal);
  wcsprintf("     global: %d\n", prj->global);
  wcsprintf("  divergent: %d\n", prj->divergent);
  wcsprintf("         x0: %f\n", prj->x0);
  wcsprintf("         y0: %f\n", prj->y0);

  // Error handling.
  WCSPRINTF_PTR("        err: ", prj->err, "\n");
  if (prj->err) {
    wcserr_prt(prj->err, "             ");
  }

  // Intermediate values set by prjset().
  wcsprintf("        w[]:");
  for (int i = 0; i < 5; i++) {
    wcsprintf("  %#- 11.5g", prj->w[i]);
  }
  wcsprintf("\n            ");
  for (int i = 5; i < 10; i++) {
    wcsprintf("  %#- 11.5g", prj->w[i]);
  }
  wcsprintf("\n");
  wcsprintf("          m: %d\n", prj->m);
  wcsprintf("          n: %d\n", prj->n);

  // Pointers to projection and deprojection functions.
  char hext[32];
  wcsprintf("     prjx2s: %s\n",
    wcsutil_fptr2str((void (*)(void))prj->prjx2s, hext));
  wcsprintf("     prjs2x: %s\n",
    wcsutil_fptr2str((void (*)(void))prj->prjs2x, hext));

  return 0;
}

//----------------------------------------------------------------------------

int prjperr(const struct prjprm *prj, const char *prefix)

{
  if (prj == 0x0) return PRJERR_NULL_POINTER;

  if (prj->err) {
    wcserr_prt(prj->err, prefix);
  }

  return 0;
}

//----------------------------------------------------------------------------

int prjbchk(
  double tol,
  int nphi,
  int ntheta,
  int spt,
  double phi[],
  double theta[],
  int stat[])

{
  double *phip   = phi;
  double *thetap = theta;
  int    *statp  = stat;
  int    status  = 0;
  for (int itheta = 0; itheta < ntheta; itheta++) {
    for (int iphi = 0; iphi < nphi; iphi++, phip += spt, thetap += spt,
         statp++) {
      // Skip values already marked as illegal.
      if (*statp == 0) {
        if (*phip < -180.0) {
          if (*phip < -180.0-tol) {
            *statp = 1;
            status = 1;
          } else {
            *phip = -180.0;
          }
        } else if (180.0 < *phip) {
          if (180.0+tol < *phip) {
            *statp = 1;
            status = 1;
          } else {
            *phip = 180.0;
          }
        }

        if (*thetap < -90.0) {
          if (*thetap < -90.0-tol) {
            *statp = 1;
            status = 1;
          } else {
            *thetap = -90.0;
          }
        } else if (90.0 < *thetap) {
          if (90.0+tol < *thetap) {
            *statp = 1;
            status = 1;
          } else {
            *thetap = 90.0;
          }
        }
      }
    }
  }

  return status;
}

//----------------------------------------------------------------------------

int prjset(struct prjprm *prj)

{
  static const char *function = "prjset";

  if (prj == 0x0) return PRJERR_NULL_POINTER;
  if (prj->flag < 0) return 0;
  struct wcserr **err = &(prj->err);

  // Invoke the relevant initialization routine.
  prj->code[3] = '\0';

  int status;
  if (strcmp(prj->code, "AZP") == 0) {
    status = azpset(prj);
  } else if (strcmp(prj->code, "SZP") == 0) {
    status = szpset(prj);
  } else if (strcmp(prj->code, "TAN") == 0) {
    status = tanset(prj);
  } else if (strcmp(prj->code, "STG") == 0) {
    status = stgset(prj);
  } else if (strcmp(prj->code, "SIN") == 0) {
    status = sinset(prj);
  } else if (strcmp(prj->code, "ARC") == 0) {
    status = arcset(prj);
  } else if (strcmp(prj->code, "ZPN") == 0) {
    status = zpnset(prj);
  } else if (strcmp(prj->code, "ZEA") == 0) {
    status = zeaset(prj);
  } else if (strcmp(prj->code, "AIR") == 0) {
    status = airset(prj);
  } else if (strcmp(prj->code, "CYP") == 0) {
    status = cypset(prj);
  } else if (strcmp(prj->code, "CEA") == 0) {
    status = ceaset(prj);
  } else if (strcmp(prj->code, "CAR") == 0) {
    status = carset(prj);
  } else if (strcmp(prj->code, "MER") == 0) {
    status = merset(prj);
  } else if (strcmp(prj->code, "SFL") == 0) {
    status = sflset(prj);
  } else if (strcmp(prj->code, "PAR") == 0) {
    status = parset(prj);
  } else if (strcmp(prj->code, "MOL") == 0) {
    status = molset(prj);
  } else if (strcmp(prj->code, "AIT") == 0) {
    status = aitset(prj);
  } else if (strcmp(prj->code, "COP") == 0) {
    status = copset(prj);
  } else if (strcmp(prj->code, "COE") == 0) {
    status = coeset(prj);
  } else if (strcmp(prj->code, "COD") == 0) {
    status = codset(prj);
  } else if (strcmp(prj->code, "COO") == 0) {
    status = cooset(prj);
  } else if (strcmp(prj->code, "BON") == 0) {
    status = bonset(prj);
  } else if (strcmp(prj->code, "PCO") == 0) {
    status = pcoset(prj);
  } else if (strcmp(prj->code, "TSC") == 0) {
    status = tscset(prj);
  } else if (strcmp(prj->code, "CSC") == 0) {
    status = cscset(prj);
  } else if (strcmp(prj->code, "QSC") == 0) {
    status = qscset(prj);
  } else if (strcmp(prj->code, "HPX") == 0) {
    status = hpxset(prj);
  } else if (strcmp(prj->code, "XPH") == 0) {
    status = xphset(prj);
  } else {
    // Unrecognized projection code.
    status = wcserr_set(WCSERR_SET(PRJERR_BAD_PARAM),
               "Unrecognized projection code '%s'", prj->code);
  }

  return status;
}

//----------------------------------------------------------------------------

int prjx2s(
  struct prjprm *prj,
  int nx,
  int ny,
  int sxy,
  int spt,
  const double x[],
  const double y[],
  double phi[],
  double theta[],
  int stat[])

{
  // Initialize.
  if (prj == 0x0) return PRJERR_NULL_POINTER;

  int status;
  if (abs(prj->flag) < 100) {
    if ((status = prjset(prj))) return status;
  }

  return prj->prjx2s(prj, nx, ny, sxy, spt, x, y, phi, theta, stat);
}

//----------------------------------------------------------------------------

int prjs2x(
  struct prjprm *prj,
  int nphi,
  int ntheta,
  int spt,
  int sxy,
  const double phi[],
  const double theta[],
  double x[],
  double y[],
  int stat[])

{
  // Initialize.
  if (prj == 0x0) return PRJERR_NULL_POINTER;

  int status;
  if (abs(prj->flag) < 100) {
    if ((status = prjset(prj))) return status;
  }

  return prj->prjs2x(prj, nphi, ntheta, spt, sxy, phi, theta, x, y, stat);
}

/*============================================================================
* Internal helper routine used by the *set() routines - not intended for
* outside use.  It forces (x,y) = (0,0) at (phi0,theta0).
*---------------------------------------------------------------------------*/

static int prjoff(
  struct prjprm *prj,
  const double phi0,
  const double theta0)

{
  if (prj == 0x0) return PRJERR_NULL_POINTER;

  prj->x0 = 0.0;
  prj->y0 = 0.0;

  if (undefined(prj->phi0) || undefined(prj->theta0)) {
    // Set both to the projection-specific default if either undefined.
    prj->phi0   = phi0;
    prj->theta0 = theta0;

  } else {
    double x0, y0;
    int    stat;
    if (prj->prjs2x(prj, 1, 1, 1, 1, &(prj->phi0), &(prj->theta0), &x0, &y0,
                    &stat)) {
      return PRJERR_BAD_PARAM_SET("prjoff");
    }

    prj->x0 = x0;
    prj->y0 = y0;
  }

  return 0;
}

/*============================================================================
*   AZP: zenithal/azimuthal perspective projection.
*
*   Given:
*      prj->pv[1]   Distance parameter, mu in units of r0.
*      prj->pv[2]   Tilt angle, gamma in degrees.
*
*   Given and/or returned:
*      prj->r0      Reset to 180/pi if 0.
*      prj->phi0    Reset to  0.0 if undefined.
*      prj->theta0  Reset to 90.0 if undefined.
*
*   Returned:
*      prj->flag     AZP
*      prj->code    "AZP"
*      prj->x0      Offset in x.
*      prj->y0      Offset in y.
*      prj->w[0]    r0*(mu+1)
*      prj->w[1]    tan(gamma)
*      prj->w[2]    sec(gamma)
*      prj->w[3]    cos(gamma)
*      prj->w[4]    sin(gamma)
*      prj->w[5]    asin(-1/mu) for |mu| >= 1, -90 otherwise
*      prj->w[6]    mu*cos(gamma)
*      prj->w[7]    1 if |mu*cos(gamma)| < 1, 0 otherwise
*      prj->prjx2s  Pointer to azpx2s().
*      prj->prjs2x  Pointer to azps2x().
*===========================================================================*/

int azpset(struct prjprm *prj)

{
  if (prj == 0x0) return PRJERR_NULL_POINTER;
  if (prj->flag == -AZP) return 0;

  strncpy(prj->code, "AZP", 4);

  if (undefined(prj->pv[1])) prj->pv[1] = 0.0;
  if (undefined(prj->pv[2])) prj->pv[2] = 0.0;
  if (prj->r0 == 0.0) prj->r0 = R2D;

  strncpy(prj->name, "zenithal/azimuthal perspective", 40);
  prj->category  = ZENITHAL;
  prj->pvrange   = 102;
  prj->simplezen = prj->pv[2] == 0.0;
  prj->equiareal = 0;
  prj->conformal = 0;
  prj->global    = 0;
  prj->divergent = prj->pv[1] <= 1.0;

  prj->w[0] = prj->r0*(prj->pv[1] + 1.0);
  if (prj->w[0] == 0.0) {
    return PRJERR_BAD_PARAM_SET("azpset");
  }

  prj->w[3] = cosd(prj->pv[2]);
  if (prj->w[3] == 0.0) {
    return PRJERR_BAD_PARAM_SET("azpset");
  }

  prj->w[2] = 1.0/prj->w[3];
  prj->w[4] = sind(prj->pv[2]);
  prj->w[1] = prj->w[4] / prj->w[3];

  if (fabs(prj->pv[1]) > 1.0) {
    prj->w[5] = asind(-1.0/prj->pv[1]);
  } else {
    prj->w[5] = -90.0;
  }

  prj->w[6] = prj->pv[1] * prj->w[3];
  prj->w[7] = (fabs(prj->w[6]) < 1.0) ? 1.0 : 0.0;

  prj->prjx2s = azpx2s;
  prj->prjs2x = azps2x;

  prj->flag = (prj->flag == 1) ? -AZP : AZP;

  return prjoff(prj, 0.0, 90.0);
}

//----------------------------------------------------------------------------

int azpx2s(
  struct prjprm *prj,
  int nx,
  int ny,
  int sxy,
  int spt,
  const double x[],
  const double y[],
  double phi[],
  double theta[],
  int stat[])

{
  const double tol = 1.0e-13;

  // Initialize.
  if (prj == 0x0) return PRJERR_NULL_POINTER;

  int status;
  if (abs(prj->flag) != AZP) {
    if ((status = azpset(prj))) return status;
  }

  int mx, my;
  if (ny > 0) {
    mx = nx;
    my = ny;
  } else {
    mx = 1;
    my = 1;
    ny = nx;
  }

  status = 0;


  // Do x dependence.
  const double *xp = x;
  double *phip, *thetap;
  int rowoff = 0;
  int rowlen = nx*spt;
  for (int ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    double xj = *xp + prj->x0;

    phip = phi + rowoff;
    for (int iy = 0; iy < my; iy++) {
      *phip = xj;
      phip += rowlen;
    }
  }


  // Do y dependence.
  const double *yp = y;
  int *statp  = stat;

  phip   = phi;
  thetap = theta;
  for (int iy = 0; iy < ny; iy++, yp += sxy) {
    double yj = *yp + prj->y0;

    double yc  = yj*prj->w[3];
    double yc2 = yc*yc;

    double q = prj->w[0] + yj*prj->w[4];

    for (int ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
      double xj = *phip;

      double r = sqrt(xj*xj + yc2);
      if (r == 0.0) {
        *phip = 0.0;
        *thetap = 90.0;
        *statp  = 0;

      } else {
        *phip = atan2d(xj, -yc);

        double s = r / q;
        double t = s*prj->pv[1]/sqrt(s*s + 1.0);

        s = atan2d(1.0, s);

        if (fabs(t) > 1.0) {
          if (fabs(t) > 1.0+tol) {
            *thetap = 0.0;
            *statp  = 1;
            if (!status) status = PRJERR_BAD_PIX_SET("azpx2s");
            continue;
          }
          t = copysign(90.0, t);
        } else {
          t = asind(t);
        }

        double a = s - t;
        double b = s + t + 180.0;

        if (a > 90.0) a -= 360.0;
        if (b > 90.0) b -= 360.0;

        *thetap = (a > b) ? a : b;
        *statp  = 0;
      }
    }
  }


  // Do bounds checking on the native coordinates.
  if (prj->bounds&4 && prjbchk(1.0e-13, nx, my, spt, phi, theta, stat)) {
    if (!status) status = PRJERR_BAD_PIX_SET("azpx2s");
  }

  return status;
}

//----------------------------------------------------------------------------

int azps2x(
  struct prjprm *prj,
  int nphi,
  int ntheta,
  int spt,
  int sxy,
  const double phi[],
  const double theta[],
  double x[],
  double y[],
  int stat[])

{
  // Initialize.
  if (prj == 0x0) return PRJERR_NULL_POINTER;

  int status;
  if (abs(prj->flag) != AZP) {
    if ((status = azpset(prj))) return status;
  }

  int mphi, mtheta;
  if (ntheta > 0) {
    mphi   = nphi;
    mtheta = ntheta;
  } else {
    mphi   = 1;
    mtheta = 1;
    ntheta = nphi;
  }

  status = 0;


  // Do phi dependence.
  const double *phip = phi;
  int rowoff = 0;
  int rowlen = nphi*sxy;
  for (int iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    double sinphi, cosphi;
    sincosd(*phip, &sinphi, &cosphi);

    double *xp = x + rowoff;
    double *yp = y + rowoff;
    for (int itheta = 0; itheta < mtheta; itheta++) {
      *xp = sinphi;
      *yp = cosphi;
      xp += rowlen;
      yp += rowlen;
    }
  }


  // Do theta dependence.
  const double *thetap = theta;
  double *xp = x;
  double *yp = y;
  int *statp = stat;
  for (int itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    double sinthe, costhe;
    sincosd(*thetap, &sinthe, &costhe);

    for (int iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
      double s = prj->w[1]*(*yp);
      double t = (prj->pv[1] + sinthe) + costhe*s;

      if (t == 0.0) {
        *xp = 0.0;
        *yp = 0.0;
        *statp = 1;
        if (!status) status = PRJERR_BAD_WORLD_SET("azps2x");

      } else {
        double r = prj->w[0]*costhe/t;

        // Bounds checking.
        int istat = 0;
        if (prj->bounds&1) {
          if (*thetap < prj->w[5]) {
            // Overlap.
            istat = 1;
            if (!status) status = PRJERR_BAD_WORLD_SET("azps2x");

          } else if (prj->w[7] > 0.0) {
            // Divergence.
            t = prj->pv[1] / sqrt(1.0 + s*s);

            if (fabs(t) <= 1.0) {
              s = atand(-s);
              t = asind(t);

              double a = s - t;
              double b = s + t + 180.0;

              if (a > 90.0) a -= 360.0;
              if (b > 90.0) b -= 360.0;

              if (*thetap < ((a > b) ? a : b)) {
                istat = 1;
                if (!status) status = PRJERR_BAD_WORLD_SET("azps2x");
              }
            }
          }
        }

        *xp =  r*(*xp) - prj->x0;
        *yp = -r*(*yp)*prj->w[2] - prj->y0;
        *statp = istat;
      }
    }
  }

  return status;
}

/*============================================================================
*   SZP: slant zenithal perspective projection.
*
*   Given:
*      prj->pv[1]   Distance of the point of projection from the centre of the
*                   generating sphere, mu in units of r0.
*      prj->pv[2]   Native longitude, phi_c, and ...
*      prj->pv[3]   Native latitude, theta_c, on the planewards side of the
*                   intersection of the line through the point of projection
*                   and the centre of the generating sphere, phi_c in degrees.
*
*   Given and/or returned:
*      prj->r0      Reset to 180/pi if 0.
*      prj->phi0    Reset to  0.0 if undefined.
*      prj->theta0  Reset to 90.0 if undefined.
*
*   Returned:
*      prj->flag     SZP
*      prj->code    "SZP"
*      prj->x0      Fiducial offset in x.
*      prj->y0      Fiducial offset in y.
*      prj->w[0]    1/r0
*      prj->w[1]    xp = -mu*cos(theta_c)*sin(phi_c)
*      prj->w[2]    yp =  mu*cos(theta_c)*cos(phi_c)
*      prj->w[3]    zp =  mu*sin(theta_c) + 1
*      prj->w[4]    r0*xp
*      prj->w[5]    r0*yp
*      prj->w[6]    r0*zp
*      prj->w[7]    (zp - 1)^2
*      prj->w[8]    asin(1-zp) if |1 - zp| < 1, -90 otherwise
*      prj->prjx2s  Pointer to szpx2s().
*      prj->prjs2x  Pointer to szps2x().
*===========================================================================*/

int szpset(struct prjprm *prj)

{
  if (prj == 0x0) return PRJERR_NULL_POINTER;
  if (prj->flag == -SZP) return 0;

  strncpy(prj->code, "SZP", 4);

  if (undefined(prj->pv[1])) prj->pv[1] =  0.0;
  if (undefined(prj->pv[2])) prj->pv[2] =  0.0;
  if (undefined(prj->pv[3])) prj->pv[3] = 90.0;
  if (prj->r0 == 0.0) prj->r0 = R2D;

  strncpy(prj->name, "slant zenithal perspective", 40);
  prj->category  = ZENITHAL;
  prj->pvrange   = 103;
  prj->simplezen = prj->pv[3] == 90.0;
  prj->equiareal = 0;
  prj->conformal = 0;
  prj->global    = 0;
  prj->divergent = prj->pv[1] <= 1.0;

  prj->w[0] = 1.0/prj->r0;

  prj->w[3] = prj->pv[1] * sind(prj->pv[3]) + 1.0;
  if (prj->w[3] == 0.0) {
    return PRJERR_BAD_PARAM_SET("szpset");
  }

  prj->w[1] = -prj->pv[1] * cosd(prj->pv[3]) * sind(prj->pv[2]);
  prj->w[2] =  prj->pv[1] * cosd(prj->pv[3]) * cosd(prj->pv[2]);
  prj->w[4] =  prj->r0 * prj->w[1];
  prj->w[5] =  prj->r0 * prj->w[2];
  prj->w[6] =  prj->r0 * prj->w[3];
  prj->w[7] =  (prj->w[3] - 1.0) * prj->w[3] - 1.0;

  if (fabs(prj->w[3] - 1.0) < 1.0) {
    prj->w[8] = asind(1.0 - prj->w[3]);
  } else {
    prj->w[8] = -90.0;
  }

  prj->prjx2s = szpx2s;
  prj->prjs2x = szps2x;

  prj->flag = (prj->flag == 1) ? -SZP : SZP;

  return prjoff(prj, 0.0, 90.0);
}

//----------------------------------------------------------------------------

int szpx2s(
  struct prjprm *prj,
  int nx,
  int ny,
  int sxy,
  int spt,
  const double x[],
  const double y[],
  double phi[],
  double theta[],
  int stat[])

{
  const double tol = 1.0e-13;

  // Initialize.
  if (prj == 0x0) return PRJERR_NULL_POINTER;

  int status;
  if (abs(prj->flag) != SZP) {
    if ((status = szpset(prj))) return status;
  }

  int mx, my;
  if (ny > 0) {
    mx = nx;
    my = ny;
  } else {
    mx = 1;
    my = 1;
    ny = nx;
  }

  status = 0;


  // Do x dependence.
  const double *xp = x;
  int rowoff = 0;
  int rowlen = nx*spt;
  for (int ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    double xr = (*xp + prj->x0)*prj->w[0];

    double *phip = phi + rowoff;
    for (int iy = 0; iy < my; iy++) {
      *phip = xr;
      phip += rowlen;
    }
  }


  // Do y dependence.
  const double *yp = y;
  double *phip   = phi;
  double *thetap = theta;
  int     *statp = stat;
  for (int iy = 0; iy < ny; iy++, yp += sxy) {
    double yr = (*yp + prj->y0)*prj->w[0];

    for (int ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
      double xr = *phip;
      double r2 = xr*xr + yr*yr;

      double x1 = (xr - prj->w[1])/prj->w[3];
      double y1 = (yr - prj->w[2])/prj->w[3];
      double xy = xr*x1 + yr*y1;

      double z;
      if (r2 < 1.0e-10) {
        // Use small angle formula.
        z = r2/2.0;
        *thetap = 90.0 - R2D*sqrt(r2/(1.0 + xy));

      } else {
        double t = x1*x1 + y1*y1;
        double a = t + 1.0;
        double b = xy - t;
        double c = r2 - xy - xy + t - 1.0;
        double d = b*b - a*c;

        // Check for a solution.
        if (d < 0.0) {
          *phip = 0.0;
          *thetap = 0.0;
          *statp  = 1;
          if (!status) status = PRJERR_BAD_PIX_SET("szpx2s");
          continue;
        }
        d = sqrt(d);

        // Choose solution closest to pole.
        double sinth1 = (-b + d)/a;
        double sinth2 = (-b - d)/a;
        double sinthe = (sinth1 > sinth2) ? sinth1 : sinth2;
        if (sinthe > 1.0) {
          if (sinthe-1.0 < tol) {
            sinthe = 1.0;
          } else {
            sinthe = (sinth1 < sinth2) ? sinth1 : sinth2;
          }
        }

        if (sinthe < -1.0) {
          if (sinthe+1.0 > -tol) {
            sinthe = -1.0;
          }
        }

        if (sinthe > 1.0 || sinthe < -1.0) {
          *phip   = 0.0;
          *thetap = 0.0;
          *statp  = 1;
          if (!status) status = PRJERR_BAD_PIX_SET("szpx2s");
          continue;
        }

        *thetap = asind(sinthe);

        z = 1.0 - sinthe;
      }

      *phip = atan2d(xr - x1*z, -(yr - y1*z));
      *statp = 0;
    }
  }


  // Do bounds checking on the native coordinates.
  if (prj->bounds&4 && prjbchk(1.0e-13, nx, my, spt, phi, theta, stat)) {
    if (!status) status = PRJERR_BAD_PIX_SET("szpx2s");
  }

  return status;
}

//----------------------------------------------------------------------------

int szps2x(
  struct prjprm *prj,
  int nphi,
  int ntheta,
  int spt,
  int sxy,
  const double phi[],
  const double theta[],
  double x[],
  double y[],
  int stat[])

{
  // Initialize.
  if (prj == 0x0) return PRJERR_NULL_POINTER;

  int status;
  if (abs(prj->flag) != SZP) {
    if ((status = szpset(prj))) return status;
  }

  int mphi, mtheta;
  if (ntheta > 0) {
    mphi   = nphi;
    mtheta = ntheta;
  } else {
    mphi   = 1;
    mtheta = 1;
    ntheta = nphi;
  }

  status = 0;


  // Do phi dependence.
  const double *phip = phi;
  int rowoff = 0;
  int rowlen = nphi*sxy;
  for (int iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    double sinphi, cosphi;
    sincosd(*phip, &sinphi, &cosphi);

    double *xp = x + rowoff;
    double *yp = y + rowoff;
    for (int itheta = 0; itheta < mtheta; itheta++) {
      *xp = sinphi;
      *yp = cosphi;
      xp += rowlen;
      yp += rowlen;
    }
  }


  // Do theta dependence.
  const double *thetap = theta;
  double *xp = x;
  double *yp = y;
  int *statp = stat;
  for (int itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    double s = 1.0 - sind(*thetap);
    double t = prj->w[3] - s;

    if (t == 0.0) {
      for (int iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
        *xp = 0.0;
        *yp = 0.0;
        *statp = 1;
      }

      if (!status) status = PRJERR_BAD_WORLD_SET("szps2x");

    } else {
      double r = prj->w[6]*cosd(*thetap)/t;
      double u = prj->w[4]*s/t + prj->x0;
      double v = prj->w[5]*s/t + prj->y0;

      for (int iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
        // Bounds checking.
        int istat = 0;
        if (prj->bounds&1) {
          if (*thetap < prj->w[8]) {
            // Divergence.
            istat = 1;
            if (!status) status = PRJERR_BAD_WORLD_SET("szps2x");

          } else if (fabs(prj->pv[1]) > 1.0) {
            // Overlap.
            s = prj->w[1]*(*xp) - prj->w[2]*(*yp);
            t = 1.0/sqrt(prj->w[7] + s*s);

            if (fabs(t) <= 1.0) {
              s = atan2d(s, prj->w[3] - 1.0);
              t = asind(t);

              double a = s - t;
              double b = s + t + 180.0;

              if (a > 90.0) a -= 360.0;
              if (b > 90.0) b -= 360.0;

              if (*thetap < ((a > b) ? a : b)) {
                istat = 1;
                if (!status) status = PRJERR_BAD_WORLD_SET("szps2x");
              }
            }
          }
        }

        *xp =  r*(*xp) - u;
        *yp = -r*(*yp) - v;
        *statp = istat;
      }
    }
  }

  return status;
}


/*============================================================================
*   TAN: gnomonic projection.
*
*   Given and/or returned:
*      prj->r0      Reset to 180/pi if 0.
*      prj->phi0    Reset to  0.0 if undefined.
*      prj->theta0  Reset to 90.0 if undefined.
*
*   Returned:
*      prj->flag     TAN
*      prj->code    "TAN"
*      prj->x0      Fiducial offset in x.
*      prj->y0      Fiducial offset in y.
*      prj->prjx2s  Pointer to tanx2s().
*      prj->prjs2x  Pointer to tans2x().
*===========================================================================*/

int tanset(struct prjprm *prj)

{
  if (prj == 0x0) return PRJERR_NULL_POINTER;
  if (prj->flag == -TAN) return 0;

  strncpy(prj->code, "TAN", 4);

  if (prj->r0 == 0.0) prj->r0 = R2D;

  strncpy(prj->name, "gnomonic", 40);
  prj->category  = ZENITHAL;
  prj->pvrange   = 0;
  prj->simplezen = 1;
  prj->equiareal = 0;
  prj->conformal = 0;
  prj->global    = 0;
  prj->divergent = 1;

  prj->prjx2s = tanx2s;
  prj->prjs2x = tans2x;

  prj->flag = (prj->flag == 1) ? -TAN : TAN;

  return prjoff(prj, 0.0, 90.0);
}

//----------------------------------------------------------------------------

int tanx2s(
  struct prjprm *prj,
  int nx,
  int ny,
  int sxy,
  int spt,
  const double x[],
  const double y[],
  double phi[],
  double theta[],
  int stat[])

{
  // Initialize.
  if (prj == 0x0) return PRJERR_NULL_POINTER;

  int status;
  if (abs(prj->flag) != TAN) {
    if ((status = tanset(prj))) return status;
  }

  int mx, my;
  if (ny > 0) {
    mx = nx;
    my = ny;
  } else {
    mx = 1;
    my = 1;
    ny = nx;
  }

  status = 0;


  // Do x dependence.
  const double *xp = x;
  int rowoff = 0;
  int rowlen = nx*spt;
  for (int ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    double xj = *xp + prj->x0;

    double *phip = phi + rowoff;
    for (int iy = 0; iy < my; iy++) {
      *phip = xj;
      phip += rowlen;
    }
  }


  // Do y dependence.
  const double *yp = y;
  double *phip   = phi;
  double *thetap = theta;
  int    *statp  = stat;
  for (int iy = 0; iy < ny; iy++, yp += sxy) {
    double yj  = *yp + prj->y0;
    double yj2 = yj*yj;

    for (int ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
      double xj = *phip;

      double r = sqrt(xj*xj + yj2);
      if (r == 0.0) {
        *phip = 0.0;
      } else {
        *phip = atan2d(xj, -yj);
      }

      *thetap = atan2d(prj->r0, r);
      *statp  = 0;
    }
  }


  // Do bounds checking on the native coordinates.
  if (prj->bounds&4 && prjbchk(1.0e-13, nx, my, spt, phi, theta, stat)) {
    if (!status) status = PRJERR_BAD_PIX_SET("tanx2s");
  }

  return status;
}

//----------------------------------------------------------------------------

int tans2x(
  struct prjprm *prj,
  int nphi,
  int ntheta,
  int spt,
  int sxy,
  const double phi[],
  const double theta[],
  double x[],
  double y[],
  int stat[])

{
  // Initialize.
  if (prj == 0x0) return PRJERR_NULL_POINTER;

  int status;
  if (abs(prj->flag) != TAN) {
    if ((status = tanset(prj))) return status;
  }

  int mphi, mtheta;
  if (ntheta > 0) {
    mphi   = nphi;
    mtheta = ntheta;
  } else {
    mphi   = 1;
    mtheta = 1;
    ntheta = nphi;
  }

  status = 0;


  // Do phi dependence.
  const double *phip = phi;
  int rowoff = 0;
  int rowlen = nphi*sxy;
  for (int iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    double sinphi, cosphi;
    sincosd(*phip, &sinphi, &cosphi);

    double *xp = x + rowoff;
    double *yp = y + rowoff;
    for (int itheta = 0; itheta < mtheta; itheta++) {
      *xp = sinphi;
      *yp = cosphi;
      xp += rowlen;
      yp += rowlen;
    }
  }


  // Do theta dependence.
  const double *thetap = theta;
  double *xp = x;
  double *yp = y;
  int *statp = stat;
  for (int itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    double s = sind(*thetap);
    if (s == 0.0) {
      for (int iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
        *xp = 0.0;
        *yp = 0.0;
        *statp = 1;
      }
      if (!status) status = PRJERR_BAD_WORLD_SET("tans2x");

    } else {
      double r =  prj->r0*cosd(*thetap)/s;

      // Bounds checking.
      int istat = 0;
      if (prj->bounds&1) {
        if (s < 0.0) {
          istat = 1;
          if (!status) status = PRJERR_BAD_WORLD_SET("tans2x");
        }
      }

      for (int iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
        *xp =  r*(*xp) - prj->x0;
        *yp = -r*(*yp) - prj->y0;
        *statp = istat;
      }
    }
  }

  return status;
}

/*============================================================================
*   STG: stereographic projection.
*
*   Given and/or returned:
*      prj->r0      Reset to 180/pi if 0.
*      prj->phi0    Reset to  0.0 if undefined.
*      prj->theta0  Reset to 90.0 if undefined.
*
*   Returned:
*      prj->flag     STG
*      prj->code    "STG"
*      prj->x0      Fiducial offset in x.
*      prj->y0      Fiducial offset in y.
*      prj->w[0]    2*r0
*      prj->w[1]    1/(2*r0)
*      prj->prjx2s  Pointer to stgx2s().
*      prj->prjs2x  Pointer to stgs2x().
*===========================================================================*/

int stgset(struct prjprm *prj)

{
  if (prj == 0x0) return PRJERR_NULL_POINTER;
  if (prj->flag == -STG) return 0;

  strncpy(prj->code, "STG", 4);

  strncpy(prj->name, "stereographic", 40);
  prj->category  = ZENITHAL;
  prj->pvrange   = 0;
  prj->simplezen = 1;
  prj->equiareal = 0;
  prj->conformal = 1;
  prj->global    = 0;
  prj->divergent = 1;

  if (prj->r0 == 0.0) {
    prj->r0 = R2D;
    prj->w[0] = 360.0/PI;
    prj->w[1] = PI/360.0;
  } else {
    prj->w[0] = 2.0*prj->r0;
    prj->w[1] = 1.0/prj->w[0];
  }

  prj->prjx2s = stgx2s;
  prj->prjs2x = stgs2x;

  prj->flag = (prj->flag == 1) ? -STG : STG;

  return prjoff(prj, 0.0, 90.0);
}

//----------------------------------------------------------------------------

int stgx2s(
  struct prjprm *prj,
  int nx,
  int ny,
  int sxy,
  int spt,
  const double x[],
  const double y[],
  double phi[],
  double theta[],
  int stat[])

{
  // Initialize.
  if (prj == 0x0) return PRJERR_NULL_POINTER;

  int status;
  if (abs(prj->flag) != STG) {
    if ((status = stgset(prj))) return status;
  }

  int mx, my;
  if (ny > 0) {
    mx = nx;
    my = ny;
  } else {
    mx = 1;
    my = 1;
    ny = nx;
  }


  // Do x dependence.
  const double *xp = x;
  int rowoff = 0;
  int rowlen = nx*spt;
  for (int ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    double xj = *xp + prj->x0;

    double *phip = phi + rowoff;
    for (int iy = 0; iy < my; iy++) {
      *phip = xj;
      phip += rowlen;
    }
  }


  // Do y dependence.
  const double *yp = y;
  double *phip   = phi;
  double *thetap = theta;
  int    *statp  = stat;
  for (int iy = 0; iy < ny; iy++, yp += sxy) {
    double yj  = *yp + prj->y0;
    double yj2 = yj*yj;

    for (int ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
      double xj  = *phip;

      double r = sqrt(xj*xj + yj2);
      if (r == 0.0) {
        *phip = 0.0;
      } else {
        *phip = atan2d(xj, -yj);
      }

      *thetap = 90.0 - 2.0*atand(r*prj->w[1]);
      *statp  = 0;
    }
  }

  return 0;
}

//----------------------------------------------------------------------------

int stgs2x(
  struct prjprm *prj,
  int nphi,
  int ntheta,
  int spt,
  int sxy,
  const double phi[],
  const double theta[],
  double x[],
  double y[],
  int stat[])

{
  // Initialize.
  if (prj == 0x0) return PRJERR_NULL_POINTER;

  int status;
  if (abs(prj->flag) != STG) {
    if ((status = stgset(prj))) return status;
  }

  int mphi, mtheta;
  if (ntheta > 0) {
    mphi   = nphi;
    mtheta = ntheta;
  } else {
    mphi   = 1;
    mtheta = 1;
    ntheta = nphi;
  }

  status = 0;


  // Do phi dependence.
  const double *phip = phi;
  int rowoff = 0;
  int rowlen = nphi*sxy;
  for (int iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    double sinphi, cosphi;
    sincosd(*phip, &sinphi, &cosphi);

    double *xp = x + rowoff;
    double *yp = y + rowoff;
    for (int itheta = 0; itheta < mtheta; itheta++) {
      *xp = sinphi;
      *yp = cosphi;
      xp += rowlen;
      yp += rowlen;
    }
  }


  // Do theta dependence.
  const double *thetap = theta;
  double *xp = x;
  double *yp = y;
  int *statp = stat;
  for (int itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    double s = 1.0 + sind(*thetap);
    if (s == 0.0) {
      for (int iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
        *xp = 0.0;
        *yp = 0.0;
        *statp = 1;
      }
      if (!status) status = PRJERR_BAD_WORLD_SET("stgs2x");

    } else {
      double r = prj->w[0]*cosd(*thetap)/s;

      for (int iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
        *xp =  r*(*xp) - prj->x0;
        *yp = -r*(*yp) - prj->y0;
        *statp = 0;
      }
    }
  }

  return status;
}

/*============================================================================
*   SIN: orthographic/synthesis projection.
*
*   Given:
*      prj->pv[1:2] Obliqueness parameters, xi and eta.
*
*   Given and/or returned:
*      prj->r0      Reset to 180/pi if 0.
*      prj->phi0    Reset to  0.0 if undefined.
*      prj->theta0  Reset to 90.0 if undefined.
*
*   Returned:
*      prj->flag     SIN
*      prj->code    "SIN"
*      prj->x0      Fiducial offset in x.
*      prj->y0      Fiducial offset in y.
*      prj->w[0]    1/r0
*      prj->w[1]    xi**2 + eta**2
*      prj->w[2]    xi**2 + eta**2 + 1
*      prj->w[3]    xi**2 + eta**2 - 1
*      prj->prjx2s  Pointer to sinx2s().
*      prj->prjs2x  Pointer to sins2x().
*===========================================================================*/

int sinset(struct prjprm *prj)

{
  if (prj == 0x0) return PRJERR_NULL_POINTER;
  if (prj->flag == -SIN) return 0;

  strncpy(prj->code, "SIN", 4);

  if (undefined(prj->pv[1])) prj->pv[1] = 0.0;
  if (undefined(prj->pv[2])) prj->pv[2] = 0.0;
  if (prj->r0 == 0.0) prj->r0 = R2D;

  strncpy(prj->name, "orthographic/synthesis", 40);
  prj->category  = ZENITHAL;
  prj->pvrange   = 102;
  prj->simplezen = (prj->pv[1] == 0.0 && prj->pv[2] == 0.0);
  prj->equiareal = 0;
  prj->conformal = 0;
  prj->global    = 0;
  prj->divergent = 0;

  prj->w[0] = 1.0/prj->r0;
  prj->w[1] = prj->pv[1]*prj->pv[1] + prj->pv[2]*prj->pv[2];
  prj->w[2] = prj->w[1] + 1.0;
  prj->w[3] = prj->w[1] - 1.0;

  prj->prjx2s = sinx2s;
  prj->prjs2x = sins2x;

  prj->flag = (prj->flag == 1) ? -SIN : SIN;

  return prjoff(prj, 0.0, 90.0);
}

//----------------------------------------------------------------------------

int sinx2s(
  struct prjprm *prj,
  int nx,
  int ny,
  int sxy,
  int spt,
  const double x[],
  const double y[],
  double phi[],
  double theta[],
  int stat[])

{
  const double tol = 1.0e-13;

  // Initialize.
  if (prj == 0x0) return PRJERR_NULL_POINTER;

  int status;
  if (abs(prj->flag) != SIN) {
    if ((status = sinset(prj))) return status;
  }

  double xi  = prj->pv[1];
  double eta = prj->pv[2];

  int mx, my;
  if (ny > 0) {
    mx = nx;
    my = ny;
  } else {
    mx = 1;
    my = 1;
    ny = nx;
  }

  status = 0;


  // Do x dependence.
  const double *xp = x;
  int rowoff = 0;
  int rowlen = nx*spt;
  for (int ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    double x0 = (*xp + prj->x0)*prj->w[0];

    double *phip = phi + rowoff;
    for (int iy = 0; iy < my; iy++) {
      *phip = x0;
      phip += rowlen;
    }
  }


  // Do y dependence.
  const double *yp = y;
  double *phip   = phi;
  double *thetap = theta;
  int    *statp  = stat;
  for (int iy = 0; iy < ny; iy++, yp += sxy) {
    double y0 = (*yp + prj->y0)*prj->w[0];
    double y02 = y0*y0;

    for (int ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
      // Compute intermediaries.
      double x0 = *phip;
      double r2 = x0*x0 + y02;

      if (prj->w[1] == 0.0) {
        // Orthographic projection.
        if (r2 != 0.0) {
          *phip = atan2d(x0, -y0);
        } else {
          *phip = 0.0;
        }

        if (r2 < 0.5) {
          *thetap = acosd(sqrt(r2));
        } else if (r2 <= 1.0) {
          *thetap = asind(sqrt(1.0 - r2));
        } else {
          *statp = 1;
          if (!status) status = PRJERR_BAD_PIX_SET("sinx2s")
          continue;
        }

      } else {
        // "Synthesis" projection.
        double xy = x0*xi + y0*eta;

        double z;
        if (r2 < 1.0e-10) {
          // Use small angle formula.
          z = r2/2.0;
          *thetap = 90.0 - R2D*sqrt(r2/(1.0 + xy));

        } else {
          double a = prj->w[2];
          double b = xy - prj->w[1];
          double c = r2 - xy - xy + prj->w[3];
          double d = b*b - a*c;

          // Check for a solution.
          if (d < 0.0) {
            *phip = 0.0;
            *thetap = 0.0;
            *statp  = 1;
            if (!status) status = PRJERR_BAD_PIX_SET("sinx2s")
            continue;
          }
          d = sqrt(d);

          // Choose solution closest to pole.
          double sinth1 = (-b + d)/a;
          double sinth2 = (-b - d)/a;
          double sinthe = (sinth1 > sinth2) ? sinth1 : sinth2;
          if (sinthe > 1.0) {
            if (sinthe-1.0 < tol) {
              sinthe = 1.0;
            } else {
              sinthe = (sinth1 < sinth2) ? sinth1 : sinth2;
            }
          }

          if (sinthe < -1.0) {
            if (sinthe+1.0 > -tol) {
              sinthe = -1.0;
            }
          }

          if (sinthe > 1.0 || sinthe < -1.0) {
            *phip = 0.0;
            *thetap = 0.0;
            *statp  = 1;
            if (!status) status = PRJERR_BAD_PIX_SET("sinx2s")
            continue;
          }

          *thetap = asind(sinthe);
          z = 1.0 - sinthe;
        }

        double x1 = -y0 + eta*z;
        double y1 =  x0 -  xi*z;
        if (x1 == 0.0 && y1 == 0.0) {
          *phip = 0.0;
        } else {
          *phip = atan2d(y1,x1);
        }
      }

      *statp = 0;
    }
  }


  // Do bounds checking on the native coordinates.
  if (prj->bounds&4 && prjbchk(1.0e-13, nx, my, spt, phi, theta, stat)) {
    if (!status) status = PRJERR_BAD_PIX_SET("sinx2s");
  }

  return status;
}

//----------------------------------------------------------------------------

int sins2x(
  struct prjprm *prj,
  int nphi,
  int ntheta,
  int spt,
  int sxy,
  const double phi[],
  const double theta[],
  double x[],
  double y[],
  int stat[])

{
  // Initialize.
  if (prj == 0x0) return PRJERR_NULL_POINTER;

  int status;
  if (abs(prj->flag) != SIN) {
    if ((status = sinset(prj))) return status;
  }

  int mphi, mtheta;
  if (ntheta > 0) {
    mphi   = nphi;
    mtheta = ntheta;
  } else {
    mphi   = 1;
    mtheta = 1;
    ntheta = nphi;
  }

  status = 0;


  // Do phi dependence.
  const double *phip = phi;
  int rowoff = 0;
  int rowlen = nphi*sxy;
  for (int iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    double sinphi, cosphi;
    sincosd(*phip, &sinphi, &cosphi);

    double *xp = x + rowoff;
    double *yp = y + rowoff;
    for (int itheta = 0; itheta < mtheta; itheta++) {
      *xp = sinphi;
      *yp = cosphi;
      xp += rowlen;
      yp += rowlen;
    }
  }


  // Do theta dependence.
  const double *thetap = theta;
  double *xp = x;
  double *yp = y;
  int *statp = stat;
  for (int itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    double costhe, z;

    double t = (90.0 - fabs(*thetap))*D2R;
    if (t < 1.0e-5) {
      if (*thetap > 0.0) {
         z = t*t/2.0;
      } else {
         z = 2.0 - t*t/2.0;
      }
      costhe = t;
    } else {
      z = 1.0 - sind(*thetap);
      costhe = cosd(*thetap);
    }
    double r = prj->r0*costhe;

    if (prj->w[1] == 0.0) {
      // Orthographic projection.
      int istat = 0;
      if (prj->bounds&1) {
        if (*thetap < 0.0) {
          istat = 1;
          if (!status) status = PRJERR_BAD_WORLD_SET("sins2x");
        }
      }

      for (int iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
        *xp =  r*(*xp) - prj->x0;
        *yp = -r*(*yp) - prj->y0;
        *statp = istat;
      }

    } else {
      // "Synthesis" projection.
      z *= prj->r0;
      double z1 = prj->pv[1]*z - prj->x0;
      double z2 = prj->pv[2]*z - prj->y0;

      for (int iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
        int istat = 0;
        if (prj->bounds&1) {
          t = -atand(prj->pv[1]*(*xp) - prj->pv[2]*(*yp));
          if (*thetap < t) {
            istat = 1;
            if (!status) status = PRJERR_BAD_WORLD_SET("sins2x");
          }
        }

        *xp =  r*(*xp) + z1;
        *yp = -r*(*yp) + z2;
        *statp = istat;
      }
    }
  }

  return status;
}

/*============================================================================
*   ARC: zenithal/azimuthal equidistant projection.
*
*   Given and/or returned:
*      prj->r0      Reset to 180/pi if 0.
*      prj->phi0    Reset to  0.0 if undefined.
*      prj->theta0  Reset to 90.0 if undefined.
*
*   Returned:
*      prj->flag     ARC
*      prj->code    "ARC"
*      prj->x0      Fiducial offset in x.
*      prj->y0      Fiducial offset in y.
*      prj->w[0]    r0*(pi/180)
*      prj->w[1]    (180/pi)/r0
*      prj->prjx2s  Pointer to arcx2s().
*      prj->prjs2x  Pointer to arcs2x().
*===========================================================================*/

int arcset(struct prjprm *prj)

{
  if (prj == 0x0) return PRJERR_NULL_POINTER;
  if (prj->flag == -ARC) return 0;

  strncpy(prj->code, "ARC", 4);

  strncpy(prj->name, "zenithal/azimuthal equidistant", 40);
  prj->category  = ZENITHAL;
  prj->pvrange   = 0;
  prj->simplezen = 1;
  prj->equiareal = 0;
  prj->conformal = 0;
  prj->global    = 1;
  prj->divergent = 0;

  if (prj->r0 == 0.0) {
    prj->r0 = R2D;
    prj->w[0] = 1.0;
    prj->w[1] = 1.0;
  } else {
    prj->w[0] = prj->r0*D2R;
    prj->w[1] = 1.0/prj->w[0];
  }

  prj->prjx2s = arcx2s;
  prj->prjs2x = arcs2x;

  prj->flag = (prj->flag == 1) ? -ARC : ARC;

  return prjoff(prj, 0.0, 90.0);
}

//----------------------------------------------------------------------------

int arcx2s(
  struct prjprm *prj,
  int nx,
  int ny,
  int sxy,
  int spt,
  const double x[],
  const double y[],
  double phi[],
  double theta[],
  int stat[])

{
  // Initialize.
  if (prj == 0x0) return PRJERR_NULL_POINTER;

  int status;
  if (abs(prj->flag) != ARC) {
    if ((status = arcset(prj))) return status;
  }

  int mx, my;
  if (ny > 0) {
    mx = nx;
    my = ny;
  } else {
    mx = 1;
    my = 1;
    ny = nx;
  }

  status = 0;


  // Do x dependence.
  const double *xp = x;
  int rowoff = 0;
  int rowlen = nx*spt;
  for (int ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    double xj = *xp + prj->x0;

    double *phip = phi + rowoff;
    for (int iy = 0; iy < my; iy++) {
      *phip = xj;
      phip += rowlen;
    }
  }


  // Do y dependence.
  const double *yp = y;
  double *phip   = phi;
  double *thetap = theta;
  int    *statp  = stat;
  for (int iy = 0; iy < ny; iy++, yp += sxy) {
    double yj  = *yp + prj->y0;
    double yj2 = yj*yj;

    for (int ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
      double xj = *phip;

      double r = sqrt(xj*xj + yj2);
      if (r == 0.0) {
        *phip = 0.0;
        *thetap = 90.0;
      } else {
        *phip = atan2d(xj, -yj);
        *thetap = 90.0 - r*prj->w[1];
      }

      *statp = 0;
    }
  }


  // Do bounds checking on the native coordinates.
  if (prj->bounds&4 && prjbchk(1.0e-13, nx, my, spt, phi, theta, stat)) {
    if (!status) status = PRJERR_BAD_PIX_SET("arcx2s");
  }

  return status;
}

//----------------------------------------------------------------------------

int arcs2x(
  struct prjprm *prj,
  int nphi,
  int ntheta,
  int spt,
  int sxy,
  const double phi[],
  const double theta[],
  double x[],
  double y[],
  int stat[])

{
  // Initialize.
  if (prj == 0x0) return PRJERR_NULL_POINTER;

  int status;
  if (abs(prj->flag) != ARC) {
    if ((status = arcset(prj))) return status;
  }

  int mphi, mtheta;
  if (ntheta > 0) {
    mphi   = nphi;
    mtheta = ntheta;
  } else {
    mphi   = 1;
    mtheta = 1;
    ntheta = nphi;
  }


  // Do phi dependence.
  const double *phip = phi;
  int rowoff = 0;
  int rowlen = nphi*sxy;
  for (int iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    double sinphi, cosphi;
    sincosd(*phip, &sinphi, &cosphi);

    double *xp = x + rowoff;
    double *yp = y + rowoff;
    for (int itheta = 0; itheta < mtheta; itheta++) {
      *xp = sinphi;
      *yp = cosphi;
      xp += rowlen;
      yp += rowlen;
    }
  }


  // Do theta dependence.
  const double *thetap = theta;
  double *xp = x;
  double *yp = y;
  int *statp = stat;
  for (int itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    double r =  prj->w[0]*(90.0 - *thetap);

    for (int iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
      *xp =  r*(*xp) - prj->x0;
      *yp = -r*(*yp) - prj->y0;
      *statp = 0;
    }
  }

  return 0;
}

/*============================================================================
*   ZPN: zenithal/azimuthal polynomial projection.
*
*   Given:
*      prj->pv[]    Polynomial coefficients.
*
*   Given and/or returned:
*      prj->r0      Reset to 180/pi if 0.
*      prj->phi0    Reset to  0.0 if undefined.
*      prj->theta0  Reset to 90.0 if undefined.
*
*   Returned:
*      prj->flag     ZPN
*      prj->code    "ZPN"
*      prj->x0      Fiducial offset in x.
*      prj->y0      Fiducial offset in y.
*      prj->n       Degree of the polynomial, N.
*      prj->w[0]    Co-latitude of the first point of inflection, radian.
*      prj->w[1]    Radius of the first point of inflection (N > 1), radian.
*      prj->prjx2s  Pointer to zpnx2s().
*      prj->prjs2x  Pointer to zpns2x().
*===========================================================================*/

int zpnset(struct prjprm *prj)

{
  const double tol = 1.0e-13;

  if (prj == 0x0) return PRJERR_NULL_POINTER;
  if (prj->flag == -ZPN) return 0;

  strncpy(prj->code, "ZPN", 4);

  if (undefined(prj->pv[1])) prj->pv[1] = 0.0;
  if (undefined(prj->pv[2])) prj->pv[2] = 0.0;
  if (undefined(prj->pv[3])) prj->pv[3] = 0.0;
  if (prj->r0 == 0.0) prj->r0 = R2D;

  strncpy(prj->name, "zenithal/azimuthal polynomial", 40);
  prj->category  = ZENITHAL;
  prj->pvrange   = 30;
  prj->simplezen = 1;
  prj->equiareal = 0;
  prj->conformal = 0;
  prj->global    = 0;
  prj->divergent = 0;

  // Find the highest non-zero coefficient.
  int k;
  for (k = PVN-1; k >= 0 && prj->pv[k] == 0.0; k--);
  if (k < 0) {
    return PRJERR_BAD_PARAM_SET("zpnset");
  }

  prj->n = k;

  if (k < 2) {
    // No point of inflection.
    prj->w[0] = PI;

  } else {
    // Find the point of inflection closest to the pole.
    double d, d1, d2;

    d1 = prj->pv[1];
    if (d1 <= 0.0) {
      return PRJERR_BAD_PARAM_SET("zpnset");
    }

    // Find the point where the derivative first goes negative.
    int j;
    double zd, zd1, zd2;

    zd1 = 0.0;
    for (j = 0; j < 180; j++) {
      zd2 = j*D2R;
      d2  = 0.0;
      for (int m = k; m > 0; m--) {
        d2 = d2*zd2 + m*prj->pv[m];
      }

      if (d2 <= 0.0) break;
      zd1 = zd2;
      d1  = d2;
    }

    if (j == 180) {
      // No negative derivative -> no point of inflection.
      zd = PI;
      prj->global = 1;
    } else {
      // Find where the derivative is zero.
      for (j = 1; j <= 10; j++) {
        zd = zd1 - d1*(zd2-zd1)/(d2-d1);

        d = 0.0;
        for (int m = k; m > 0; m--) {
          d = d*zd + m*prj->pv[m];
        }

        if (fabs(d) < tol) break;

        if (d < 0.0) {
          zd2 = zd;
          d2  = d;
        } else {
          zd1 = zd;
          d1  = d;
        }
      }
    }

    double r = 0.0;
    for (int m = k; m >= 0; m--) {
      r = r*zd + prj->pv[m];
    }
    prj->w[0] = zd;
    prj->w[1] = r;
  }

  prj->prjx2s = zpnx2s;
  prj->prjs2x = zpns2x;

  prj->flag = (prj->flag == 1) ? -ZPN : ZPN;

  return prjoff(prj, 0.0, 90.0);
}

//----------------------------------------------------------------------------

int zpnx2s(
  struct prjprm *prj,
  int nx,
  int ny,
  int sxy,
  int spt,
  const double x[],
  const double y[],
  double phi[],
  double theta[],
  int stat[])

{
  const double tol = 1.0e-13;

  // Initialize.
  if (prj == 0x0) return PRJERR_NULL_POINTER;

  int status;
  if (abs(prj->flag) != ZPN) {
    if ((status = zpnset(prj))) return status;
  }

  int k = prj->n;

  int mx, my;
  if (ny > 0) {
    mx = nx;
    my = ny;
  } else {
    mx = 1;
    my = 1;
    ny = nx;
  }

  status = 0;


  // Do x dependence.
  const double *xp = x;
  int rowoff = 0;
  int rowlen = nx*spt;
  for (int ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    double xj = *xp + prj->x0;

    double *phip = phi + rowoff;
    for (int iy = 0; iy < my; iy++) {
      *phip = xj;
      phip += rowlen;
    }
  }


  // Do y dependence.
  const double *yp = y;
  double *phip   = phi;
  double *thetap = theta;
  int    *statp  = stat;
  for (int iy = 0; iy < ny; iy++, yp += sxy) {
    double yj  = *yp + prj->y0;
    double yj2 = yj*yj;

    for (int ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
      double xj = *phip;

      double r = sqrt(xj*xj + yj2)/prj->r0;
      if (r == 0.0) {
        *phip = 0.0;
      } else {
        *phip = atan2d(xj, -yj);
      }

      double zd;
      if (k < 1) {
        // Constant - no solution.
        return PRJERR_BAD_PARAM_SET("zpnx2s");

      } else if (k == 1) {
        // Linear.
        zd = (r - prj->pv[0])/prj->pv[1];

      } else if (k == 2) {
        // Quadratic.
        double a = prj->pv[2];
        double b = prj->pv[1];
        double c = prj->pv[0] - r;

        double d = b*b - 4.0*a*c;
        if (d < 0.0) {
          *thetap = 0.0;
          *statp  = 1;
          if (!status) status = PRJERR_BAD_PIX_SET("zpnx2s");
          continue;
        }
        d = sqrt(d);

        // Choose solution closest to pole.
        double zd1 = (-b + d)/(2.0*a);
        double zd2 = (-b - d)/(2.0*a);

        zd  = (zd1<zd2) ? zd1 : zd2;
        if (zd < -tol) zd = (zd1>zd2) ? zd1 : zd2;
        if (zd < 0.0) {
          if (zd < -tol) {
            *thetap = 0.0;
            *statp  = 1;
            if (!status) status = PRJERR_BAD_PIX_SET("zpnx2s");
            continue;
          }
          zd = 0.0;
        } else if (zd > PI) {
          if (zd > PI+tol) {
            *thetap = 0.0;
            *statp  = 1;
            if (!status) status = PRJERR_BAD_PIX_SET("zpnx2s");
            continue;
          }
          zd = PI;
        }
      } else {
        // Higher order - solve iteratively.
        double zd1 = 0.0;
        double r1  = prj->pv[0];
        double zd2 = prj->w[0];
        double r2  = prj->w[1];

        if (r < r1) {
          if (r < r1-tol) {
            *thetap = 0.0;
            *statp  = 1;
            if (!status) status = PRJERR_BAD_PIX_SET("zpnx2s");
            continue;
          }
          zd = zd1;
        } else if (r > r2) {
          if (r > r2+tol) {
            *thetap = 0.0;
            *statp  = 1;
            if (!status) status = PRJERR_BAD_PIX_SET("zpnx2s");
            continue;
          }
          zd = zd2;
        } else {
          // Dissect the interval.
          for (int j = 0; j < 100; j++) {
            double lambda = (r2 - r)/(r2 - r1);
            if (lambda < 0.1) {
              lambda = 0.1;
            } else if (lambda > 0.9) {
              lambda = 0.9;
            }

            zd = zd2 - lambda*(zd2 - zd1);

            double rt = 0.0;
            for (int m = k; m >= 0; m--) {
              rt = (rt * zd) + prj->pv[m];
            }

            if (rt < r) {
              if (r-rt < tol) break;
              r1 = rt;
              zd1 = zd;
            } else {
              if (rt-r < tol) break;
              r2 = rt;
              zd2 = zd;
            }

            if (fabs(zd2-zd1) < tol) break;
          }
        }
      }

      *thetap = 90.0 - zd*R2D;
      *statp  = 0;
    }
  }


  // Do bounds checking on the native coordinates.
  if (prj->bounds&4 && prjbchk(1.0e-13, nx, my, spt, phi, theta, stat)) {
    if (!status) status = PRJERR_BAD_PIX_SET("zpnx2s");
  }

  return status;
}

//----------------------------------------------------------------------------

int zpns2x(
  struct prjprm *prj,
  int nphi,
  int ntheta,
  int spt,
  int sxy,
  const double phi[],
  const double theta[],
  double x[],
  double y[],
  int stat[])

{
  // Initialize.
  if (prj == 0x0) return PRJERR_NULL_POINTER;

  int status;
  if (abs(prj->flag) != ZPN) {
    if ((status = zpnset(prj))) return status;
  }

  int mphi, mtheta;
  if (ntheta > 0) {
    mphi   = nphi;
    mtheta = ntheta;
  } else {
    mphi   = 1;
    mtheta = 1;
    ntheta = nphi;
  }

  status = 0;


  // Do phi dependence.
  const double *phip = phi;
  int rowoff = 0;
  int rowlen = nphi*sxy;
  for (int iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    double sinphi, cosphi;
    sincosd(*phip, &sinphi, &cosphi);

    double *xp = x + rowoff;
    double *yp = y + rowoff;
    for (int itheta = 0; itheta < mtheta; itheta++) {
      *xp = sinphi;
      *yp = cosphi;
      xp += rowlen;
      yp += rowlen;
    }
  }


  // Do theta dependence.
  const double *thetap = theta;
  double *xp = x;
  double *yp = y;
  int *statp = stat;
  for (int itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    double s = (90.0 - *thetap)*D2R;

    double r = 0.0;
    for (int m = prj->n; m >= 0; m--) {
      r = r*s + prj->pv[m];
    }
    r *= prj->r0;

    // Bounds checking.
    int istat = 0;
    if (prj->bounds&1) {
      if (s > prj->w[0]) {
        istat = 1;
        if (!status) status = PRJERR_BAD_WORLD_SET("zpns2x");
      }
    }

    for (int iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
      *xp =  r*(*xp) - prj->x0;
      *yp = -r*(*yp) - prj->y0;
      *statp = istat;
    }
  }

  return status;
}

/*============================================================================
*   ZEA: zenithal/azimuthal equal area projection.
*
*   Given and/or returned:
*      prj->r0      Reset to 180/pi if 0.
*      prj->phi0    Reset to  0.0 if undefined.
*      prj->theta0  Reset to 90.0 if undefined.
*
*   Returned:
*      prj->flag     ZEA
*      prj->code    "ZEA"
*      prj->x0      Fiducial offset in x.
*      prj->y0      Fiducial offset in y.
*      prj->w[0]    2*r0
*      prj->w[1]    1/(2*r0)
*      prj->prjx2s  Pointer to zeax2s().
*      prj->prjs2x  Pointer to zeas2x().
*===========================================================================*/

int zeaset(struct prjprm *prj)

{
  if (prj == 0x0) return PRJERR_NULL_POINTER;
  if (prj->flag == -ZEA) return 0;

  strncpy(prj->code, "ZEA", 4);

  strncpy(prj->name, "zenithal/azimuthal equal area", 40);
  prj->category  = ZENITHAL;
  prj->pvrange   = 0;
  prj->simplezen = 1;
  prj->equiareal = 1;
  prj->conformal = 0;
  prj->global    = 1;
  prj->divergent = 0;

  if (prj->r0 == 0.0) {
    prj->r0 = R2D;
    prj->w[0] = 360.0/PI;
    prj->w[1] = PI/360.0;
  } else {
    prj->w[0] = 2.0*prj->r0;
    prj->w[1] = 1.0/prj->w[0];
  }

  prj->prjx2s = zeax2s;
  prj->prjs2x = zeas2x;

  prj->flag = (prj->flag == 1) ? -ZEA : ZEA;

  return prjoff(prj, 0.0, 90.0);
}

//----------------------------------------------------------------------------

int zeax2s(
  struct prjprm *prj,
  int nx,
  int ny,
  int sxy,
  int spt,
  const double x[],
  const double y[],
  double phi[],
  double theta[],
  int stat[])

{
  const double tol = 1.0e-12;

  // Initialize.
  if (prj == 0x0) return PRJERR_NULL_POINTER;

  int status;
  if (abs(prj->flag) != ZEA) {
    if ((status = zeaset(prj))) return status;
  }

  int mx, my;
  if (ny > 0) {
    mx = nx;
    my = ny;
  } else {
    mx = 1;
    my = 1;
    ny = nx;
  }

  status = 0;


  // Do x dependence.
  const double *xp = x;
  int rowoff = 0;
  int rowlen = nx*spt;
  for (int ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    double xj = *xp + prj->x0;

    double *phip = phi + rowoff;
    for (int iy = 0; iy < my; iy++) {
      *phip = xj;
      phip += rowlen;
    }
  }


  // Do y dependence.
  const double *yp = y;
  double *phip   = phi;
  double *thetap = theta;
  int    *statp  = stat;
  for (int iy = 0; iy < ny; iy++, yp += sxy) {
    double yj  = *yp + prj->y0;
    double yj2 = yj*yj;

    for (int ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
      double xj  = *phip;

      double r = sqrt(xj*xj + yj2);
      if (r == 0.0) {
        *phip = 0.0;
      } else {
        *phip = atan2d(xj, -yj);
      }

      double s = r*prj->w[1];
      if (fabs(s) > 1.0) {
        if (fabs(r - prj->w[0]) < tol) {
          *thetap = -90.0;
        } else {
          *thetap = 0.0;
          *statp  = 1;
          if (!status) status = PRJERR_BAD_PIX_SET("zeax2s");
          continue;
        }
      } else {
        *thetap = 90.0 - 2.0*asind(s);
      }

      *statp = 0;
    }
  }


  // Do bounds checking on the native coordinates.
  if (prj->bounds&4 && prjbchk(1.0e-13, nx, my, spt, phi, theta, stat)) {
    if (!status) status = PRJERR_BAD_PIX_SET("zeax2s");
  }

  return status;
}

//----------------------------------------------------------------------------

int zeas2x(
  struct prjprm *prj,
  int nphi,
  int ntheta,
  int spt,
  int sxy,
  const double phi[],
  const double theta[],
  double x[],
  double y[],
  int stat[])

{
  // Initialize.
  if (prj == 0x0) return PRJERR_NULL_POINTER;

  int status;
  if (abs(prj->flag) != ZEA) {
    if ((status = zeaset(prj))) return status;
  }

  int mphi, mtheta;
  if (ntheta > 0) {
    mphi   = nphi;
    mtheta = ntheta;
  } else {
    mphi   = 1;
    mtheta = 1;
    ntheta = nphi;
  }


  // Do phi dependence.
  const double *phip = phi;
  int rowoff = 0;
  int rowlen = nphi*sxy;
  for (int iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    double sinphi, cosphi;
    sincosd(*phip, &sinphi, &cosphi);

    double *xp = x + rowoff;
    double *yp = y + rowoff;
    for (int itheta = 0; itheta < mtheta; itheta++) {
      *xp = sinphi;
      *yp = cosphi;
      xp += rowlen;
      yp += rowlen;
    }
  }


  // Do theta dependence.
  const double *thetap = theta;
  double *xp = x;
  double *yp = y;
  int *statp = stat;
  for (int itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    double r =  prj->w[0]*sind((90.0 - *thetap)/2.0);

    for (int iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
      *xp =  r*(*xp) - prj->x0;
      *yp = -r*(*yp) - prj->y0;
      *statp = 0;
    }
  }

  return 0;
}

/*============================================================================
*   AIR: Airy's projection.
*
*   Given:
*      prj->pv[1]   Latitude theta_b within which the error is minimized, in
*                   degrees.
*
*   Given and/or returned:
*      prj->r0      Reset to 180/pi if 0.
*      prj->phi0    Reset to  0.0 if undefined.
*      prj->theta0  Reset to 90.0 if undefined.
*
*   Returned:
*      prj->flag     AIR
*      prj->code    "AIR"
*      prj->x0      Fiducial offset in x.
*      prj->y0      Fiducial offset in y.
*      prj->w[0]    2*r0
*      prj->w[1]    ln(cos(xi_b))/tan(xi_b)**2, where xi_b = (90-theta_b)/2
*      prj->w[2]    1/2 - prj->w[1]
*      prj->w[3]    2*r0*prj->w[2]
*      prj->w[4]    tol, cutoff for using small angle approximation, in
*                   radians.
*      prj->w[5]    prj->w[2]*tol
*      prj->w[6]    (180/pi)/prj->w[2]
*      prj->prjx2s  Pointer to airx2s().
*      prj->prjs2x  Pointer to airs2x().
*===========================================================================*/

int airset(struct prjprm *prj)

{
  const double tol = 1.0e-4;

  if (prj == 0x0) return PRJERR_NULL_POINTER;
  if (prj->flag == -AIR) return 0;

  strncpy(prj->code, "AIR", 4);

  if (undefined(prj->pv[1])) prj->pv[1] = 90.0;
  if (prj->r0 == 0.0) prj->r0 = R2D;

  strncpy(prj->name, "Airy's zenithal", 40);
  prj->category  = ZENITHAL;
  prj->pvrange   = 101;
  prj->simplezen = 1;
  prj->equiareal = 0;
  prj->conformal = 0;
  prj->global    = 0;
  prj->divergent = 1;

  prj->w[0] = 2.0*prj->r0;
  if (prj->pv[1] == 90.0) {
    prj->w[1] = -0.5;
    prj->w[2] =  1.0;
  } else if (prj->pv[1] > -90.0) {
    double cosxi = cosd((90.0 - prj->pv[1])/2.0);
    prj->w[1] = log(cosxi)*(cosxi*cosxi)/(1.0-cosxi*cosxi);
    prj->w[2] = 0.5 - prj->w[1];
  } else {
    return PRJERR_BAD_PARAM_SET("airset");
  }

  prj->w[3] = prj->w[0] * prj->w[2];
  prj->w[4] = tol;
  prj->w[5] = prj->w[2]*tol;
  prj->w[6] = R2D/prj->w[2];

  prj->prjx2s = airx2s;
  prj->prjs2x = airs2x;

  prj->flag = (prj->flag == 1) ? -AIR : AIR;

  return prjoff(prj, 0.0, 90.0);
}

//----------------------------------------------------------------------------

int airx2s(
  struct prjprm *prj,
  int nx,
  int ny,
  int sxy,
  int spt,
  const double x[],
  const double y[],
  double phi[],
  double theta[],
  int stat[])

{
  const double tol = 1.0e-12;

  // Initialize.
  if (prj == 0x0) return PRJERR_NULL_POINTER;

  int status;
  if (abs(prj->flag) != AIR) {
    if ((status = airset(prj))) return status;
  }

  int mx, my;
  if (ny > 0) {
    mx = nx;
    my = ny;
  } else {
    mx = 1;
    my = 1;
    ny = nx;
  }

  status = 0;


  // Do x dependence.
  const double *xp = x;
  int rowoff = 0;
  int rowlen = nx*spt;
  for (int ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    double xj = *xp + prj->x0;

    double *phip = phi + rowoff;
    for (int iy = 0; iy < my; iy++) {
      *phip = xj;
      phip += rowlen;
    }
  }


  // Do y dependence.
  const double *yp = y;
  double *phip   = phi;
  double *thetap = theta;
  int    *statp  = stat;
  for (int iy = 0; iy < ny; iy++, yp += sxy) {
    double yj  = *yp + prj->y0;
    double yj2 = yj*yj;

    for (int ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
      double xj = *phip;

      double r = sqrt(xj*xj + yj2)/prj->w[0];
      if (r == 0.0) {
        *phip = 0.0;
      } else {
        *phip = atan2d(xj, -yj);
      }

      double xi;
      if (r == 0.0) {
        xi = 0.0;
      } else if (r < prj->w[5]) {
        xi = r*prj->w[6];
      } else {
        // Find a solution interval.
        double x1 = 1.0;
        double x2 = 1.0;
        double r1 = 0.0;
        double r2 = 0.0;

        int k;
        for (k = 0; k < 30; k++) {
          x2 = x1/2.0;
          double tanxi = sqrt(1.0-x2*x2)/x2;
          r2 = -(log(x2)/tanxi + prj->w[1]*tanxi);

          if (r2 >= r) break;
          x1 = x2;
          r1 = r2;
        }
        if (k == 30) {
          *thetap = 0.0;
          *statp  = 1;
          if (!status) status = PRJERR_BAD_PIX_SET("airx2s");
          continue;
        }

        double cosxi;
        for (k = 0; k < 100; k++) {
          // Weighted division of the interval.
          double lambda = (r2-r)/(r2-r1);
          if (lambda < 0.1) {
            lambda = 0.1;
          } else if (lambda > 0.9) {
            lambda = 0.9;
          }
          cosxi = x2 - lambda*(x2-x1);

          double tanxi = sqrt(1.0-cosxi*cosxi)/cosxi;
          double rt = -(log(cosxi)/tanxi + prj->w[1]*tanxi);

          if (rt < r) {
            if (r-rt < tol) break;
            r1 = rt;
            x1 = cosxi;
          } else {
            if (rt-r < tol) break;
            r2 = rt;
            x2 = cosxi;
          }
        }
        if (k == 100) {
          *thetap = 0.0;
          *statp  = 1;
          if (!status) status = PRJERR_BAD_PIX_SET("airx2s");
          continue;
        }

        xi = acosd(cosxi);
      }

      *thetap = 90.0 - 2.0*xi;
      *statp  = 0;
    }
  }


  // Do bounds checking on the native coordinates.
  if (prj->bounds&4 && prjbchk(1.0e-13, nx, my, spt, phi, theta, stat)) {
    if (!status) status = PRJERR_BAD_PIX_SET("airx2s");
  }

  return status;
}

//----------------------------------------------------------------------------

int airs2x(
  struct prjprm *prj,
  int nphi,
  int ntheta,
  int spt,
  int sxy,
  const double phi[],
  const double theta[],
  double x[],
  double y[],
  int stat[])

{
  // Initialize.
  if (prj == 0x0) return PRJERR_NULL_POINTER;

  int status;
  if (abs(prj->flag) != AIR) {
    if ((status = airset(prj))) return status;
  }

  int mphi, mtheta;
  if (ntheta > 0) {
    mphi   = nphi;
    mtheta = ntheta;
  } else {
    mphi   = 1;
    mtheta = 1;
    ntheta = nphi;
  }

  status = 0;


  // Do phi dependence.
  const double *phip = phi;
  int rowoff = 0;
  int rowlen = nphi*sxy;
  for (int iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    double sinphi, cosphi;
    sincosd(*phip, &sinphi, &cosphi);

    double *xp = x + rowoff;
    double *yp = y + rowoff;
    for (int itheta = 0; itheta < mtheta; itheta++) {
      *xp = sinphi;
      *yp = cosphi;
      xp += rowlen;
      yp += rowlen;
    }
  }


  // Do theta dependence.
  const double *thetap = theta;
  double *xp = x;
  double *yp = y;
  int *statp = stat;
  for (int itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    int istat = 0;

    double r;
    if (*thetap == 90.0) {
      r = 0.0;
    } else if (*thetap > -90.0) {
      double xi = D2R*(90.0 - *thetap)/2.0;
      if (xi < prj->w[4]) {
        r = xi*prj->w[3];
      } else {
        double cosxi = cosd((90.0 - *thetap)/2.0);
        double tanxi = sqrt(1.0 - cosxi*cosxi)/cosxi;
        r = -prj->w[0]*(log(cosxi)/tanxi + prj->w[1]*tanxi);
      }
    } else {
      r = 0.0;
      istat = 1;
      if (!status) status = PRJERR_BAD_WORLD_SET("airs2x");
    }

    for (int iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
      *xp =  r*(*xp) - prj->x0;
      *yp = -r*(*yp) - prj->y0;
      *statp = istat;
    }
  }

  return status;
}

/*============================================================================
*   CYP: cylindrical perspective projection.
*
*   Given:
*      prj->pv[1]   Distance of point of projection from the centre of the
*                   generating sphere, mu, in units of r0.
*      prj->pv[2]   Radius of the cylinder of projection, lambda, in units of
*                   r0.
*
*   Given and/or returned:
*      prj->r0      Reset to 180/pi if 0.
*      prj->phi0    Reset to 0.0 if undefined.
*      prj->theta0  Reset to 0.0 if undefined.
*
*   Returned:
*      prj->flag     CYP
*      prj->code    "CYP"
*      prj->x0      Fiducial offset in x.
*      prj->y0      Fiducial offset in y.
*      prj->w[0]    r0*lambda*(pi/180)
*      prj->w[1]    (180/pi)/(r0*lambda)
*      prj->w[2]    r0*(mu + lambda)
*      prj->w[3]    1/(r0*(mu + lambda))
*      prj->prjx2s  Pointer to cypx2s().
*      prj->prjs2x  Pointer to cyps2x().
*===========================================================================*/

int cypset(struct prjprm *prj)

{
  if (prj == 0x0) return PRJERR_NULL_POINTER;
  if (prj->flag == -CYP) return 0;

  strncpy(prj->code, "CYP", 4);

  if (undefined(prj->pv[1])) prj->pv[1] = 1.0;
  if (undefined(prj->pv[2])) prj->pv[2] = 1.0;

  strncpy(prj->name, "cylindrical perspective", 40);
  prj->category  = CYLINDRICAL;
  prj->pvrange   = 102;
  prj->simplezen = 0;
  prj->equiareal = 0;
  prj->conformal = 0;
  prj->global    = prj->pv[1] < -1.0 || 0.0 < prj->pv[1];
  prj->divergent = !prj->global;

  if (prj->r0 == 0.0) {
    prj->r0 = R2D;

    prj->w[0] = prj->pv[2];
    if (prj->w[0] == 0.0) {
      return PRJERR_BAD_PARAM_SET("cypset");
    }

    prj->w[1] = 1.0/prj->w[0];

    prj->w[2] = R2D*(prj->pv[1] + prj->pv[2]);
    if (prj->w[2] == 0.0) {
      return PRJERR_BAD_PARAM_SET("cypset");
    }

    prj->w[3] = 1.0/prj->w[2];
  } else {
    prj->w[0] = prj->r0*prj->pv[2]*D2R;
    if (prj->w[0] == 0.0) {
      return PRJERR_BAD_PARAM_SET("cypset");
    }

    prj->w[1] = 1.0/prj->w[0];

    prj->w[2] = prj->r0*(prj->pv[1] + prj->pv[2]);
    if (prj->w[2] == 0.0) {
      return PRJERR_BAD_PARAM_SET("cypset");
    }

    prj->w[3] = 1.0/prj->w[2];
  }

  prj->prjx2s = cypx2s;
  prj->prjs2x = cyps2x;

  prj->flag = (prj->flag == 1) ? -CYP : CYP;

  return prjoff(prj, 0.0, 0.0);
}

//----------------------------------------------------------------------------

int cypx2s(
  struct prjprm *prj,
  int nx,
  int ny,
  int sxy,
  int spt,
  const double x[],
  const double y[],
  double phi[],
  double theta[],
  int stat[])

{
  // Initialize.
  if (prj == 0x0) return PRJERR_NULL_POINTER;

  int status;
  if (abs(prj->flag) != CYP) {
    if ((status = cypset(prj))) return status;
  }

  int mx, my;
  if (ny > 0) {
    mx = nx;
    my = ny;
  } else {
    mx = 1;
    my = 1;
    ny = nx;
  }

  status = 0;


  // Do x dependence.
  const double *xp = x;
  int rowoff = 0;
  int rowlen = nx*spt;
  for (int ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    double s = prj->w[1]*(*xp + prj->x0);

    double *phip = phi + rowoff;
    for (int iy = 0; iy < my; iy++) {
      *phip = s;
      phip += rowlen;
    }
  }


  // Do y dependence.
  const double *yp = y;
  double *thetap = theta;
  int    *statp  = stat;
  for (int iy = 0; iy < ny; iy++, yp += sxy) {
    double eta = prj->w[3]*(*yp + prj->y0);
    double t = atan2d(eta,1.0) + asind(eta*prj->pv[1]/sqrt(eta*eta+1.0));

    for (int ix = 0; ix < mx; ix++, thetap += spt, statp++) {
      *thetap = t;
      *statp  = 0;
    }
  }


  // Do bounds checking on the native coordinates.
  if (prj->bounds&4 && prjbchk(1.0e-13, nx, my, spt, phi, theta, stat)) {
    if (!status) status = PRJERR_BAD_PIX_SET("cypx2s");
  }

  return status;
}

//----------------------------------------------------------------------------

int cyps2x(
  struct prjprm *prj,
  int nphi,
  int ntheta,
  int spt,
  int sxy,
  const double phi[],
  const double theta[],
  double x[],
  double y[],
  int stat[])

{
  // Initialize.
  if (prj == 0x0) return PRJERR_NULL_POINTER;

  int status;
  if (abs(prj->flag) != CYP) {
    if ((status = cypset(prj))) return status;
  }

  int mphi, mtheta;
  if (ntheta > 0) {
    mphi   = nphi;
    mtheta = ntheta;
  } else {
    mphi   = 1;
    mtheta = 1;
    ntheta = nphi;
  }

  status = 0;


  // Do phi dependence.
  const double *phip = phi;
  int rowoff = 0;
  int rowlen = nphi*sxy;
  for (int iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    double xi = prj->w[0]*(*phip) - prj->x0;

    double *xp = x + rowoff;
    for (int itheta = 0; itheta < mtheta; itheta++) {
      *xp = xi;
      xp += rowlen;
    }
  }


  // Do theta dependence.
  const double *thetap = theta;
  double *yp = y;
  int *statp = stat;
  for (int itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    double eta = prj->pv[1] + cosd(*thetap);

    int istat = 0;
    if (eta == 0.0) {
      istat = 1;
      if (!status) status = PRJERR_BAD_WORLD_SET("cyps2x");

    } else {
      eta = prj->w[2]*sind(*thetap)/eta;
    }

    eta -= prj->y0;
    for (int iphi = 0; iphi < mphi; iphi++, yp += sxy, statp++) {
      *yp = eta;
      *statp = istat;
    }
  }

  return status;
}

/*============================================================================
*   CEA: cylindrical equal area projection.
*
*   Given:
*      prj->pv[1]   Square of the cosine of the latitude at which the
*                   projection is conformal, lambda.
*
*   Given and/or returned:
*      prj->r0      Reset to 180/pi if 0.
*      prj->phi0    Reset to 0.0 if undefined.
*      prj->theta0  Reset to 0.0 if undefined.
*
*   Returned:
*      prj->flag     CEA
*      prj->code    "CEA"
*      prj->x0      Fiducial offset in x.
*      prj->y0      Fiducial offset in y.
*      prj->w[0]    r0*(pi/180)
*      prj->w[1]    (180/pi)/r0
*      prj->w[2]    r0/lambda
*      prj->w[3]    lambda/r0
*      prj->prjx2s  Pointer to ceax2s().
*      prj->prjs2x  Pointer to ceas2x().
*===========================================================================*/

int ceaset(struct prjprm *prj)

{
  if (prj == 0x0) return PRJERR_NULL_POINTER;
  if (prj->flag == -CEA) return 0;

  strncpy(prj->code, "CEA", 4);

  if (undefined(prj->pv[1])) prj->pv[1] = 1.0;

  strncpy(prj->name, "cylindrical equal area", 40);
  prj->category  = CYLINDRICAL;
  prj->pvrange   = 101;
  prj->simplezen = 0;
  prj->equiareal = 1;
  prj->conformal = 0;
  prj->global    = 1;
  prj->divergent = 0;

  if (prj->r0 == 0.0) {
    prj->r0 = R2D;
    prj->w[0] = 1.0;
    prj->w[1] = 1.0;
    if (prj->pv[1] <= 0.0 || prj->pv[1] > 1.0) {
      return PRJERR_BAD_PARAM_SET("ceaset");
    }
    prj->w[2] = prj->r0/prj->pv[1];
    prj->w[3] = prj->pv[1]/prj->r0;
  } else {
    prj->w[0] = prj->r0*D2R;
    prj->w[1] = R2D/prj->r0;
    if (prj->pv[1] <= 0.0 || prj->pv[1] > 1.0) {
      return PRJERR_BAD_PARAM_SET("ceaset");
    }
    prj->w[2] = prj->r0/prj->pv[1];
    prj->w[3] = prj->pv[1]/prj->r0;
  }

  prj->prjx2s = ceax2s;
  prj->prjs2x = ceas2x;

  prj->flag = (prj->flag == 1) ? -CEA : CEA;

  return prjoff(prj, 0.0, 0.0);
}

//----------------------------------------------------------------------------

int ceax2s(
  struct prjprm *prj,
  int nx,
  int ny,
  int sxy,
  int spt,
  const double x[],
  const double y[],
  double phi[],
  double theta[],
  int stat[])

{
  const double tol = 1.0e-13;

  // Initialize.
  if (prj == 0x0) return PRJERR_NULL_POINTER;

  int status;
  if (abs(prj->flag) != CEA) {
    if ((status = ceaset(prj))) return status;
  }

  int mx, my;
  if (ny > 0) {
    mx = nx;
    my = ny;
  } else {
    mx = 1;
    my = 1;
    ny = nx;
  }

  status = 0;


  // Do x dependence.
  const double *xp = x;
  int rowoff = 0;
  int rowlen = nx*spt;
  for (int ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    double s = prj->w[1]*(*xp + prj->x0);

    double *phip = phi + rowoff;
    for (int iy = 0; iy < my; iy++) {
      *phip = s;
      phip += rowlen;
    }
  }


  // Do y dependence.
  const double *yp = y;
  double *thetap = theta;
  int    *statp  = stat;
  for (int iy = 0; iy < ny; iy++, yp += sxy) {
    double s = prj->w[3]*(*yp + prj->y0);

    int istat = 0;
    if (fabs(s) > 1.0) {
      if (fabs(s) > 1.0+tol) {
        s = 0.0;
        istat = 1;
        if (!status) status = PRJERR_BAD_PIX_SET("ceax2s");
      } else {
        s = copysign(90.0, s);
      }
    } else {
      s = asind(s);
    }

    for (int ix = 0; ix < mx; ix++, thetap += spt, statp++) {
      *thetap = s;
      *statp  = istat;
    }
  }


  // Do bounds checking on the native coordinates.
  if (prj->bounds&4 && prjbchk(1.0e-13, nx, my, spt, phi, theta, stat)) {
    if (!status) status = PRJERR_BAD_PIX_SET("ceax2s");
  }

  return status;
}

//----------------------------------------------------------------------------

int ceas2x(
  struct prjprm *prj,
  int nphi,
  int ntheta,
  int spt,
  int sxy,
  const double phi[],
  const double theta[],
  double x[],
  double y[],
  int stat[])

{
  // Initialize.
  if (prj == 0x0) return PRJERR_NULL_POINTER;

  int status;
  if (abs(prj->flag) != CEA) {
    if ((status = ceaset(prj))) return status;
  }

  int mphi, mtheta;
  if (ntheta > 0) {
    mphi   = nphi;
    mtheta = ntheta;
  } else {
    mphi   = 1;
    mtheta = 1;
    ntheta = nphi;
  }


  // Do phi dependence.
  const double *phip = phi;
  int rowoff = 0;
  int rowlen = nphi*sxy;
  for (int iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    double xi = prj->w[0]*(*phip) - prj->x0;

    double *xp = x + rowoff;
    for (int itheta = 0; itheta < mtheta; itheta++) {
      *xp = xi;
      xp += rowlen;
    }
  }


  // Do theta dependence.
  const double *thetap = theta;
  double *yp = y;
  int *statp = stat;
  for (int itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    double eta = prj->w[2]*sind(*thetap) - prj->y0;

    for (int iphi = 0; iphi < mphi; iphi++, yp += sxy, statp++) {
      *yp = eta;
      *statp = 0;
    }
  }

  return 0;
}

/*============================================================================
*   CAR: Plate carree projection.
*
*   Given and/or returned:
*      prj->r0      Reset to 180/pi if 0.
*      prj->phi0    Reset to 0.0 if undefined.
*      prj->theta0  Reset to 0.0 if undefined.
*
*   Returned:
*      prj->flag     CAR
*      prj->code    "CAR"
*      prj->x0      Fiducial offset in x.
*      prj->y0      Fiducial offset in y.
*      prj->w[0]    r0*(pi/180)
*      prj->w[1]    (180/pi)/r0
*      prj->prjx2s  Pointer to carx2s().
*      prj->prjs2x  Pointer to cars2x().
*===========================================================================*/

int carset(struct prjprm *prj)

{
  if (prj == 0x0) return PRJERR_NULL_POINTER;
  if (prj->flag == -CAR) return 0;

  strncpy(prj->code, "CAR", 4);

  strncpy(prj->name, "plate caree", 40);
  prj->category  = CYLINDRICAL;
  prj->pvrange   = 0;
  prj->simplezen = 0;
  prj->equiareal = 0;
  prj->conformal = 0;
  prj->global    = 1;
  prj->divergent = 0;

  if (prj->r0 == 0.0) {
    prj->r0 = R2D;
    prj->w[0] = 1.0;
    prj->w[1] = 1.0;
  } else {
    prj->w[0] = prj->r0*D2R;
    prj->w[1] = 1.0/prj->w[0];
  }

  prj->prjx2s = carx2s;
  prj->prjs2x = cars2x;

  prj->flag = (prj->flag == 1) ? -CAR : CAR;

  return prjoff(prj, 0.0, 0.0);
}

//----------------------------------------------------------------------------

int carx2s(
  struct prjprm *prj,
  int nx,
  int ny,
  int sxy,
  int spt,
  const double x[],
  const double y[],
  double phi[],
  double theta[],
  int stat[])

{
  // Initialize.
  if (prj == 0x0) return PRJERR_NULL_POINTER;

  int status;
  if (abs(prj->flag) != CAR) {
    if ((status = carset(prj))) return status;
  }

  int mx, my;
  if (ny > 0) {
    mx = nx;
    my = ny;
  } else {
    mx = 1;
    my = 1;
    ny = nx;
  }

  status = 0;


  // Do x dependence.
  const double *xp = x;
  int rowoff = 0;
  int rowlen = nx*spt;
  for (int ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    double s = prj->w[1]*(*xp + prj->x0);

    double *phip = phi + rowoff;
    for (int iy = 0; iy < my; iy++) {
      *phip = s;
      phip += rowlen;
    }
  }


  // Do y dependence.
  const double *yp = y;
  double *thetap = theta;
  int    *statp  = stat;
  for (int iy = 0; iy < ny; iy++, yp += sxy) {
    double t = prj->w[1]*(*yp + prj->y0);

    for (int ix = 0; ix < mx; ix++, thetap += spt, statp++) {
      *thetap = t;
      *statp  = 0;
    }
  }


  // Do bounds checking on the native coordinates.
  if (prj->bounds&4 && prjbchk(1.0e-13, nx, my, spt, phi, theta, stat)) {
    if (!status) status = PRJERR_BAD_PIX_SET("carx2s");
  }

  return status;
}

//----------------------------------------------------------------------------

int cars2x(
  struct prjprm *prj,
  int nphi,
  int ntheta,
  int spt,
  int sxy,
  const double phi[],
  const double theta[],
  double x[],
  double y[],
  int stat[])

{
  // Initialize.
  if (prj == 0x0) return PRJERR_NULL_POINTER;

  int status;
  if (abs(prj->flag) != CAR) {
    if ((status = carset(prj))) return status;
  }

  int mphi, mtheta;
  if (ntheta > 0) {
    mphi   = nphi;
    mtheta = ntheta;
  } else {
    mphi   = 1;
    mtheta = 1;
    ntheta = nphi;
  }


  // Do phi dependence.
  const double *phip = phi;
  int rowoff = 0;
  int rowlen = nphi*sxy;
  for (int iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    double xi = prj->w[0]*(*phip) - prj->x0;

    double *xp = x + rowoff;
    for (int itheta = 0; itheta < mtheta; itheta++) {
      *xp = xi;
      xp += rowlen;
    }
  }


  // Do theta dependence.
  const double *thetap = theta;
  double *yp = y;
  int *statp = stat;
  for (int itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    double eta = prj->w[0]*(*thetap) - prj->y0;

    for (int iphi = 0; iphi < mphi; iphi++, yp += sxy, statp++) {
      *yp = eta;
      *statp = 0;
    }
  }

  return 0;
}

/*============================================================================
*   MER: Mercator's projection.
*
*   Given and/or returned:
*      prj->r0      Reset to 180/pi if 0.
*      prj->phi0    Reset to 0.0 if undefined.
*      prj->theta0  Reset to 0.0 if undefined.
*
*   Returned:
*      prj->flag     MER
*      prj->code    "MER"
*      prj->x0      Fiducial offset in x.
*      prj->y0      Fiducial offset in y.
*      prj->w[0]    r0*(pi/180)
*      prj->w[1]    (180/pi)/r0
*      prj->prjx2s  Pointer to merx2s().
*      prj->prjs2x  Pointer to mers2x().
*===========================================================================*/

int merset(struct prjprm *prj)

{
  if (prj == 0x0) return PRJERR_NULL_POINTER;
  if (prj->flag == -MER) return 0;

  strncpy(prj->code, "MER", 4);

  strncpy(prj->name, "Mercator's", 40);
  prj->category  = CYLINDRICAL;
  prj->pvrange   = 0;
  prj->simplezen = 0;
  prj->equiareal = 0;
  prj->conformal = 1;
  prj->global    = 0;
  prj->divergent = 1;

  if (prj->r0 == 0.0) {
    prj->r0 = R2D;
    prj->w[0] = 1.0;
    prj->w[1] = 1.0;
  } else {
    prj->w[0] = prj->r0*D2R;
    prj->w[1] = 1.0/prj->w[0];
  }

  prj->prjx2s = merx2s;
  prj->prjs2x = mers2x;

  prj->flag = (prj->flag == 1) ? -MER : MER;

  return prjoff(prj, 0.0, 0.0);
}

//----------------------------------------------------------------------------

int merx2s(
  struct prjprm *prj,
  int nx,
  int ny,
  int sxy,
  int spt,
  const double x[],
  const double y[],
  double phi[],
  double theta[],
  int stat[])

{
  // Initialize.
  if (prj == 0x0) return PRJERR_NULL_POINTER;

  int status;
  if (abs(prj->flag) != MER) {
    if ((status = merset(prj))) return status;
  }

  int mx, my;
  if (ny > 0) {
    mx = nx;
    my = ny;
  } else {
    mx = 1;
    my = 1;
    ny = nx;
  }

  status = 0;


  // Do x dependence.
  const double *xp = x;
  int rowoff = 0;
  int rowlen = nx*spt;
  for (int ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    double s = prj->w[1]*(*xp + prj->x0);

    double *phip = phi + rowoff;
    for (int iy = 0; iy < my; iy++) {
      *phip = s;
      phip += rowlen;
    }
  }


  // Do y dependence.
  const double *yp = y;
  double *thetap = theta;
  int    *statp  = stat;
  for (int iy = 0; iy < ny; iy++, yp += sxy) {
    double t = 2.0*atand(exp((*yp + prj->y0)/prj->r0)) - 90.0;

    for (int ix = 0; ix < mx; ix++, thetap += spt, statp++) {
      *thetap = t;
      *statp  = 0;
    }
  }


  // Do bounds checking on the native coordinates.
  if (prj->bounds&4 && prjbchk(1.0e-13, nx, my, spt, phi, theta, stat)) {
    if (!status) status = PRJERR_BAD_PIX_SET("merx2s");
  }

  return status;
}

//----------------------------------------------------------------------------

int mers2x(
  struct prjprm *prj,
  int nphi,
  int ntheta,
  int spt,
  int sxy,
  const double phi[],
  const double theta[],
  double x[],
  double y[],
  int stat[])

{
  // Initialize.
  if (prj == 0x0) return PRJERR_NULL_POINTER;

  int status;
  if (abs(prj->flag) != MER) {
    if ((status = merset(prj))) return status;
  }

  int mphi, mtheta;
  if (ntheta > 0) {
    mphi   = nphi;
    mtheta = ntheta;
  } else {
    mphi   = 1;
    mtheta = 1;
    ntheta = nphi;
  }

  status = 0;


  // Do phi dependence.
  const double *phip = phi;
  int rowoff = 0;
  int rowlen = nphi*sxy;
  for (int iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    double xi  = prj->w[0]*(*phip) - prj->x0;

    double *xp = x + rowoff;
    for (int itheta = 0; itheta < mtheta; itheta++) {
      *xp = xi;
      xp += rowlen;
    }
  }


  // Do theta dependence.
  const double *thetap = theta;
  double *yp = y;
  int *statp = stat;
  for (int itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    int istat = 0;

    double eta;
    if (*thetap <= -90.0 || *thetap >= 90.0) {
      eta = 0.0;
      istat = 1;
      if (!status) status = PRJERR_BAD_WORLD_SET("mers2x");
    } else {
      eta = prj->r0*log(tand((*thetap+90.0)/2.0)) - prj->y0;
    }

    for (int iphi = 0; iphi < mphi; iphi++, yp += sxy, statp++) {
      *yp = eta;
      *statp = istat;
    }
  }

  return status;
}

/*============================================================================
*   SFL: Sanson-Flamsteed ("global sinusoid") projection.
*
*   Given and/or returned:
*      prj->r0      Reset to 180/pi if 0.
*      prj->phi0    Reset to 0.0 if undefined.
*      prj->theta0  Reset to 0.0 if undefined.
*
*   Returned:
*      prj->flag     SFL
*      prj->code    "SFL"
*      prj->x0      Fiducial offset in x.
*      prj->y0      Fiducial offset in y.
*      prj->w[0]    r0*(pi/180)
*      prj->w[1]    (180/pi)/r0
*      prj->prjx2s  Pointer to sflx2s().
*      prj->prjs2x  Pointer to sfls2x().
*===========================================================================*/

int sflset(struct prjprm *prj)

{
  if (prj == 0x0) return PRJERR_NULL_POINTER;
  if (prj->flag == -SFL) return 0;

  strncpy(prj->code, "SFL", 4);

  strncpy(prj->name, "Sanson-Flamsteed", 40);
  prj->category  = PSEUDOCYLINDRICAL;
  prj->pvrange   = 0;
  prj->simplezen = 0;
  prj->equiareal = 1;
  prj->conformal = 0;
  prj->global    = 1;
  prj->divergent = 0;

  if (prj->r0 == 0.0) {
    prj->r0 = R2D;
    prj->w[0] = 1.0;
    prj->w[1] = 1.0;
  } else {
    prj->w[0] = prj->r0*D2R;
    prj->w[1] = 1.0/prj->w[0];
  }

  prj->prjx2s = sflx2s;
  prj->prjs2x = sfls2x;

  prj->flag = (prj->flag == 1) ? -SFL : SFL;

  return prjoff(prj, 0.0, 0.0);
}

//----------------------------------------------------------------------------

int sflx2s(
  struct prjprm *prj,
  int nx,
  int ny,
  int sxy,
  int spt,
  const double x[],
  const double y[],
  double phi[],
  double theta[],
  int stat[])

{
  // Initialize.
  if (prj == 0x0) return PRJERR_NULL_POINTER;

  int status;
  if (abs(prj->flag) != SFL) {
    if ((status = sflset(prj))) return status;
  }

  int mx, my;
  if (ny > 0) {
    mx = nx;
    my = ny;
  } else {
    mx = 1;
    my = 1;
    ny = nx;
  }

  status = 0;


  // Do x dependence.
  const double *xp = x;
  int rowoff = 0;
  int rowlen = nx*spt;
  for (int ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    double s = prj->w[1]*(*xp + prj->x0);

    double *phip = phi + rowoff;
    for (int iy = 0; iy < my; iy++) {
      *phip = s;
      phip += rowlen;
    }
  }


  // Do y dependence.
  const double *yp = y;
  double *phip   = phi;
  double *thetap = theta;
  int    *statp  = stat;
  for (int iy = 0; iy < ny; iy++, yp += sxy) {
    double yj = *yp + prj->y0;
    double s = cos(yj/prj->r0);

    int istat = 0;
    if (s == 0.0) {
      istat = 1;
      if (!status) status = PRJERR_BAD_PIX_SET("sflx2s");
    } else {
      s = 1.0/s;
    }

    double t = prj->w[1]*yj;

    for (int ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
      *phip  *= s;
      *thetap = t;
      *statp  = istat;
    }
  }


  // Do bounds checking on the native coordinates.
  if (prj->bounds&4 && prjbchk(1.0e-12, nx, my, spt, phi, theta, stat)) {
    if (!status) status = PRJERR_BAD_PIX_SET("sflx2s");
  }

  return status;
}

//----------------------------------------------------------------------------

int sfls2x(
  struct prjprm *prj,
  int nphi,
  int ntheta,
  int spt,
  int sxy,
  const double phi[],
  const double theta[],
  double x[],
  double y[],
  int stat[])

{
  // Initialize.
  if (prj == 0x0) return PRJERR_NULL_POINTER;

  int status;
  if (abs(prj->flag) != SFL) {
    if ((status = sflset(prj))) return status;
  }

  int mphi, mtheta;
  if (ntheta > 0) {
    mphi   = nphi;
    mtheta = ntheta;
  } else {
    mphi   = 1;
    mtheta = 1;
    ntheta = nphi;
  }


  // Do phi dependence.
  const double *phip = phi;
  int rowoff = 0;
  int rowlen = nphi*sxy;
  for (int iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    double xi = prj->w[0]*(*phip);

    double *xp = x + rowoff;
    for (int itheta = 0; itheta < mtheta; itheta++) {
      *xp = xi;
      xp += rowlen;
    }
  }


  // Do theta dependence.
  const double *thetap = theta;
  double *xp = x;
  double *yp = y;
  int *statp = stat;
  for (int itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    double xi  = cosd(*thetap);
    double eta = prj->w[0]*(*thetap) - prj->y0;

    for (int iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
      *xp = xi*(*xp) - prj->x0;
      *yp = eta;
      *statp = 0;
    }
  }

  return 0;
}

/*============================================================================
*   PAR: parabolic projection.
*
*   Given and/or returned:
*      prj->r0      Reset to 180/pi if 0.
*      prj->phi0    Reset to 0.0 if undefined.
*      prj->theta0  Reset to 0.0 if undefined.
*
*   Returned:
*      prj->flag     PAR
*      prj->code    "PAR"
*      prj->x0      Fiducial offset in x.
*      prj->y0      Fiducial offset in y.
*      prj->w[0]    r0*(pi/180)
*      prj->w[1]    (180/pi)/r0
*      prj->w[2]    pi*r0
*      prj->w[3]    1/(pi*r0)
*      prj->prjx2s  Pointer to parx2s().
*      prj->prjs2x  Pointer to pars2x().
*===========================================================================*/

int parset(struct prjprm *prj)

{
  if (prj == 0x0) return PRJERR_NULL_POINTER;
  if (prj->flag == -PAR) return 0;

  strncpy(prj->code, "PAR", 4);

  strncpy(prj->name, "parabolic", 40);
  prj->category  = PSEUDOCYLINDRICAL;
  prj->pvrange   = 0;
  prj->simplezen = 0;
  prj->equiareal = 1;
  prj->conformal = 0;
  prj->global    = 1;
  prj->divergent = 0;

  if (prj->r0 == 0.0) {
    prj->r0 = R2D;
    prj->w[0] = 1.0;
    prj->w[1] = 1.0;
    prj->w[2] = 180.0;
    prj->w[3] = 1.0/prj->w[2];
  } else {
    prj->w[0] = prj->r0*D2R;
    prj->w[1] = 1.0/prj->w[0];
    prj->w[2] = PI*prj->r0;
    prj->w[3] = 1.0/prj->w[2];
  }

  prj->prjx2s = parx2s;
  prj->prjs2x = pars2x;

  prj->flag = (prj->flag == 1) ? -PAR : PAR;

  return prjoff(prj, 0.0, 0.0);
}

//----------------------------------------------------------------------------

int parx2s(
  struct prjprm *prj,
  int nx,
  int ny,
  int sxy,
  int spt,
  const double x[],
  const double y[],
  double phi[],
  double theta[],
  int stat[])

{
  const double tol = 1.0e-13;

  // Initialize.
  if (prj == 0x0) return PRJERR_NULL_POINTER;

  int status;
  if (abs(prj->flag) != PAR) {
    if ((status = parset(prj))) return status;
  }

  int mx, my;
  if (ny > 0) {
    mx = nx;
    my = ny;
  } else {
    mx = 1;
    my = 1;
    ny = nx;
  }

  status = 0;


  // Do x dependence.
  const double *xp = x;
  int rowoff = 0;
  int rowlen = nx*spt;
  for (int ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    double xj = *xp + prj->x0;
    double s = prj->w[1]*xj;
    double t = fabs(xj) - tol;

    double *phip   = phi   + rowoff;
    double *thetap = theta + rowoff;
    for (int iy = 0; iy < my; iy++) {
      *phip   = s;
      *thetap = t;
      phip   += rowlen;
      thetap += rowlen;
    }
  }


  // Do y dependence.
  const double *yp = y;
  double *phip   = phi;
  double *thetap = theta;
  int    *statp  = stat;
  for (int iy = 0; iy < ny; iy++, yp += sxy) {
    double r = prj->w[3]*(*yp + prj->y0);

    int istat = 0;
    double s, t;
    if (r > 1.0 || r < -1.0) {
      s = 0.0;
      t = 0.0;
      istat = 1;
      if (!status) status = PRJERR_BAD_PIX_SET("parx2s");

    } else {
      s = 1.0 - 4.0*r*r;
      if (s == 0.0) {
        // Deferred test.
        istat = -1;
      } else {
        s = 1.0/s;
      }

      t = 3.0*asind(r);
    }

    for (int ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
      if (istat < 0) {
        if (*thetap < 0.0) {
          *statp = 0;
        } else {
          *statp = 1;
          if (!status) status = PRJERR_BAD_PIX_SET("parx2s");
        }
      } else {
        *statp = istat;
      }

      *phip  *= s;
      *thetap = t;
    }
  }


  // Do bounds checking on the native coordinates.
  if (prj->bounds&4 && prjbchk(1.0e-12, nx, my, spt, phi, theta, stat)) {
    if (!status) status = PRJERR_BAD_PIX_SET("parx2s");
  }

  return status;
}

//----------------------------------------------------------------------------

int pars2x(
  struct prjprm *prj,
  int nphi,
  int ntheta,
  int spt,
  int sxy,
  const double phi[],
  const double theta[],
  double x[],
  double y[],
  int stat[])

{
  // Initialize.
  if (prj == 0x0) return PRJERR_NULL_POINTER;

  int status;
  if (abs(prj->flag) != PAR) {
    if ((status = parset(prj))) return status;
  }

  int mphi, mtheta;
  if (ntheta > 0) {
    mphi   = nphi;
    mtheta = ntheta;
  } else {
    mphi   = 1;
    mtheta = 1;
    ntheta = nphi;
  }


  // Do phi dependence.
  const double *phip = phi;
  int rowoff = 0;
  int rowlen = nphi*sxy;
  for (int iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    double xi = prj->w[0]*(*phip);

    double *xp = x + rowoff;
    for (int itheta = 0; itheta < mtheta; itheta++) {
      *xp = xi;
      xp += rowlen;
    }
  }


  // Do theta dependence.
  const double *thetap = theta;
  double *xp = x;
  double *yp = y;
  int *statp = stat;
  for (int itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    double s = sind((*thetap)/3.0);
    double xi = (1.0 - 4.0*s*s);
    double eta = prj->w[2]*s - prj->y0;

    for (int iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
      *xp = xi*(*xp) - prj->x0;
      *yp = eta;
      *statp = 0;
    }
  }

  return 0;
}

/*============================================================================
*   MOL: Mollweide's projection.
*
*   Given and/or returned:
*      prj->r0      Reset to 180/pi if 0.
*      prj->phi0    Reset to 0.0 if undefined.
*      prj->theta0  Reset to 0.0 if undefined.
*
*   Returned:
*      prj->flag     MOL
*      prj->code    "MOL"
*      prj->x0      Fiducial offset in x.
*      prj->y0      Fiducial offset in y.
*      prj->w[0]    sqrt(2)*r0
*      prj->w[1]    sqrt(2)*r0/90
*      prj->w[2]    1/(sqrt(2)*r0)
*      prj->w[3]    90/r0
*      prj->prjx2s  Pointer to molx2s().
*      prj->prjs2x  Pointer to mols2x().
*===========================================================================*/

int molset(struct prjprm *prj)

{
  if (prj == 0x0) return PRJERR_NULL_POINTER;
  if (prj->flag == -MOL) return 0;

  strncpy(prj->code, "MOL", 4);

  if (prj->r0 == 0.0) prj->r0 = R2D;

  strncpy(prj->name, "Mollweide's", 40);
  prj->category  = PSEUDOCYLINDRICAL;
  prj->pvrange   = 0;
  prj->simplezen = 0;
  prj->equiareal = 1;
  prj->conformal = 0;
  prj->global    = 1;
  prj->divergent = 0;

  prj->w[0] = SQRT2*prj->r0;
  prj->w[1] = prj->w[0]/90.0;
  prj->w[2] = 1.0/prj->w[0];
  prj->w[3] = 90.0/prj->r0;
  prj->w[4] = 2.0/PI;

  prj->prjx2s = molx2s;
  prj->prjs2x = mols2x;

  prj->flag = (prj->flag == 1) ? -MOL : MOL;

  return prjoff(prj, 0.0, 0.0);
}

//----------------------------------------------------------------------------

int molx2s(
  struct prjprm *prj,
  int nx,
  int ny,
  int sxy,
  int spt,
  const double x[],
  const double y[],
  double phi[],
  double theta[],
  int stat[])

{
  const double tol = 1.0e-12;

  // Initialize.
  if (prj == 0x0) return PRJERR_NULL_POINTER;

  int status;
  if (abs(prj->flag) != MOL) {
    if ((status = molset(prj))) return status;
  }

  int mx, my;
  if (ny > 0) {
    mx = nx;
    my = ny;
  } else {
    mx = 1;
    my = 1;
    ny = nx;
  }

  status = 0;


  // Do x dependence.
  const double *xp = x;
  int rowoff = 0;
  int rowlen = nx*spt;
  for (int ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    double xj = *xp + prj->x0;
    double s = prj->w[3]*xj;
    double t = fabs(xj) - tol;

    double *phip   = phi   + rowoff;
    double *thetap = theta + rowoff;
    for (int iy = 0; iy < my; iy++) {
      *phip   = s;
      *thetap = t;
      phip   += rowlen;
      thetap += rowlen;
    }
  }


  // Do y dependence.
  const double *yp = y;
  double *phip   = phi;
  double *thetap = theta;
  int    *statp  = stat;
  for (int iy = 0; iy < ny; iy++, yp += sxy) {
    double yj = *yp + prj->y0;
    double y0 = yj/prj->r0;
    double r  = 2.0 - y0*y0;

    int istat = 0;
    double s;
    if (r <= tol) {
      if (r < -tol) {
        istat = 1;
        if (!status) status = PRJERR_BAD_PIX_SET("molx2s");
      } else {
        // OK if fabs(x) < tol whence phi = 0.0.
        istat = -1;
      }

      r = 0.0;
      s = 0.0;

    } else {
      r = sqrt(r);
      s = 1.0/r;
    }

    double z = yj*prj->w[2];
    if (fabs(z) > 1.0) {
      if (fabs(z) > 1.0+tol) {
        z = 0.0;
        istat = 1;
        if (!status) status = PRJERR_BAD_PIX_SET("molx2s");
      } else {
        z = copysign(1.0, z) + y0*r/PI;
      }
    } else {
      z = asin(z)*prj->w[4] + y0*r/PI;
    }

    if (fabs(z) > 1.0) {
      if (fabs(z) > 1.0+tol) {
        z = 0.0;
        istat = 1;
        if (!status) status = PRJERR_BAD_PIX_SET("molx2s");
      } else {
        z = copysign(1.0, z);
      }
    }

    double t = asind(z);

    for (int ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
      if (istat < 0) {
        if (*thetap < 0.0) {
          *statp = 0;
        } else {
          *statp = 1;
          if (!status) status = PRJERR_BAD_PIX_SET("molx2s");
        }
      } else {
        *statp = istat;
      }

      *phip  *= s;
      *thetap = t;
    }
  }


  // Do bounds checking on the native coordinates.
  if (prj->bounds&4 && prjbchk(1.0e-11, nx, my, spt, phi, theta, stat)) {
    if (!status) status = PRJERR_BAD_PIX_SET("molx2s");
  }

  return status;
}

//----------------------------------------------------------------------------

int mols2x(
  struct prjprm *prj,
  int nphi,
  int ntheta,
  int spt,
  int sxy,
  const double phi[],
  const double theta[],
  double x[],
  double y[],
  int stat[])

{
  const double tol = 1.0e-13;

  // Initialize.
  if (prj == 0x0) return PRJERR_NULL_POINTER;

  int status;
  if (abs(prj->flag) != MOL) {
    if ((status = molset(prj))) return status;
  }

  int mphi, mtheta;
  if (ntheta > 0) {
    mphi   = nphi;
    mtheta = ntheta;
  } else {
    mphi   = 1;
    mtheta = 1;
    ntheta = nphi;
  }


  // Do phi dependence.
  const double *phip = phi;
  int rowoff = 0;
  int rowlen = nphi*sxy;
  for (int iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    double xi = prj->w[1]*(*phip);

    double *xp = x + rowoff;
    for (int itheta = 0; itheta < mtheta; itheta++) {
      *xp = xi;
      xp += rowlen;
    }
  }


  // Do theta dependence.
  const double *thetap = theta;
  double *xp = x;
  double *yp = y;
  int *statp = stat;
  for (int itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    double xi, eta;

    if (fabs(*thetap) == 90.0) {
      xi  = 0.0;
      eta = copysign(prj->w[0], *thetap);

    } else if (*thetap == 0.0) {
      xi  = 1.0;
      eta = 0.0;

    } else {
      double u  = PI*sind(*thetap);
      double v0 = -PI;
      double v1 =  PI;
      double v  = u;
      for (int k = 0; k < 100; k++) {
        double resid = (v - u) + sin(v);
        if (resid < 0.0) {
          if (resid > -tol) break;
          v0 = v;
        } else {
          if (resid < tol) break;
          v1 = v;
        }
        v = (v0 + v1)/2.0;
      }

      double gamma = v/2.0;
      xi  = cos(gamma);
      eta = prj->w[0]*sin(gamma);
    }

    eta -= prj->y0;
    for (int iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
      *xp = xi*(*xp) - prj->x0;
      *yp = eta;
      *statp = 0;
    }
  }

  return 0;
}

/*============================================================================
*   AIT: Hammer-Aitoff projection.
*
*   Given and/or returned:
*      prj->r0      Reset to 180/pi if 0.
*      prj->phi0    Reset to 0.0 if undefined.
*      prj->theta0  Reset to 0.0 if undefined.
*
*   Returned:
*      prj->flag     AIT
*      prj->code    "AIT"
*      prj->x0      Fiducial offset in x.
*      prj->y0      Fiducial offset in y.
*      prj->w[0]    2*r0**2
*      prj->w[1]    1/(2*r0)**2
*      prj->w[2]    1/(4*r0)**2
*      prj->w[3]    1/(2*r0)
*      prj->prjx2s  Pointer to aitx2s().
*      prj->prjs2x  Pointer to aits2x().
*===========================================================================*/

int aitset(struct prjprm *prj)

{
  if (prj == 0x0) return PRJERR_NULL_POINTER;
  if (prj->flag == -AIT) return 0;

  strncpy(prj->code, "AIT", 4);

  if (prj->r0 == 0.0) prj->r0 = R2D;

  strncpy(prj->name, "Hammer-Aitoff", 40);
  prj->category  = CONVENTIONAL;
  prj->pvrange   = 0;
  prj->simplezen = 0;
  prj->equiareal = 1;
  prj->conformal = 0;
  prj->global    = 1;
  prj->divergent = 0;

  prj->w[0] = 2.0*prj->r0*prj->r0;
  prj->w[1] = 1.0/(2.0*prj->w[0]);
  prj->w[2] = prj->w[1]/4.0;
  prj->w[3] = 1.0/(2.0*prj->r0);

  prj->prjx2s = aitx2s;
  prj->prjs2x = aits2x;

  prj->flag = (prj->flag == 1) ? -AIT : AIT;

  return prjoff(prj, 0.0, 0.0);
}

//----------------------------------------------------------------------------

int aitx2s(
  struct prjprm *prj,
  int nx,
  int ny,
  int sxy,
  int spt,
  const double x[],
  const double y[],
  double phi[],
  double theta[],
  int stat[])

{
  const double tol = 1.0e-13;

  // Initialize.
  if (prj == 0x0) return PRJERR_NULL_POINTER;

  int status;
  if (abs(prj->flag) != AIT) {
    if ((status = aitset(prj))) return status;
  }

  int mx, my;
  if (ny > 0) {
    mx = nx;
    my = ny;
  } else {
    mx = 1;
    my = 1;
    ny = nx;
  }

  status = 0;


  // Do x dependence.
  const double *xp = x;
  int rowoff = 0;
  int rowlen = nx*spt;
  for (int ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    double xj = *xp + prj->x0;
    double s  = 1.0 - xj*xj*prj->w[2];
    double t  = xj*prj->w[3];

    double *phip   = phi   + rowoff;
    double *thetap = theta + rowoff;
    for (int iy = 0; iy < my; iy++) {
      *phip   = s;
      *thetap = t;
      phip   += rowlen;
      thetap += rowlen;
    }
  }


  // Do y dependence.
  const double *yp = y;
  double *phip   = phi;
  double *thetap = theta;
  int    *statp  = stat;
  for (int iy = 0; iy < ny; iy++, yp += sxy) {
    double yj  = *yp + prj->y0;
    double yj2 = yj*yj*prj->w[1];

    for (int ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
      double s = *phip - yj2;

      int istat = 0;
      if (s < 0.5) {
        if (s < 0.5-tol) {
          istat = 1;
          if (!status) status = PRJERR_BAD_PIX_SET("aitx2s");
        }

        s = 0.5;
      }

      double z = sqrt(s);
      double x0 = 2.0*z*z - 1.0;
      double y0 = z*(*thetap);
      if (x0 == 0.0 && y0 == 0.0) {
        *phip = 0.0;
      } else {
        *phip = 2.0*atan2d(y0, x0);
      }

      double t = z*yj/prj->r0;
      if (fabs(t) > 1.0) {
        if (fabs(t) > 1.0+tol) {
          istat = 1;
          if (!status) status = PRJERR_BAD_PIX_SET("aitx2s");
        }
        t = copysign(90.0, t);

      } else {
        t = asind(t);
      }

      *thetap = t;
      *statp  = istat;
    }
  }


  // Do bounds checking on the native coordinates.
  if (prj->bounds&4 && prjbchk(1.0e-13, nx, my, spt, phi, theta, stat)) {
    if (!status) status = PRJERR_BAD_PIX_SET("aitx2s");
  }

  return status;
}

//----------------------------------------------------------------------------

int aits2x(
  struct prjprm *prj,
  int nphi,
  int ntheta,
  int spt,
  int sxy,
  const double phi[],
  const double theta[],
  double x[],
  double y[],
  int stat[])

{
  // Initialize.
  if (prj == 0x0) return PRJERR_NULL_POINTER;

  int status;
  if (abs(prj->flag) != AIT) {
    if ((status = aitset(prj))) return status;
  }

  int mphi, mtheta;
  if (ntheta > 0) {
    mphi   = nphi;
    mtheta = ntheta;
  } else {
    mphi   = 1;
    mtheta = 1;
    ntheta = nphi;
  }


  // Do phi dependence.
  const double *phip = phi;
  int rowoff = 0;
  int rowlen = nphi*sxy;
  for (int iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    double w = (*phip)/2.0;
    double sinphi, cosphi;
    sincosd(w, &sinphi, &cosphi);

    double *xp = x + rowoff;
    double *yp = y + rowoff;
    for (int itheta = 0; itheta < mtheta; itheta++) {
      *xp = sinphi;
      *yp = cosphi;
      xp += rowlen;
      yp += rowlen;
    }
  }


  // Do theta dependence.
  const double *thetap = theta;
  double *xp = x;
  double *yp = y;
  int *statp = stat;
  for (int itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    double sinthe, costhe;
    sincosd(*thetap, &sinthe, &costhe);

    for (int iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
      double w = sqrt(prj->w[0]/(1.0 + costhe*(*yp)));
      *xp = 2.0*w*costhe*(*xp) - prj->x0;
      *yp = w*sinthe - prj->y0;
      *statp = 0;
    }
  }

  return 0;
}

/*============================================================================
*   COP: conic perspective projection.
*
*   Given:
*      prj->pv[1]   sigma = (theta2+theta1)/2
*      prj->pv[2]   delta = (theta2-theta1)/2, where theta1 and theta2 are the
*                   latitudes of the standard parallels, in degrees.
*
*   Given and/or returned:
*      prj->r0      Reset to 180/pi if 0.
*      prj->phi0    Reset to sigma if undefined.
*      prj->theta0  Reset to sigma if undefined.
*
*   Returned:
*      prj->flag     COP
*      prj->code    "COP"
*      prj->x0      Fiducial offset in x.
*      prj->y0      Fiducial offset in y.
*      prj->w[0]    C  = sin(sigma)
*      prj->w[1]    1/C
*      prj->w[2]    Y0 = r0*cos(delta)*cot(sigma)
*      prj->w[3]    r0*cos(delta)
*      prj->w[4]    1/(r0*cos(delta)
*      prj->w[5]    cot(sigma)
*      prj->prjx2s  Pointer to copx2s().
*      prj->prjs2x  Pointer to cops2x().
*===========================================================================*/

int copset(struct prjprm *prj)

{
  if (prj == 0x0) return PRJERR_NULL_POINTER;
  if (prj->flag == -COP) return 0;

  strncpy(prj->code, "COP", 4);

  if (undefined(prj->pv[1])) {
    return PRJERR_BAD_PARAM_SET("copset");
  }
  if (undefined(prj->pv[2])) prj->pv[2] = 0.0;
  if (prj->r0 == 0.0) prj->r0 = R2D;

  strncpy(prj->name, "conic perspective", 40);
  prj->category  = CONIC;
  prj->pvrange   = 102;
  prj->simplezen = 0;
  prj->equiareal = 0;
  prj->conformal = 0;
  prj->global    = 0;
  prj->divergent = 1;

  prj->w[0] = sind(prj->pv[1]);
  if (prj->w[0] == 0.0) {
    return PRJERR_BAD_PARAM_SET("copset");
  }

  prj->w[1] = 1.0/prj->w[0];

  prj->w[3] = prj->r0*cosd(prj->pv[2]);
  if (prj->w[3] == 0.0) {
    return PRJERR_BAD_PARAM_SET("copset");
  }

  prj->w[4] = 1.0/prj->w[3];
  prj->w[5] = 1.0/tand(prj->pv[1]);

  prj->w[2] = prj->w[3]*prj->w[5];

  prj->prjx2s = copx2s;
  prj->prjs2x = cops2x;

  prj->flag = (prj->flag == 1) ? -COP : COP;

  return prjoff(prj, 0.0, prj->pv[1]);
}

//----------------------------------------------------------------------------

int copx2s(
  struct prjprm *prj,
  int nx,
  int ny,
  int sxy,
  int spt,
  const double x[],
  const double y[],
  double phi[],
  double theta[],
  int stat[])

{
  // Initialize.
  if (prj == 0x0) return PRJERR_NULL_POINTER;

  int status;
  if (abs(prj->flag) != COP) {
    if ((status = copset(prj))) return status;
  }

  int mx, my;
  if (ny > 0) {
    mx = nx;
    my = ny;
  } else {
    mx = 1;
    my = 1;
    ny = nx;
  }

  status = 0;


  // Do x dependence.
  const double *xp = x;
  int rowoff = 0;
  int rowlen = nx*spt;
  for (int ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    double xj = *xp + prj->x0;

    double *phip = phi + rowoff;
    for (int iy = 0; iy < my; iy++) {
      *phip = xj;
      phip += rowlen;
    }
  }


  // Do y dependence.
  const double *yp = y;
  double *phip   = phi;
  double *thetap = theta;
  int    *statp  = stat;
  for (int iy = 0; iy < ny; iy++, yp += sxy) {
    double dy  = prj->w[2] - (*yp + prj->y0);
    double dy2 = dy*dy;

    for (int ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
      double xj = *phip;

      double r = sqrt(xj*xj + dy2);
      if (prj->pv[1] < 0.0) r = -r;

      double alpha;
      if (r == 0.0) {
        alpha = 0.0;
      } else {
        alpha = atan2d(xj/r, dy/r);
      }

      *phip = alpha*prj->w[1];
      *thetap = prj->pv[1] + atand(prj->w[5] - r*prj->w[4]);
      *statp  = 0;
    }
  }


  // Do bounds checking on the native coordinates.
  if (prj->bounds&4 && prjbchk(1.0e-13, nx, my, spt, phi, theta, stat)) {
    if (!status) status = PRJERR_BAD_PIX_SET("copx2s");
  }

  return status;
}

//----------------------------------------------------------------------------

int cops2x(
  struct prjprm *prj,
  int nphi,
  int ntheta,
  int spt,
  int sxy,
  const double phi[],
  const double theta[],
  double x[],
  double y[],
  int stat[])

{
  // Initialize.
  if (prj == 0x0) return PRJERR_NULL_POINTER;

  int status;
  if (abs(prj->flag) != COP) {
    if ((status = copset(prj))) return status;
  }

  int mphi, mtheta;
  if (ntheta > 0) {
    mphi   = nphi;
    mtheta = ntheta;
  } else {
    mphi   = 1;
    mtheta = 1;
    ntheta = nphi;
  }

  status = 0;


  // Do phi dependence.
  const double *phip = phi;
  int rowoff = 0;
  int rowlen = nphi*sxy;
  for (int iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    double alpha = prj->w[0]*(*phip);
    double sinalpha, cosalpha;
    sincosd(alpha, &sinalpha, &cosalpha);

    double *xp = x + rowoff;
    double *yp = y + rowoff;
    for (int itheta = 0; itheta < mtheta; itheta++) {
      *xp = sinalpha;
      *yp = cosalpha;
      xp += rowlen;
      yp += rowlen;
    }
  }


  // Do theta dependence.
  const double *thetap = theta;
  double *xp = x;
  double *yp = y;
  int *statp = stat;
  double y0 = prj->y0 - prj->w[2];
  for (int itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    double t = *thetap - prj->pv[1];
    double s = cosd(t);

    int istat = 0;
    double r;
    if (s == 0.0) {
      // Latitude of divergence.
      r = 0.0;
      istat = 1;
      if (!status) status = PRJERR_BAD_WORLD_SET("cops2x");

    } else if (fabs(*thetap) == 90.0) {
      // Return an exact value at the poles.
      r = 0.0;

      // Bounds checking.
      if (prj->bounds&1) {
        if ((*thetap < 0.0) != (prj->pv[1] < 0.0)) {
          istat = 1;
          if (!status) status = PRJERR_BAD_WORLD_SET("cops2x");
        }
      }

    } else {
      r = prj->w[2] - prj->w[3]*sind(t)/s;

      // Bounds checking.
      if (prj->bounds&1) {
        if (r*prj->w[0] < 0.0) {
          istat = 1;
          if (!status) status = PRJERR_BAD_WORLD_SET("cops2x");
        }
      }
    }

    for (int iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
      *xp =  r*(*xp) - prj->x0;
      *yp = -r*(*yp) - y0;
      *statp = istat;
    }
  }

  return status;
}

/*============================================================================
*   COE: conic equal area projection.
*
*   Given:
*      prj->pv[1]   sigma = (theta2+theta1)/2
*      prj->pv[2]   delta = (theta2-theta1)/2, where theta1 and theta2 are the
*                   latitudes of the standard parallels, in degrees.
*
*   Given and/or returned:
*      prj->r0      Reset to 180/pi if 0.
*      prj->phi0    Reset to sigma if undefined.
*      prj->theta0  Reset to sigma if undefined.
*
*   Returned:
*      prj->flag     COE
*      prj->code    "COE"
*      prj->x0      Fiducial offset in x.
*      prj->y0      Fiducial offset in y.
*      prj->w[0]    C = (sin(theta1) + sin(theta2))/2
*      prj->w[1]    1/C
*      prj->w[2]    Y0 = chi*sqrt(psi - 2C*sind(sigma))
*      prj->w[3]    chi = r0/C
*      prj->w[4]    psi = 1 + sin(theta1)*sin(theta2)
*      prj->w[5]    2C
*      prj->w[6]    (1 + sin(theta1)*sin(theta2))*(r0/C)**2
*      prj->w[7]    C/(2*r0**2)
*      prj->w[8]    chi*sqrt(psi + 2C)
*      prj->prjx2s  Pointer to coex2s().
*      prj->prjs2x  Pointer to coes2x().
*===========================================================================*/

int coeset(struct prjprm *prj)

{
  if (prj == 0x0) return PRJERR_NULL_POINTER;
  if (prj->flag == -COE) return 0;

  strncpy(prj->code, "COE", 4);

  if (undefined(prj->pv[1])) {
    return PRJERR_BAD_PARAM_SET("coeset");
  }
  if (undefined(prj->pv[2])) prj->pv[2] = 0.0;
  if (prj->r0 == 0.0) prj->r0 = R2D;

  strncpy(prj->name, "conic equal area", 40);
  prj->category  = CONIC;
  prj->pvrange   = 102;
  prj->simplezen = 0;
  prj->equiareal = 1;
  prj->conformal = 0;
  prj->global    = 1;
  prj->divergent = 0;

  double theta1 = prj->pv[1] - prj->pv[2];
  double theta2 = prj->pv[1] + prj->pv[2];

  prj->w[0] = (sind(theta1) + sind(theta2))/2.0;
  if (prj->w[0] == 0.0) {
    return PRJERR_BAD_PARAM_SET("coeset");
  }

  prj->w[1] = 1.0/prj->w[0];

  prj->w[3] = prj->r0/prj->w[0];
  prj->w[4] = 1.0 + sind(theta1)*sind(theta2);
  prj->w[5] = 2.0*prj->w[0];
  prj->w[6] = prj->w[3]*prj->w[3]*prj->w[4];
  prj->w[7] = 1.0/(2.0*prj->r0*prj->w[3]);
  prj->w[8] = prj->w[3]*sqrt(prj->w[4] + prj->w[5]);

  prj->w[2] = prj->w[3]*sqrt(prj->w[4] - prj->w[5]*sind(prj->pv[1]));

  prj->prjx2s = coex2s;
  prj->prjs2x = coes2x;

  prj->flag = (prj->flag == 1) ? -COE : COE;

  return prjoff(prj, 0.0, prj->pv[1]);
}

//----------------------------------------------------------------------------

int coex2s(
  struct prjprm *prj,
  int nx,
  int ny,
  int sxy,
  int spt,
  const double x[],
  const double y[],
  double phi[],
  double theta[],
  int stat[])

{
  const double tol = 1.0e-12;

  // Initialize.
  if (prj == 0x0) return PRJERR_NULL_POINTER;

  int status;
  if (abs(prj->flag) != COE) {
    if ((status = coeset(prj))) return status;
  }

  int mx, my;
  if (ny > 0) {
    mx = nx;
    my = ny;
  } else {
    mx = 1;
    my = 1;
    ny = nx;
  }

  status = 0;


  // Do x dependence.
  const double *xp = x;
  int rowoff = 0;
  int rowlen = nx*spt;
  for (int ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    double xj = *xp + prj->x0;

    double *phip = phi + rowoff;
    for (int iy = 0; iy < my; iy++) {
      *phip = xj;
      phip += rowlen;
    }
  }


  // Do y dependence.
  const double *yp = y;
  double *phip   = phi;
  double *thetap = theta;
  int    *statp  = stat;
  for (int iy = 0; iy < ny; iy++, yp += sxy) {
    double dy  = prj->w[2] - (*yp + prj->y0);
    double dy2 = dy*dy;

    for (int ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
      double xj = *phip;

      double r = sqrt(xj*xj + dy2);
      if (prj->pv[1] < 0.0) r = -r;

      double alpha;
      if (r == 0.0) {
        alpha = 0.0;
      } else {
        alpha = atan2d(xj/r, dy/r);
      }

      int istat = 0;
      double t;
      if (fabs(r - prj->w[8]) < tol) {
        t = -90.0;
      } else {
        double w = (prj->w[6] - r*r)*prj->w[7];
        if (fabs(w) > 1.0) {
          if (fabs(w-1.0) < tol) {
            t = 90.0;
          } else if (fabs(w+1.0) < tol) {
            t = -90.0;
          } else {
            t = 0.0;
            istat = 1;
            if (!status) status = PRJERR_BAD_PIX_SET("coex2s");
          }
        } else {
          t = asind(w);
        }
      }

      *phip = alpha*prj->w[1];
      *thetap = t;
      *statp  = istat;
    }
  }


  // Do bounds checking on the native coordinates.
  if (prj->bounds&4 && prjbchk(1.0e-13, nx, my, spt, phi, theta, stat)) {
    if (!status) status = PRJERR_BAD_PIX_SET("coex2s");
  }

  return status;
}

//----------------------------------------------------------------------------

int coes2x(
  struct prjprm *prj,
  int nphi,
  int ntheta,
  int spt,
  int sxy,
  const double phi[],
  const double theta[],
  double x[],
  double y[],
  int stat[])

{
  // Initialize.
  if (prj == 0x0) return PRJERR_NULL_POINTER;

  int status;
  if (abs(prj->flag) != COE) {
    if ((status = coeset(prj))) return status;
  }

  int mphi, mtheta;
  if (ntheta > 0) {
    mphi   = nphi;
    mtheta = ntheta;
  } else {
    mphi   = 1;
    mtheta = 1;
    ntheta = nphi;
  }


  // Do phi dependence.
  const double *phip = phi;
  int rowoff = 0;
  int rowlen = nphi*sxy;
  for (int iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    double alpha = prj->w[0]*(*phip);
    double sinalpha, cosalpha;
    sincosd(alpha, &sinalpha, &cosalpha);

    double *xp = x + rowoff;
    double *yp = y + rowoff;
    for (int itheta = 0; itheta < mtheta; itheta++) {
      *xp = sinalpha;
      *yp = cosalpha;
      xp += rowlen;
      yp += rowlen;
    }
  }


  // Do theta dependence.
  const double *thetap = theta;
  double *xp = x;
  double *yp = y;
  int *statp = stat;
  double y0 = prj->y0 - prj->w[2];
  for (int itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    double r;
    if (*thetap == -90.0) {
      r = prj->w[8];
    } else {
      r = prj->w[3]*sqrt(prj->w[4] - prj->w[5]*sind(*thetap));
    }

    for (int iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
      *xp =  r*(*xp) - prj->x0;
      *yp = -r*(*yp) - y0;
      *statp = 0;
    }
  }

  return 0;
}

/*============================================================================
*   COD: conic equidistant projection.
*
*   Given:
*      prj->pv[1]   sigma = (theta2+theta1)/2
*      prj->pv[2]   delta = (theta2-theta1)/2, where theta1 and theta2 are the
*                   latitudes of the standard parallels, in degrees.
*
*   Given and/or returned:
*      prj->r0      Reset to 180/pi if 0.
*      prj->phi0    Reset to sigma if undefined.
*      prj->theta0  Reset to sigma if undefined.
*
*   Returned:
*      prj->flag     COD
*      prj->code    "COD"
*      prj->x0      Fiducial offset in x.
*      prj->y0      Fiducial offset in y.
*      prj->w[0]    C = r0*sin(sigma)*sin(delta)/delta
*      prj->w[1]    1/C
*      prj->w[2]    Y0 = delta*cot(delta)*cot(sigma)
*      prj->w[3]    Y0 + sigma
*      prj->prjx2s  Pointer to codx2s().
*      prj->prjs2x  Pointer to cods2x().
*===========================================================================*/

int codset(struct prjprm *prj)

{
  if (prj == 0x0) return PRJERR_NULL_POINTER;
  if (prj->flag == -COD) return 0;

  strncpy(prj->code, "COD", 4);

  if (undefined(prj->pv[1])) {
    return PRJERR_BAD_PARAM_SET("codset");
  }
  if (undefined(prj->pv[2])) prj->pv[2] = 0.0;
  if (prj->r0 == 0.0) prj->r0 = R2D;

  strncpy(prj->name, "conic equidistant", 40);
  prj->category  = CONIC;
  prj->pvrange   = 102;
  prj->simplezen = 0;
  prj->equiareal = 0;
  prj->conformal = 0;
  prj->global    = 1;
  prj->divergent = 0;

  if (prj->pv[2] == 0.0) {
    prj->w[0] = prj->r0*sind(prj->pv[1])*D2R;
  } else {
    prj->w[0] = prj->r0*sind(prj->pv[1])*sind(prj->pv[2])/prj->pv[2];
  }

  if (prj->w[0] == 0.0) {
    return PRJERR_BAD_PARAM_SET("codset");
  }

  prj->w[1] = 1.0/prj->w[0];
  prj->w[2] = prj->r0*cosd(prj->pv[2])*cosd(prj->pv[1])/prj->w[0];
  prj->w[3] = prj->w[2] + prj->pv[1];

  prj->prjx2s = codx2s;
  prj->prjs2x = cods2x;

  prj->flag = (prj->flag == 1) ? -COD : COD;

  return prjoff(prj, 0.0, prj->pv[1]);
}

//----------------------------------------------------------------------------

int codx2s(
  struct prjprm *prj,
  int nx,
  int ny,
  int sxy,
  int spt,
  const double x[],
  const double y[],
  double phi[],
  double theta[],
  int stat[])

{
  // Initialize.
  if (prj == 0x0) return PRJERR_NULL_POINTER;

  int status;
  if (abs(prj->flag) != COD) {
    if ((status = codset(prj))) return status;
  }

  int mx, my;
  if (ny > 0) {
    mx = nx;
    my = ny;
  } else {
    mx = 1;
    my = 1;
    ny = nx;
  }

  status = 0;


  // Do x dependence.
  const double *xp = x;
  int rowoff = 0;
  int rowlen = nx*spt;
  for (int ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    double xj = *xp + prj->x0;

    double *phip = phi + rowoff;
    for (int iy = 0; iy < my; iy++) {
      *phip = xj;
      phip += rowlen;
    }
  }


  // Do y dependence.
  const double *yp = y;
  double *phip   = phi;
  double *thetap = theta;
  int    *statp  = stat;
  for (int iy = 0; iy < ny; iy++, yp += sxy) {
    double dy  = prj->w[2] - (*yp + prj->y0);
    double dy2 = dy*dy;

    for (int ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
      double xj = *phip;

      double r = sqrt(xj*xj + dy2);
      if (prj->pv[1] < 0.0) r = -r;

      double alpha;
      if (r == 0.0) {
        alpha = 0.0;
      } else {
        alpha = atan2d(xj/r, dy/r);
      }

      *phip = alpha*prj->w[1];
      *thetap = prj->w[3] - r;
      *statp  = 0;
    }
  }


  // Do bounds checking on the native coordinates.
  if (prj->bounds&4 && prjbchk(1.0e-13, nx, my, spt, phi, theta, stat)) {
    if (!status) status = PRJERR_BAD_PIX_SET("codx2s");
  }

  return status;
}

//----------------------------------------------------------------------------

int cods2x(
  struct prjprm *prj,
  int nphi,
  int ntheta,
  int spt,
  int sxy,
  const double phi[],
  const double theta[],
  double x[],
  double y[],
  int stat[])

{
  // Initialize.
  if (prj == 0x0) return PRJERR_NULL_POINTER;

  int status;
  if (abs(prj->flag) != COD) {
    if ((status = codset(prj))) return status;
  }

  int mphi, mtheta;
  if (ntheta > 0) {
    mphi   = nphi;
    mtheta = ntheta;
  } else {
    mphi   = 1;
    mtheta = 1;
    ntheta = nphi;
  }


  // Do phi dependence.
  const double *phip = phi;
  int rowoff = 0;
  int rowlen = nphi*sxy;
  for (int iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    double alpha = prj->w[0]*(*phip);
    double sinalpha, cosalpha;
    sincosd(alpha, &sinalpha, &cosalpha);

    double *xp = x + rowoff;
    double *yp = y + rowoff;
    for (int itheta = 0; itheta < mtheta; itheta++) {
      *xp = sinalpha;
      *yp = cosalpha;
      xp += rowlen;
      yp += rowlen;
    }
  }


  // Do theta dependence.
  const double *thetap = theta;
  double *xp = x;
  double *yp = y;
  int *statp = stat;
  double y0 = prj->y0 - prj->w[2];
  for (int itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    double r = prj->w[3] - *thetap;

    for (int iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
      *xp =  r*(*xp) - prj->x0;
      *yp = -r*(*yp) - y0;
      *statp = 0;
    }
  }

  return 0;
}

/*============================================================================
*   COO: conic orthomorphic projection.
*
*   Given:
*      prj->pv[1]   sigma = (theta2+theta1)/2
*      prj->pv[2]   delta = (theta2-theta1)/2, where theta1 and theta2 are the
*                   latitudes of the standard parallels, in degrees.
*
*   Given and/or returned:
*      prj->r0      Reset to 180/pi if 0.
*      prj->phi0    Reset to sigma if undefined.
*      prj->theta0  Reset to sigma if undefined.
*
*   Returned:
*      prj->flag     COO
*      prj->code    "COO"
*      prj->x0      Fiducial offset in x.
*      prj->y0      Fiducial offset in y.
*      prj->w[0]    C = ln(cos(theta2)/cos(theta1))/ln(tan(tau2)/tan(tau1))
*                       where tau1 = (90 - theta1)/2
*                             tau2 = (90 - theta2)/2
*      prj->w[1]    1/C
*      prj->w[2]    Y0 = psi*tan((90-sigma)/2)**C
*      prj->w[3]    psi = (r0*cos(theta1)/C)/tan(tau1)**C
*      prj->w[4]    1/psi
*      prj->prjx2s  Pointer to coox2s().
*      prj->prjs2x  Pointer to coos2x().
*===========================================================================*/

int cooset(struct prjprm *prj)

{
  if (prj == 0x0) return PRJERR_NULL_POINTER;
  if (prj->flag == -COO) return 0;

  strncpy(prj->code, "COO", 4);

  if (undefined(prj->pv[1])) {
    return PRJERR_BAD_PARAM_SET("cooset");
  }
  if (undefined(prj->pv[2])) prj->pv[2] = 0.0;
  if (prj->r0 == 0.0) prj->r0 = R2D;

  strncpy(prj->name, "conic orthomorphic", 40);
  prj->category  = CONIC;
  prj->pvrange   = 102;
  prj->simplezen = 0;
  prj->equiareal = 0;
  prj->conformal = 1;
  prj->global    = 0;
  prj->divergent = 1;

  double theta1 = prj->pv[1] - prj->pv[2];
  double theta2 = prj->pv[1] + prj->pv[2];

  double tan1 = tand((90.0 - theta1)/2.0);
  double cos1 = cosd(theta1);

  if (theta1 == theta2) {
    prj->w[0] = sind(theta1);
  } else {
    double tan2 = tand((90.0 - theta2)/2.0);
    double cos2 = cosd(theta2);
    prj->w[0] = log(cos2/cos1)/log(tan2/tan1);
  }
  if (prj->w[0] == 0.0) {
    return PRJERR_BAD_PARAM_SET("cooset");
  }

  prj->w[1] = 1.0/prj->w[0];

  prj->w[3] = prj->r0*(cos1/prj->w[0])/pow(tan1,prj->w[0]);
  if (prj->w[3] == 0.0) {
    return PRJERR_BAD_PARAM_SET("cooset");
  }
  prj->w[2] = prj->w[3]*pow(tand((90.0 - prj->pv[1])/2.0),prj->w[0]);
  prj->w[4] = 1.0/prj->w[3];

  prj->prjx2s = coox2s;
  prj->prjs2x = coos2x;

  prj->flag = (prj->flag == 1) ? -COO : COO;

  return prjoff(prj, 0.0, prj->pv[1]);
}

//----------------------------------------------------------------------------

int coox2s(
  struct prjprm *prj,
  int nx,
  int ny,
  int sxy,
  int spt,
  const double x[],
  const double y[],
  double phi[],
  double theta[],
  int stat[])

{
  // Initialize.
  if (prj == 0x0) return PRJERR_NULL_POINTER;

  int status;
  if (abs(prj->flag) != COO) {
    if ((status = cooset(prj))) return status;
  }

  int mx, my;
  if (ny > 0) {
    mx = nx;
    my = ny;
  } else {
    mx = 1;
    my = 1;
    ny = nx;
  }

  status = 0;


  // Do x dependence.
  const double *xp = x;
  int rowoff = 0;
  int rowlen = nx*spt;
  for (int ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    double xj = *xp + prj->x0;

    double *phip = phi + rowoff;
    for (int iy = 0; iy < my; iy++) {
      *phip = xj;
      phip += rowlen;
    }
  }


  // Do y dependence.
  const double *yp = y;
  double *phip   = phi;
  double *thetap = theta;
  int    *statp  = stat;
  for (int iy = 0; iy < ny; iy++, yp += sxy) {
    double dy  = prj->w[2] - (*yp + prj->y0);
    double dy2 = dy*dy;

    for (int ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
      double xj = *phip;

      double r = sqrt(xj*xj + dy2);
      if (prj->pv[1] < 0.0) r = -r;

      double alpha;
      if (r == 0.0) {
        alpha = 0.0;
      } else {
        alpha = atan2d(xj/r, dy/r);
      }

      int istat = 0;
      double t;
      if (r == 0.0) {
        if (prj->w[0] < 0.0) {
          t = -90.0;
        } else {
          t = 0.0;
          istat = 1;
          if (!status) status = PRJERR_BAD_PIX_SET("coox2s");
        }
      } else {
        t = 90.0 - 2.0*atand(pow(r*prj->w[4],prj->w[1]));
      }

      *phip = alpha*prj->w[1];
      *thetap = t;
      *statp  = istat;
    }
  }


  // Do bounds checking on the native coordinates.
  if (prj->bounds&4 && prjbchk(1.0e-13, nx, my, spt, phi, theta, stat)) {
    if (!status) status = PRJERR_BAD_PIX_SET("coox2s");
  }

  return status;
}

//----------------------------------------------------------------------------

int coos2x(
  struct prjprm *prj,
  int nphi,
  int ntheta,
  int spt,
  int sxy,
  const double phi[],
  const double theta[],
  double x[],
  double y[],
  int stat[])

{
  // Initialize.
  if (prj == 0x0) return PRJERR_NULL_POINTER;

  int status;
  if (abs(prj->flag) != COO) {
    if ((status = cooset(prj))) return status;
  }

  int mphi, mtheta;
  if (ntheta > 0) {
    mphi   = nphi;
    mtheta = ntheta;
  } else {
    mphi   = 1;
    mtheta = 1;
    ntheta = nphi;
  }

  status = 0;


  // Do phi dependence.
  const double *phip = phi;
  int rowoff = 0;
  int rowlen = nphi*sxy;
  for (int iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    double alpha = prj->w[0]*(*phip);
    double sinalpha, cosalpha;
    sincosd(alpha, &sinalpha, &cosalpha);

    double *xp = x + rowoff;
    double *yp = y + rowoff;
    for (int itheta = 0; itheta < mtheta; itheta++) {
      *xp = sinalpha;
      *yp = cosalpha;
      xp += rowlen;
      yp += rowlen;
    }
  }


  // Do theta dependence.
  const double *thetap = theta;
  double *xp = x;
  double *yp = y;
  int *statp = stat;
  double y0 = prj->y0 - prj->w[2];
  for (int itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    int istat = 0;

    double r;
    if (*thetap == -90.0) {
      r = 0.0;
      if (prj->w[0] >= 0.0) {
        istat = 1;
        if (!status) status = PRJERR_BAD_WORLD_SET("coos2x");
      }
    } else {
      r = prj->w[3]*pow(tand((90.0 - *thetap)/2.0),prj->w[0]);
    }

    for (int iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
      *xp =  r*(*xp) - prj->x0;
      *yp = -r*(*yp) - y0;
      *statp = istat;
    }
  }

  return status;
}

/*============================================================================
*   BON: Bonne's projection.
*
*   Given:
*      prj->pv[1]   Bonne conformal latitude, theta1, in degrees.
*
*   Given and/or returned:
*      prj->r0      Reset to 180/pi if 0.
*      prj->phi0    Reset to 0.0 if undefined.
*      prj->theta0  Reset to 0.0 if undefined.
*
*   Returned:
*      prj->flag     BON
*      prj->code    "BON"
*      prj->x0      Fiducial offset in x.
*      prj->y0      Fiducial offset in y.
*      prj->w[1]    r0*pi/180
*      prj->w[2]    Y0 = r0*(cot(theta1) + theta1*pi/180)
*      prj->prjx2s  Pointer to bonx2s().
*      prj->prjs2x  Pointer to bons2x().
*===========================================================================*/

int bonset(struct prjprm *prj)

{
  if (prj == 0x0) return PRJERR_NULL_POINTER;
  if (prj->flag == -BON) return 0;

  strncpy(prj->code, "BON", 4);

  if (undefined(prj->pv[1])) {
    return PRJERR_BAD_PARAM_SET("bonset");
  }

  if (prj->pv[1] == 0.0) {
    // Sanson-Flamsteed.
    return sflset(prj);
  }

  strncpy(prj->name, "Bonne's", 40);
  prj->category  = POLYCONIC;
  prj->pvrange   = 101;
  prj->simplezen = 0;
  prj->equiareal = 1;
  prj->conformal = 0;
  prj->global    = 1;
  prj->divergent = 0;

  if (prj->r0 == 0.0) {
    prj->r0 = R2D;
    prj->w[1] = 1.0;
    prj->w[2] = prj->r0*cosd(prj->pv[1])/sind(prj->pv[1]) + prj->pv[1];
  } else {
    prj->w[1] = prj->r0*D2R;
    prj->w[2] = prj->r0*(cosd(prj->pv[1])/sind(prj->pv[1]) + prj->pv[1]*D2R);
  }

  prj->prjx2s = bonx2s;
  prj->prjs2x = bons2x;

  prj->flag = (prj->flag == 1) ? -BON : BON;

  return prjoff(prj, 0.0, 0.0);
}

//----------------------------------------------------------------------------

int bonx2s(
  struct prjprm *prj,
  int nx,
  int ny,
  int sxy,
  int spt,
  const double x[],
  const double y[],
  double phi[],
  double theta[],
  int stat[])

{
  // Initialize.
  if (prj == 0x0) return PRJERR_NULL_POINTER;
  if (prj->pv[1] == 0.0) {
    // Sanson-Flamsteed.
    return sflx2s(prj, nx, ny, sxy, spt, x, y, phi, theta, stat);
  }

  int status;
  if (abs(prj->flag) != BON) {
    if ((status = bonset(prj))) return status;
  }

  int mx, my;
  if (ny > 0) {
    mx = nx;
    my = ny;
  } else {
    mx = 1;
    my = 1;
    ny = nx;
  }

  status = 0;


  // Do x dependence.
  const double *xp = x;
  int rowoff = 0;
  int rowlen = nx*spt;
  for (int ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    double xj = *xp + prj->x0;

    double *phip = phi + rowoff;
    for (int iy = 0; iy < my; iy++) {
      *phip = xj;
      phip += rowlen;
    }
  }


  // Do y dependence.
  const double *yp = y;
  double *phip   = phi;
  double *thetap = theta;
  int    *statp  = stat;
  for (int iy = 0; iy < ny; iy++, yp += sxy) {
    double dy  = prj->w[2] - (*yp + prj->y0);
    double dy2 = dy*dy;

    for (int ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
      double xj = *phip;

      double r = sqrt(xj*xj + dy2);
      if (prj->pv[1] < 0.0) r = -r;

      double alpha;
      if (r == 0.0) {
        alpha = 0.0;
      } else {
        alpha = atan2d(xj/r, dy/r);
      }

      double s;
      double t = (prj->w[2] - r)/prj->w[1];
      double costhe = cosd(t);
      if (costhe == 0.0) {
        s = 0.0;
      } else {
        s = alpha*(r/prj->r0)/costhe;
      }

      *phip = s;
      *thetap = t;
      *statp  = 0;
    }
  }


  // Do bounds checking on the native coordinates.
  if (prj->bounds&4 && prjbchk(1.0e-11, nx, my, spt, phi, theta, stat)) {
    if (!status) status = PRJERR_BAD_PIX_SET("bonx2s");
  }

  return status;
}

//----------------------------------------------------------------------------

int bons2x(
  struct prjprm *prj,
  int nphi,
  int ntheta,
  int spt,
  int sxy,
  const double phi[],
  const double theta[],
  double x[],
  double y[],
  int stat[])

{
  // Initialize.
  if (prj == 0x0) return PRJERR_NULL_POINTER;
  if (prj->pv[1] == 0.0) {
    // Sanson-Flamsteed.
    return sfls2x(prj, nphi, ntheta, spt, sxy, phi, theta, x, y, stat);
  }

  int status;
  if (abs(prj->flag) != BON) {
    if ((status = bonset(prj))) return status;
  }

  int mphi, mtheta;
  if (ntheta > 0) {
    mphi   = nphi;
    mtheta = ntheta;
  } else {
    mphi   = 1;
    mtheta = 1;
    ntheta = nphi;
  }


  // Do phi dependence.
  const double *phip = phi;
  int rowoff = 0;
  int rowlen = nphi*sxy;
  for (int iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    double s = prj->r0*(*phip);

    double *xp = x + rowoff;
    for (int itheta = 0; itheta < mtheta; itheta++) {
      *xp = s;
      xp += rowlen;
    }
  }


  // Do theta dependence.
  const double *thetap = theta;
  double *xp = x;
  double *yp = y;
  int *statp = stat;
  double y0 = prj->y0 - prj->w[2];
  for (int itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    double r = prj->w[2] - prj->w[1]*(*thetap);
    double s = cosd(*thetap)/r;

    for (int iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
      double alpha = s*(*xp);
      double sinalpha, cosalpha;
      sincosd(alpha, &sinalpha, &cosalpha);
      *xp =  r*sinalpha - prj->x0;
      *yp = -r*cosalpha - y0;
      *statp = 0;
    }
  }

  return 0;
}

/*============================================================================
*   PCO: polyconic projection.
*
*   Given and/or returned:
*      prj->r0      Reset to 180/pi if 0.
*      prj->phi0    Reset to 0.0 if undefined.
*      prj->theta0  Reset to 0.0 if undefined.
*
*   Returned:
*      prj->flag     PCO
*      prj->code    "PCO"
*      prj->x0      Fiducial offset in x.
*      prj->y0      Fiducial offset in y.
*      prj->w[0]    r0*(pi/180)
*      prj->w[1]    (180/pi)/r0
*      prj->w[2]    2*r0
*      prj->w[3]    (pi/180)/(2*r0)
*      prj->prjx2s  Pointer to pcox2s().
*      prj->prjs2x  Pointer to pcos2x().
*===========================================================================*/

int pcoset(struct prjprm *prj)

{
  if (prj == 0x0) return PRJERR_NULL_POINTER;
  if (prj->flag == -PCO) return 0;

  strncpy(prj->code, "PCO", 4);

  strncpy(prj->name, "polyconic", 40);
  prj->category  = POLYCONIC;
  prj->pvrange   = 0;
  prj->simplezen = 0;
  prj->equiareal = 0;
  prj->conformal = 0;
  prj->global    = 1;
  prj->divergent = 0;

  if (prj->r0 == 0.0) {
    prj->r0 = R2D;
    prj->w[0] = 1.0;
    prj->w[1] = 1.0;
    prj->w[2] = 360.0/PI;
  } else {
    prj->w[0] = prj->r0*D2R;
    prj->w[1] = 1.0/prj->w[0];
    prj->w[2] = 2.0*prj->r0;
  }
  prj->w[3] = D2R/prj->w[2];

  prj->prjx2s = pcox2s;
  prj->prjs2x = pcos2x;

  prj->flag = (prj->flag == 1) ? -PCO : PCO;

  return prjoff(prj, 0.0, 0.0);
}

//----------------------------------------------------------------------------

int pcox2s(
  struct prjprm *prj,
  int nx,
  int ny,
  int sxy,
  int spt,
  const double x[],
  const double y[],
  double phi[],
  double theta[],
  int stat[])

{
  const double tol = 1.0e-12;

  // Initialize.
  if (prj == 0x0) return PRJERR_NULL_POINTER;

  int status;
  if (abs(prj->flag) != PCO) {
    if ((status = pcoset(prj))) return status;
  }

  int mx, my;
  if (ny > 0) {
    mx = nx;
    my = ny;
  } else {
    mx = 1;
    my = 1;
    ny = nx;
  }

  status = 0;


  // Do x dependence.
  const double *xp = x;
  int rowoff = 0;
  int rowlen = nx*spt;
  for (int ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    double xj = *xp + prj->x0;

    double *phip = phi + rowoff;
    for (int iy = 0; iy < my; iy++) {
      *phip = xj;
      phip += rowlen;
    }
  }


  // Do y dependence.
  const double *yp = y;
  double *phip   = phi;
  double *thetap = theta;
  int    *statp  = stat;
  for (int iy = 0; iy < ny; iy++, yp += sxy) {
    double yj = *yp + prj->y0;
    double w  = fabs(yj*prj->w[1]);

    for (int ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
      double xj = *phip;

      if (w < tol) {
        *phip = xj*prj->w[1];
        *thetap = 0.0;

      } else if (fabs(w-90.0) < tol) {
        *phip = 0.0;
        *thetap = copysign(90.0, yj);

      } else {
        double the, ymthe, tanthe;
        if (w < 1.0e-4) {
          // To avoid cot(theta) blowing up near theta == 0.
          the    = yj / (prj->w[0] + prj->w[3]*xj*xj);
          ymthe  = yj - prj->w[0]*the;
          tanthe = tand(the);

        } else {
          // Iterative solution using weighted division of the interval.
          double thepos = yj / prj->w[0];
          double theneg = 0.0;

          // Setting fneg = -fpos halves the interval in the first iter.
          double xx = xj*xj;
          double fpos =  xx;
          double fneg = -xx;

          for (int k = 0; k < 64; k++) {
            // Weighted division of the interval.
            double lambda = fpos/(fpos-fneg);
            if (lambda < 0.1) {
              lambda = 0.1;
            } else if (lambda > 0.9) {
              lambda = 0.9;
            }
            the = thepos - lambda*(thepos-theneg);

            // Compute the residue.
            ymthe  = yj - prj->w[0]*the;
            tanthe = tand(the);
            double f = xx + ymthe*(ymthe - prj->w[2]/tanthe);

            // Check for convergence.
            if (fabs(f) < tol) break;
            if (fabs(thepos-theneg) < tol) break;

            // Redefine the interval.
            if (f > 0.0) {
              thepos = the;
              fpos = f;
            } else {
              theneg = the;
              fneg = f;
            }
          }
        }

        double x1 = prj->r0 - ymthe*tanthe;
        double y1 = xj*tanthe;
        if (x1 == 0.0 && y1 == 0.0) {
          *phip = 0.0;
        } else {
          *phip = atan2d(y1, x1)/sind(the);
        }

        *thetap = the;
      }

      *statp = 0;
    }
  }


  // Do bounds checking on the native coordinates.
  if (prj->bounds&4 && prjbchk(1.0e-12, nx, my, spt, phi, theta, stat)) {
    if (!status) status = PRJERR_BAD_PIX_SET("pcox2s");
  }

  return status;
}

//----------------------------------------------------------------------------

int pcos2x(
  struct prjprm *prj,
  int nphi,
  int ntheta,
  int spt,
  int sxy,
  const double phi[],
  const double theta[],
  double x[],
  double y[],
  int stat[])

{
  // Initialize.
  if (prj == 0x0) return PRJERR_NULL_POINTER;

  int status;
  if (abs(prj->flag) != PCO) {
    if ((status = pcoset(prj))) return status;
  }

  int mphi, mtheta;
  if (ntheta > 0) {
    mphi   = nphi;
    mtheta = ntheta;
  } else {
    mphi   = 1;
    mtheta = 1;
    ntheta = nphi;
  }


  // Do phi dependence.
  const double *phip = phi;
  int rowoff = 0;
  int rowlen = nphi*sxy;
  for (int iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    double *xp = x + rowoff;
    for (int itheta = 0; itheta < mtheta; itheta++) {
      *xp = *phip;
      xp += rowlen;
    }
  }


  // Do theta dependence.
  const double *thetap = theta;
  double *xp = x;
  double *yp = y;
  int *statp = stat;
  for (int itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    if (*thetap == 0.0) {
      for (int iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
        *xp =  prj->w[0]*(*xp) - prj->x0;
        *yp = -prj->y0;
        *statp = 0;
      }

    } else if (fabs(*thetap) < 1.0e-4) {
      // To avoid cot(theta) blowing up near theta == 0.
      for (int iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
        *xp = prj->w[0]*(*xp)*cosd(*thetap) - prj->x0;
        *yp = (prj->w[0] + prj->w[3]*(*xp)*(*xp))*(*thetap) - prj->y0;
        *statp = 0;
      }

    } else {
      double therad = (*thetap)*D2R;
      double sinthe, costhe;
      sincosd(*thetap, &sinthe, &costhe);

      for (int iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
        double sinpsi, cospsi;
        sincosd((*xp)*sinthe, &sinpsi, &cospsi);
        double cotthe = costhe/sinthe;
        *xp = prj->r0*cotthe*sinpsi - prj->x0;
        *yp = prj->r0*(cotthe*(1.0 - cospsi) + therad) - prj->y0;
        *statp = 0;
      }
    }
  }

  return 0;
}

/*============================================================================
*   TSC: tangential spherical cube projection.
*
*   Given and/or returned:
*      prj->r0      Reset to 180/pi if 0.
*      prj->phi0    Reset to 0.0 if undefined.
*      prj->theta0  Reset to 0.0 if undefined.
*
*   Returned:
*      prj->flag     TSC
*      prj->code    "TSC"
*      prj->x0      Fiducial offset in x.
*      prj->y0      Fiducial offset in y.
*      prj->w[0]    r0*(pi/4)
*      prj->w[1]    (4/pi)/r0
*      prj->prjx2s  Pointer to tscx2s().
*      prj->prjs2x  Pointer to tscs2x().
*===========================================================================*/

int tscset(struct prjprm *prj)

{
  if (prj == 0x0) return PRJERR_NULL_POINTER;
  if (prj->flag == -TSC) return 0;

  strncpy(prj->code, "TSC", 4);

  strncpy(prj->name, "tangential spherical cube", 40);
  prj->category  = QUADCUBE;
  prj->pvrange   = 0;
  prj->simplezen = 0;
  prj->equiareal = 0;
  prj->conformal = 0;
  prj->global    = 1;
  prj->divergent = 0;

  if (prj->r0 == 0.0) {
    prj->r0 = R2D;
    prj->w[0] = 45.0;
    prj->w[1] = 1.0/45.0;
  } else {
    prj->w[0] = prj->r0*PI/4.0;
    prj->w[1] = 1.0/prj->w[0];
  }

  prj->prjx2s = tscx2s;
  prj->prjs2x = tscs2x;

  prj->flag = (prj->flag == 1) ? -TSC : TSC;

  return prjoff(prj, 0.0, 0.0);
}

//----------------------------------------------------------------------------

int tscx2s(
  struct prjprm *prj,
  int nx,
  int ny,
  int sxy,
  int spt,
  const double x[],
  const double y[],
  double phi[],
  double theta[],
  int stat[])

{
  // Initialize.
  if (prj == 0x0) return PRJERR_NULL_POINTER;

  int status;
  if (abs(prj->flag) != TSC) {
    if ((status = tscset(prj))) return status;
  }

  int mx, my;
  if (ny > 0) {
    mx = nx;
    my = ny;
  } else {
    mx = 1;
    my = 1;
    ny = nx;
  }

  status = 0;


  // Do x dependence.
  const double *xp = x;
  int rowoff = 0;
  int rowlen = nx*spt;
  for (int ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    double xf = (*xp + prj->x0)*prj->w[1];

    double *phip = phi + rowoff;
    for (int iy = 0; iy < my; iy++) {
      *phip = xf;
      phip += rowlen;
    }
  }


  // Do y dependence.
  const double *yp = y;
  double *phip   = phi;
  double *thetap = theta;
  int    *statp  = stat;
  for (int iy = 0; iy < ny; iy++, yp += sxy) {
    double yf = (*yp + prj->y0)*prj->w[1];

    for (int ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
      double xf = *phip;

      // Bounds checking.
      if (fabs(xf) <= 1.0) {
        if (fabs(yf) > 3.0) {
          *phip = 0.0;
          *thetap = 0.0;
          *statp  = 1;
          if (!status) status = PRJERR_BAD_PIX_SET("tscx2s");
          continue;
        }
      } else {
        if (fabs(xf) > 7.0 || fabs(yf) > 1.0) {
          *phip = 0.0;
          *thetap = 0.0;
          *statp  = 1;
          if (!status) status = PRJERR_BAD_PIX_SET("tscx2s");
          continue;
        }
      }

      // Map negative faces to the other side.
      if (xf < -1.0) xf += 8.0;

      // Determine the face.
      double l, m, n;
      if (xf > 5.0) {
        // face = 4
        xf = xf - 6.0;
        m  = -1.0/sqrt(1.0 + xf*xf + yf*yf);
        l  = -m*xf;
        n  = -m*yf;
      } else if (xf > 3.0) {
        // face = 3
        xf = xf - 4.0;
        l  = -1.0/sqrt(1.0 + xf*xf + yf*yf);
        m  =  l*xf;
        n  = -l*yf;
      } else if (xf > 1.0) {
        // face = 2
        xf = xf - 2.0;
        m  =  1.0/sqrt(1.0 + xf*xf + yf*yf);
        l  = -m*xf;
        n  =  m*yf;
      } else if (yf > 1.0) {
        // face = 0
        yf = yf - 2.0;
        n  = 1.0/sqrt(1.0 + xf*xf + yf*yf);
        l  = -n*yf;
        m  =  n*xf;
      } else if (yf < -1.0) {
        // face = 5
        yf = yf + 2.0;
        n  = -1.0/sqrt(1.0 + xf*xf + yf*yf);
        l  = -n*yf;
        m  = -n*xf;
      } else {
        // face = 1
        l  =  1.0/sqrt(1.0 + xf*xf + yf*yf);
        m  =  l*xf;
        n  =  l*yf;
      }

      if (l == 0.0 && m == 0.0) {
        *phip = 0.0;
      } else {
        *phip = atan2d(m, l);
      }

      *thetap = asind(n);
      *statp  = 0;
    }
  }


  // Do bounds checking on the native coordinates.
  if (prj->bounds&4 && prjbchk(1.0e-13, nx, my, spt, phi, theta, stat)) {
    if (!status) status = PRJERR_BAD_PIX_SET("tscx2s");
  }

  return status;
}

//----------------------------------------------------------------------------

int tscs2x(
  struct prjprm *prj,
  int nphi,
  int ntheta,
  int spt,
  int sxy,
  const double phi[],
  const double theta[],
  double x[],
  double y[],
  int stat[])

{
  const double tol = 1.0e-12;

  // Initialize.
  if (prj == 0x0) return PRJERR_NULL_POINTER;

  int status;
  if (abs(prj->flag) != TSC) {
    if ((status = tscset(prj))) return status;
  }

  int mphi, mtheta;
  if (ntheta > 0) {
    mphi   = nphi;
    mtheta = ntheta;
  } else {
    mphi   = 1;
    mtheta = 1;
    ntheta = nphi;
  }

  status = 0;


  // Do phi dependence.
  const double *phip = phi;
  int rowoff = 0;
  int rowlen = nphi*sxy;
  for (int iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    double sinphi, cosphi;
    sincosd(*phip, &sinphi, &cosphi);

    double *xp = x + rowoff;
    double *yp = y + rowoff;
    for (int itheta = 0; itheta < mtheta; itheta++) {
      *xp = cosphi;
      *yp = sinphi;
      xp += rowlen;
      yp += rowlen;
    }
  }


  // Do theta dependence.
  const double *thetap = theta;
  double *xp = x;
  double *yp = y;
  int *statp = stat;
  for (int itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    double sinthe, costhe;
    sincosd(*thetap, &sinthe, &costhe);

    for (int iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
      double l = costhe*(*xp);
      double m = costhe*(*yp);
      double n = sinthe;

      int face = 0;
      double zeta = n;
      if (l > zeta) {
        face = 1;
        zeta = l;
      }
      if (m > zeta) {
        face = 2;
        zeta = m;
      }
      if (-l > zeta) {
        face = 3;
        zeta = -l;
      }
      if (-m > zeta) {
        face = 4;
        zeta = -m;
      }
      if (-n > zeta) {
        face = 5;
        zeta = -n;
      }

      double xf, yf, x0, y0;
      switch (face) {
      case 1:
        xf =  m/zeta;
        yf =  n/zeta;
        x0 =  0.0;
        y0 =  0.0;
        break;
      case 2:
        xf = -l/zeta;
        yf =  n/zeta;
        x0 =  2.0;
        y0 =  0.0;
        break;
      case 3:
        xf = -m/zeta;
        yf =  n/zeta;
        x0 =  4.0;
        y0 =  0.0;
        break;
      case 4:
        xf =  l/zeta;
        yf =  n/zeta;
        x0 =  6.0;
        y0 =  0.0;
        break;
      case 5:
        xf =  m/zeta;
        yf =  l/zeta;
        x0 =  0.0;
        y0 = -2.0;
        break;
      default:
        // face == 0
        xf =  m/zeta;
        yf = -l/zeta;
        x0 =  0.0;
        y0 =  2.0;
        break;
      }

      int istat = 0;
      if (fabs(xf) > 1.0) {
        if (fabs(xf) > 1.0+tol) {
          istat = 1;
          if (!status) status = PRJERR_BAD_WORLD_SET("tscs2x");
        }
        xf = copysign(1.0, xf);
      }
      if (fabs(yf) > 1.0) {
        if (fabs(yf) > 1.0+tol) {
          istat = 1;
          if (!status) status = PRJERR_BAD_WORLD_SET("tscs2x");
        }
        yf = copysign(1.0, yf);
      }

      *xp = prj->w[0]*(xf + x0) - prj->x0;
      *yp = prj->w[0]*(yf + y0) - prj->y0;
      *statp = istat;
    }
  }

  return status;
}

/*============================================================================
*   CSC: COBE quadrilateralized spherical cube projection.
*
*   Given and/or returned:
*      prj->r0      Reset to 180/pi if 0.
*      prj->phi0    Reset to 0.0 if undefined.
*      prj->theta0  Reset to 0.0 if undefined.
*
*   Returned:
*      prj->flag     CSC
*      prj->code    "CSC"
*      prj->x0      Fiducial offset in x.
*      prj->y0      Fiducial offset in y.
*      prj->w[0]    r0*(pi/4)
*      prj->w[1]    (4/pi)/r0
*      prj->prjx2s  Pointer to cscx2s().
*      prj->prjs2x  Pointer to cscs2x().
*===========================================================================*/

int cscset(struct prjprm *prj)

{
  if (prj == 0x0) return PRJERR_NULL_POINTER;
  if (prj->flag == -CSC) return 0;

  strncpy(prj->code, "CSC", 4);

  strncpy(prj->name, "COBE quadrilateralized spherical cube", 40);
  prj->category  = QUADCUBE;
  prj->pvrange   = 0;
  prj->simplezen = 0;
  prj->equiareal = 0;
  prj->conformal = 0;
  prj->global    = 1;
  prj->divergent = 0;

  if (prj->r0 == 0.0) {
    prj->r0 = R2D;
    prj->w[0] = 45.0;
    prj->w[1] = 1.0/45.0;
  } else {
    prj->w[0] = prj->r0*PI/4.0;
    prj->w[1] = 1.0/prj->w[0];
  }

  prj->prjx2s = cscx2s;
  prj->prjs2x = cscs2x;

  prj->flag = (prj->flag == 1) ? -CSC : CSC;

  return prjoff(prj, 0.0, 0.0);
}

//----------------------------------------------------------------------------

int cscx2s(
  struct prjprm *prj,
  int nx,
  int ny,
  int sxy,
  int spt,
  const double x[],
  const double y[],
  double phi[],
  double theta[],
  int stat[])

{
  const float p00 = -0.27292696f;
  const float p10 = -0.07629969f;
  const float p20 = -0.22797056f;
  const float p30 =  0.54852384f;
  const float p40 = -0.62930065f;
  const float p50 =  0.25795794f;
  const float p60 =  0.02584375f;
  const float p01 = -0.02819452f;
  const float p11 = -0.01471565f;
  const float p21 =  0.48051509f;
  const float p31 = -1.74114454f;
  const float p41 =  1.71547508f;
  const float p51 = -0.53022337f;
  const float p02 =  0.27058160f;
  const float p12 = -0.56800938f;
  const float p22 =  0.30803317f;
  const float p32 =  0.98938102f;
  const float p42 = -0.83180469f;
  const float p03 = -0.60441560f;
  const float p13 =  1.50880086f;
  const float p23 = -0.93678576f;
  const float p33 =  0.08693841f;
  const float p04 =  0.93412077f;
  const float p14 = -1.41601920f;
  const float p24 =  0.33887446f;
  const float p05 = -0.63915306f;
  const float p15 =  0.52032238f;
  const float p06 =  0.14381585f;

  // Initialize.
  if (prj == 0x0) return PRJERR_NULL_POINTER;

  int status;
  if (abs(prj->flag) != CSC) {
    if ((status = cscset(prj))) return status;
  }

  int mx, my;
  if (ny > 0) {
    mx = nx;
    my = ny;
  } else {
    mx = 1;
    my = 1;
    ny = nx;
  }

  status = 0;


  // Do x dependence.
  const double *xp = x;
  int rowoff = 0;
  int rowlen = nx*spt;
  for (int ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    float xf = (float)((*xp + prj->x0)*prj->w[1]);

    double *phip = phi + rowoff;
    for (int iy = 0; iy < my; iy++) {
      *phip = xf;
      phip += rowlen;
    }
  }


  // Do y dependence.
  const double *yp = y;
  double *phip   = phi;
  double *thetap = theta;
  int    *statp  = stat;
  for (int iy = 0; iy < ny; iy++, yp += sxy) {
    float yf = (float)((*yp + prj->y0)*prj->w[1]);

    for (int ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
      float xf = (float)(*phip);

      // Bounds checking.
      if (fabs((double)xf) <= 1.0) {
        if (fabs((double)yf) > 3.0) {
          *phip = 0.0;
          *thetap = 0.0;
          *statp  = 1;
          if (!status) status = PRJERR_BAD_PIX_SET("cscx2s");
          continue;
        }
      } else {
        if (fabs((double)xf) > 7.0 || fabs((double)yf) > 1.0) {
          *phip = 0.0;
          *thetap = 0.0;
          *statp  = 1;
          if (!status) status = PRJERR_BAD_PIX_SET("cscx2s");
          continue;
        }
      }

      // Map negative faces to the other side.
      if (xf < -1.0f) xf += 8.0f;

      // Determine the face.
      int face = 0;
      if (xf > 5.0f) {
        face = 4;
        xf = xf - 6.0f;
      } else if (xf > 3.0f) {
        face = 3;
        xf = xf - 4.0f;
      } else if (xf > 1.0f) {
        face = 2;
        xf = xf - 2.0f;
      } else if (yf > 1.0f) {
        face = 0;
        yf = yf - 2.0f;
      } else if (yf < -1.0f) {
        face = 5;
        yf = yf + 2.0f;
      } else {
        face = 1;
      }

      float xx  =  xf*xf;
      float yy  =  yf*yf;

      float z0, z1, z2, z3, z4, z5, z6;
      z0 = p00 + xx*(p10 + xx*(p20 + xx*(p30 + xx*(p40 + xx*(p50 +
                 xx*(p60))))));
      z1 = p01 + xx*(p11 + xx*(p21 + xx*(p31 + xx*(p41 + xx*(p51)))));
      z2 = p02 + xx*(p12 + xx*(p22 + xx*(p32 + xx*(p42))));
      z3 = p03 + xx*(p13 + xx*(p23 + xx*(p33)));
      z4 = p04 + xx*(p14 + xx*(p24));
      z5 = p05 + xx*(p15);
      z6 = p06;

      float chi;
      chi = z0 + yy*(z1 + yy*(z2 + yy*(z3 + yy*(z4 + yy*(z5 + yy*z6)))));
      chi = xf + xf*(1.0f - xx)*chi;

      z0 = p00 + yy*(p10 + yy*(p20 + yy*(p30 + yy*(p40 + yy*(p50 +
                 yy*(p60))))));
      z1 = p01 + yy*(p11 + yy*(p21 + yy*(p31 + yy*(p41 + yy*(p51)))));
      z2 = p02 + yy*(p12 + yy*(p22 + yy*(p32 + yy*(p42))));
      z3 = p03 + yy*(p13 + yy*(p23 + yy*(p33)));
      z4 = p04 + yy*(p14 + yy*(p24));
      z5 = p05 + yy*(p15);
      z6 = p06;

      float psi;
      psi = z0 + xx*(z1 + xx*(z2 + xx*(z3 + xx*(z4 + xx*(z5 + xx*z6)))));
      psi = yf + yf*(1.0f - yy)*psi;

      double l, m, n;
      double t = 1.0/sqrt((double)(chi*chi + psi*psi) + 1.0);
      switch (face) {
      case 1:
        l =  t;
        m =  chi*l;
        n =  psi*l;
        break;
      case 2:
        m =  t;
        l = -chi*m;
        n =  psi*m;
        break;
      case 3:
        l = -t;
        m =  chi*l;
        n = -psi*l;
        break;
      case 4:
        m = -t;
        l = -chi*m;
        n = -psi*m;
        break;
      case 5:
        n = -t;
        l = -psi*n;
        m = -chi*n;
        break;
      default:
        // face == 0
        n =  t;
        l = -psi*n;
        m =  chi*n;
        break;
      }

      if (l == 0.0 && m == 0.0) {
        *phip = 0.0;
      } else {
        *phip = atan2d(m, l);
      }

      *thetap = asind(n);
      *statp  = 0;
    }
  }


  // Do bounds checking on the native coordinates.
  if (prj->bounds&4 && prjbchk(1.0e-13, nx, my, spt, phi, theta, stat)) {
    if (!status) status = PRJERR_BAD_PIX_SET("cscx2s");
  }

  return status;
}

//----------------------------------------------------------------------------

int cscs2x(
  struct prjprm *prj,
  int nphi,
  int ntheta,
  int spt,
  int sxy,
  const double phi[],
  const double theta[],
  double x[],
  double y[],
  int stat[])

{
  const double tol = 1.0e-7;

  const float gstar  =  1.37484847732f;
  const float mm     =  0.004869491981f;
  const float gamma  = -0.13161671474f;
  const float omega1 = -0.159596235474f;
  const float d0  =  0.0759196200467f;
  const float d1  = -0.0217762490699f;
  const float c00 =  0.141189631152f;
  const float c10 =  0.0809701286525f;
  const float c01 = -0.281528535557f;
  const float c11 =  0.15384112876f;
  const float c20 = -0.178251207466f;
  const float c02 =  0.106959469314f;


  // Initialize.
  if (prj == 0x0) return PRJERR_NULL_POINTER;

  int status;
  if (abs(prj->flag) != CSC) {
    if ((status = cscset(prj))) return status;
  }

  int mphi, mtheta;
  if (ntheta > 0) {
    mphi   = nphi;
    mtheta = ntheta;
  } else {
    mphi   = 1;
    mtheta = 1;
    ntheta = nphi;
  }

  status = 0;


  // Do phi dependence.
  const double *phip = phi;
  int rowoff = 0;
  int rowlen = nphi*sxy;
  for (int iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    double sinphi, cosphi;
    sincosd(*phip, &sinphi, &cosphi);

    double *xp = x + rowoff;
    double *yp = y + rowoff;
    for (int itheta = 0; itheta < mtheta; itheta++) {
      *xp = cosphi;
      *yp = sinphi;
      xp += rowlen;
      yp += rowlen;
    }
  }


  // Do theta dependence.
  const double *thetap = theta;
  double *xp = x;
  double *yp = y;
  int *statp = stat;
  for (int itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    double sinthe, costhe;
    sincosd(*thetap, &sinthe, &costhe);

    for (int iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
      double l = costhe*(*xp);
      double m = costhe*(*yp);
      double n = sinthe;

      int face = 0;
      double zeta = n;
      if (l > zeta) {
        face = 1;
        zeta = l;
      }
      if (m > zeta) {
        face = 2;
        zeta = m;
      }
      if (-l > zeta) {
        face = 3;
        zeta = -l;
      }
      if (-m > zeta) {
        face = 4;
        zeta = -m;
      }
      if (-n > zeta) {
        face = 5;
        zeta = -n;
      }

      double eta, xi;
      float  x0, y0;
      switch (face) {
      case 1:
        xi  =  m;
        eta =  n;
        x0  =  0.0f;
        y0  =  0.0f;
        break;
      case 2:
        xi  = -l;
        eta =  n;
        x0  =  2.0f;
        y0  =  0.0f;
        break;
      case 3:
        xi  = -m;
        eta =  n;
        x0  =  4.0f;
        y0  =  0.0f;
        break;
      case 4:
        xi  =  l;
        eta =  n;
        x0  =  6.0f;
        y0  =  0.0f;
        break;
      case 5:
        xi  =  m;
        eta =  l;
        x0  =  0.0f;
        y0  = -2.0f;
        break;
      default:
        // face == 0
        xi  =  m;
        eta = -l;
        x0  =  0.0f;
        y0  =  2.0f;
        break;
      }

      float chi = (float)( xi/zeta);
      float psi = (float)(eta/zeta);

      float chi2 = chi*chi;
      float psi2 = psi*psi;
      float chi2co = 1.0f - chi2;
      float psi2co = 1.0f - psi2;

      // Avoid floating underflows.
      float chipsi = (float)fabs((double)(chi*psi));
      float chi4   = (chi2 > 1.0e-16f) ? chi2*chi2 : 0.0f;
      float psi4   = (psi2 > 1.0e-16f) ? psi2*psi2 : 0.0f;
      float chi2psi2 = (chipsi > 1.0e-16f) ? chi2*psi2 : 0.0f;

      float xf, yf;
      xf = chi*(chi2 + chi2co*(gstar + psi2*(gamma*chi2co + mm*chi2 +
                psi2co*(c00 + c10*chi2 + c01*psi2 + c11*chi2psi2 + c20*chi4 +
                c02*psi4)) + chi2*(omega1 - chi2co*(d0 + d1*chi2))));
      yf = psi*(psi2 + psi2co*(gstar + chi2*(gamma*psi2co + mm*psi2 +
                chi2co*(c00 + c10*psi2 + c01*chi2 + c11*chi2psi2 + c20*psi4 +
                c02*chi4)) + psi2*(omega1 - psi2co*(d0 + d1*psi2))));

      int istat = 0;
      if (fabs((double)xf) > 1.0) {
        if (fabs((double)xf) > 1.0+tol) {
          istat = 1;
          if (!status) status = PRJERR_BAD_WORLD_SET("cscs2x");
        }
        xf = (float)copysign(1.0, (double)xf);
      }
      if (fabs((double)yf) > 1.0) {
        if (fabs((double)yf) > 1.0+tol) {
          istat = 1;
          if (!status) status = PRJERR_BAD_WORLD_SET("cscs2x");
        }
        yf = (float)copysign(1.0, (double)yf);
      }

      *xp = prj->w[0]*(xf + x0) - prj->x0;
      *yp = prj->w[0]*(yf + y0) - prj->y0;
      *statp = istat;
    }
  }

  return status;
}

/*============================================================================
*   QSC: quadrilaterilized spherical cube projection.
*
*   Given and/or returned:
*      prj->r0      Reset to 180/pi if 0.
*      prj->phi0    Reset to 0.0 if undefined.
*      prj->theta0  Reset to 0.0 if undefined.
*
*   Returned:
*      prj->flag     QSC
*      prj->code    "QSC"
*      prj->x0      Fiducial offset in x.
*      prj->y0      Fiducial offset in y.
*      prj->w[0]    r0*(pi/4)
*      prj->w[1]    (4/pi)/r0
*      prj->prjx2s  Pointer to qscx2s().
*      prj->prjs2x  Pointer to qscs2x().
*===========================================================================*/

int qscset(struct prjprm *prj)

{
  if (prj == 0x0) return PRJERR_NULL_POINTER;
  if (prj->flag == -QSC) return 0;

  strncpy(prj->code, "QSC", 4);

  strncpy(prj->name, "quadrilateralized spherical cube", 40);
  prj->category  = QUADCUBE;
  prj->pvrange   = 0;
  prj->simplezen = 0;
  prj->equiareal = 1;
  prj->conformal = 0;
  prj->global    = 1;
  prj->divergent = 0;

  if (prj->r0 == 0.0) {
    prj->r0 = R2D;
    prj->w[0] = 45.0;
    prj->w[1] = 1.0/45.0;
  } else {
    prj->w[0] = prj->r0*PI/4.0;
    prj->w[1] = 1.0/prj->w[0];
  }

  prj->prjx2s = qscx2s;
  prj->prjs2x = qscs2x;

  prj->flag = (prj->flag == 1) ? -QSC : QSC;

  return prjoff(prj, 0.0, 0.0);
}

//----------------------------------------------------------------------------

int qscx2s(
  struct prjprm *prj,
  int nx,
  int ny,
  int sxy,
  int spt,
  const double x[],
  const double y[],
  double phi[],
  double theta[],
  int stat[])

{
  const double tol = 1.0e-12;

  // Initialize.
  if (prj == 0x0) return PRJERR_NULL_POINTER;

  int status;
  if (abs(prj->flag) != QSC) {
    if ((status = qscset(prj))) return status;
  }

  int mx, my;
  if (ny > 0) {
    mx = nx;
    my = ny;
  } else {
    mx = 1;
    my = 1;
    ny = nx;
  }

  status = 0;


  // Do x dependence.
  const double *xp = x;
  int rowoff = 0;
  int rowlen = nx*spt;
  for (int ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    double xf = (*xp + prj->x0)*prj->w[1];

    double *phip = phi + rowoff;
    for (int iy = 0; iy < my; iy++) {
      *phip = xf;
      phip += rowlen;
    }
  }


  // Do y dependence.
  const double *yp = y;
  double *phip   = phi;
  double *thetap = theta;
  int    *statp  = stat;
  for (int iy = 0; iy < ny; iy++, yp += sxy) {
    double yf = (*yp + prj->y0)*prj->w[1];

    for (int ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
      double xf = *phip;

      // Bounds checking.
      if (fabs(xf) <= 1.0) {
        if (fabs(yf) > 3.0) {
          *phip = 0.0;
          *thetap = 0.0;
          *statp  = 1;
          if (!status) status = PRJERR_BAD_PIX_SET("qscx2s");
          continue;
        }
      } else {
        if (fabs(xf) > 7.0 || fabs(yf) > 1.0) {
          *phip = 0.0;
          *thetap = 0.0;
          *statp  = 1;
          if (!status) status = PRJERR_BAD_PIX_SET("qscx2s");
          continue;
        }
      }

      // Map negative faces to the other side.
      if (xf < -1.0) xf += 8.0;

      int face = 0;
      // Determine the face.
      if (xf > 5.0) {
        face = 4;
        xf -= 6.0;
      } else if (xf > 3.0) {
        face = 3;
        xf -= 4.0;
      } else if (xf > 1.0) {
        face = 2;
        xf -= 2.0;
      } else if (yf > 1.0) {
        face = 0;
        yf -= 2.0;
      } else if (yf < -1.0) {
        face = 5;
        yf += 2.0;
      } else {
        face = 1;
      }

      double omega, tau, w, zeta, zeco;
      int direct = (fabs(xf) > fabs(yf));
      if (direct) {
        if (xf == 0.0) {
          omega = 0.0;
          tau  = 1.0;
          zeta = 1.0;
          zeco = 0.0;
        } else {
          w = 15.0*yf/xf;
          omega = sind(w)/(cosd(w) - SQRT2INV);
          tau  = 1.0 + omega*omega;
          zeco = xf*xf*(1.0 - 1.0/sqrt(1.0 + tau));
          zeta = 1.0 - zeco;
        }
      } else {
        if (yf == 0.0) {
          omega = 0.0;
          tau  = 1.0;
          zeta = 1.0;
          zeco = 0.0;
        } else {
          w = 15.0*xf/yf;
          double sinw, cosw;
          sincosd(w, &sinw, &cosw);
          omega = sinw/(cosw - SQRT2INV);
          tau  = 1.0 + omega*omega;
          zeco = yf*yf*(1.0 - 1.0/sqrt(1.0 + tau));
          zeta = 1.0 - zeco;
        }
      }

      if (zeta < -1.0) {
        if (zeta < -1.0-tol) {
          *phip = 0.0;
          *thetap = 0.0;
          *statp  = 1;
          if (!status) status = PRJERR_BAD_PIX_SET("qscx2s");
          continue;
        }

        zeta = -1.0;
        w    =  0.0;
      } else {
        w = sqrt(zeco*(2.0-zeco)/tau);
      }

      double l, m, n;
      switch (face) {
      case 1:
        l = zeta;
        if (direct) {
          m = w;
          if (xf < 0.0) m = -m;
          n = m*omega;
        } else {
          n = w;
          if (yf < 0.0) n = -n;
          m = n*omega;
        }
        break;
      case 2:
        m = zeta;
        if (direct) {
          l = w;
          if (xf > 0.0) l = -l;
          n = -l*omega;
        } else {
          n = w;
          if (yf < 0.0) n = -n;
          l = -n*omega;
        }
        break;
      case 3:
        l = -zeta;
        if (direct) {
          m = w;
          if (xf > 0.0) m = -m;
          n = -m*omega;
        } else {
          n = w;
          if (yf < 0.0) n = -n;
          m = -n*omega;
        }
        break;
      case 4:
        m = -zeta;
        if (direct) {
          l = w;
          if (xf < 0.0) l = -l;
          n = l*omega;
        } else {
          n = w;
          if (yf < 0.0) n = -n;
          l = n*omega;
        }
        break;
      case 5:
        n = -zeta;
        if (direct) {
          m = w;
          if (xf < 0.0) m = -m;
          l = m*omega;
        } else {
          l = w;
          if (yf < 0.0) l = -l;
          m = l*omega;
        }
        break;
      default:
        // face == 0
        n = zeta;
        if (direct) {
          m = w;
          if (xf < 0.0) m = -m;
          l = -m*omega;
        } else {
          l = w;
          if (yf > 0.0) l = -l;
          m = -l*omega;
        }
        break;
      }

      if (l == 0.0 && m == 0.0) {
        *phip = 0.0;
      } else {
        *phip = atan2d(m, l);
      }

      *thetap = asind(n);
      *statp  = 0;
    }
  }


  // Do bounds checking on the native coordinates.
  if (prj->bounds&4 && prjbchk(1.0e-13, nx, my, spt, phi, theta, stat)) {
    if (!status) status = PRJERR_BAD_PIX_SET("qscx2s");
  }

  return status;
}

//----------------------------------------------------------------------------

int qscs2x(
  struct prjprm *prj,
  int nphi,
  int ntheta,
  int spt,
  int sxy,
  const double phi[],
  const double theta[],
  double x[],
  double y[],
  int stat[])

{
  const double tol = 1.0e-12;

  // Initialize.
  if (prj == 0x0) return PRJERR_NULL_POINTER;

  int status;
  if (abs(prj->flag) != QSC) {
    if ((status = qscset(prj))) return status;
  }

  int mphi, mtheta;
  if (ntheta > 0) {
    mphi   = nphi;
    mtheta = ntheta;
  } else {
    mphi   = 1;
    mtheta = 1;
    ntheta = nphi;
  }

  status = 0;


  // Do phi dependence.
  const double *phip = phi;
  int rowoff = 0;
  int rowlen = nphi*sxy;
  for (int iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    double sinphi, cosphi;
    sincosd(*phip, &sinphi, &cosphi);

    double *xp = x + rowoff;
    double *yp = y + rowoff;
    for (int itheta = 0; itheta < mtheta; itheta++) {
      *xp = cosphi;
      *yp = sinphi;
      xp += rowlen;
      yp += rowlen;
    }
  }


  // Do theta dependence.
  const double *thetap = theta;
  double *xp = x;
  double *yp = y;
  int *statp = stat;
  for (int itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    double sinthe, costhe;
    sincosd(*thetap, &sinthe, &costhe);

    for (int iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
      if (fabs(*thetap) == 90.0) {
        *xp = -prj->x0;
        *yp = copysign(2.0*prj->w[0], *thetap) - prj->y0;
        *statp = 0;
        continue;
      }

      double l = costhe*(*xp);
      double m = costhe*(*yp);
      double n = sinthe;

      int face = 0;
      double zeta = n;
      if (l > zeta) {
        face = 1;
        zeta = l;
      }
      if (m > zeta) {
        face = 2;
        zeta = m;
      }
      if (-l > zeta) {
        face = 3;
        zeta = -l;
      }
      if (-m > zeta) {
        face = 4;
        zeta = -m;
      }
      if (-n > zeta) {
        face = 5;
        zeta = -n;
      }

      double zeco = 1.0 - zeta;

      double xi, eta, x0, y0;
      switch (face) {
      case 1:
        xi  = m;
        eta = n;
        if (zeco < 1.0e-8) {
          // Small angle formula.
          double t = (*thetap)*D2R;
          double p = atan2(*yp, *xp);
          zeco = (p*p + t*t)/2.0;
        }
        x0 = 0.0;
        y0 = 0.0;
        break;
      case 2:
        xi  = -l;
        eta =  n;
        if (zeco < 1.0e-8) {
          // Small angle formula.
          double t = (*thetap)*D2R;
          double p = atan2(*yp, *xp) - PI/2.0;
          zeco = (p*p + t*t)/2.0;
        }
        x0 = 2.0;
        y0 = 0.0;
        break;
      case 3:
        xi  = -m;
        eta =  n;
        if (zeco < 1.0e-8) {
          // Small angle formula.
          double t = (*thetap)*D2R;
          double p = atan2(*yp, *xp);
          p -= copysign(PI, p);
          zeco = (p*p + t*t)/2.0;
        }
        x0 = 4.0;
        y0 = 0.0;
        break;
      case 4:
        xi  = l;
        eta = n;
        if (zeco < 1.0e-8) {
          // Small angle formula.
          double t = (*thetap)*D2R;
          double p = atan2(*yp, *xp) + PI/2.0;
          zeco = (p*p + t*t)/2.0;
        }
        x0 = 6;
        y0 = 0.0;
        break;
      case 5:
        xi  =  m;
        eta =  l;
        if (zeco < 1.0e-8) {
          // Small angle formula.
          double t = (*thetap + 90.0)*D2R;
          zeco = t*t/2.0;
        }
        x0 =  0.0;
        y0 = -2;
         break;
      default:
        // face == 0
        xi  =  m;
        eta = -l;
        if (zeco < 1.0e-8) {
          // Small angle formula.
          double t = (90.0 - *thetap)*D2R;
          zeco = t*t/2.0;
        }
        x0 = 0.0;
        y0 = 2.0;
        break;
      }

      double omega, tau;
      double xf = 0.0;
      double yf = 0.0;
      if (xi != 0.0 || eta != 0.0) {
        if (-xi > fabs(eta)) {
          omega = eta/xi;
          tau = 1.0 + omega*omega;
          xf  = -sqrt(zeco/(1.0 - 1.0/sqrt(1.0+tau)));
          yf  = (xf/15.0)*(atand(omega) - asind(omega/sqrt(tau+tau)));
        } else if (xi > fabs(eta)) {
          omega = eta/xi;
          tau = 1.0 + omega*omega;
          xf  =  sqrt(zeco/(1.0 - 1.0/sqrt(1.0+tau)));
          yf  = (xf/15.0)*(atand(omega) - asind(omega/sqrt(tau+tau)));
        } else if (-eta >= fabs(xi)) {
          omega = xi/eta;
          tau = 1.0 + omega*omega;
          yf  = -sqrt(zeco/(1.0 - 1.0/sqrt(1.0+tau)));
          xf  = (yf/15.0)*(atand(omega) - asind(omega/sqrt(tau+tau)));
        } else if (eta >= fabs(xi)) {
          omega = xi/eta;
          tau = 1.0 + omega*omega;
          yf  =  sqrt(zeco/(1.0 - 1.0/sqrt(1.0+tau)));
          xf  = (yf/15.0)*(atand(omega) - asind(omega/sqrt(tau+tau)));
        }
      }

      int istat = 0;
      if (fabs(xf) > 1.0) {
        if (fabs(xf) > 1.0+tol) {
          istat = 1;
          if (!status) status = PRJERR_BAD_WORLD_SET("qscs2x");
        }
        xf = copysign(1.0, xf);
      }
      if (fabs(yf) > 1.0) {
        if (fabs(yf) > 1.0+tol) {
          istat = 1;
          if (!status) status = PRJERR_BAD_WORLD_SET("qscs2x");
        }
        yf = copysign(1.0, yf);
      }

      *xp = prj->w[0]*(xf + x0) - prj->x0;
      *yp = prj->w[0]*(yf + y0) - prj->y0;
      *statp = istat;
    }
  }

  return status;
}

/*============================================================================
*   HPX: HEALPix projection.
*
*   Given:
*      prj->pv[1]   H - the number of facets in longitude.
*      prj->pv[2]   K - the number of facets in latitude
*
*   Given and/or returned:
*      prj->r0      Reset to 180/pi if 0.
*      prj->phi0    Reset to 0.0 if undefined.
*      prj->theta0  Reset to 0.0 if undefined.
*
*   Returned:
*      prj->flag     HPX
*      prj->code    "HPX"
*      prj->x0      Fiducial offset in x.
*      prj->y0      Fiducial offset in y.
*      prj->m       True if H is odd.
*      prj->n       True if K is odd.
*      prj->w[0]    r0*(pi/180)
*      prj->w[1]    (180/pi)/r0
*      prj->w[2]    (K-1)/K
*      prj->w[3]    90*K/H
*      prj->w[4]    (K+1)/2
*      prj->w[5]    90*(K-1)/H
*      prj->w[6]    180/H
*      prj->w[7]    H/360
*      prj->w[8]    r0*(pi/180)*(90*K/H)
*      prj->w[9]    r0*(pi/180)*(180/H)
*      prj->prjx2s  Pointer to hpxx2s().
*      prj->prjs2x  Pointer to hpxs2x().
*===========================================================================*/

int hpxset(struct prjprm *prj)

{
  if (prj == 0x0) return PRJERR_NULL_POINTER;
  if (prj->flag == -HPX) return 0;

  strncpy(prj->code, "HPX", 4);

  if (undefined(prj->pv[1])) prj->pv[1] = 4.0;
  if (undefined(prj->pv[2])) prj->pv[2] = 3.0;

  strncpy(prj->name, "HEALPix", 40);
  prj->category  = HEALPIX;
  prj->pvrange   = 102;
  prj->simplezen = 0;
  prj->equiareal = 1;
  prj->conformal = 0;
  prj->global    = 1;
  prj->divergent = 0;

  if (prj->pv[1] <= 0.0 || prj->pv[2] <= 0.0) {
    return PRJERR_BAD_PARAM_SET("hpxset");
  }

  prj->m = ((int)(prj->pv[1]+0.5))%2;
  prj->n = ((int)(prj->pv[2]+0.5))%2;

  if (prj->r0 == 0.0) {
    prj->r0 = R2D;
    prj->w[0] = 1.0;
    prj->w[1] = 1.0;
  } else {
    prj->w[0] = prj->r0*D2R;
    prj->w[1] = R2D/prj->r0;
  }

  prj->w[2] = (prj->pv[2] - 1.0) / prj->pv[2];
  prj->w[3] = 90.0 * prj->pv[2] / prj->pv[1];
  prj->w[4] = (prj->pv[2] + 1.0) / 2.0;
  prj->w[5] = 90.0 * (prj->pv[2] - 1.0) / prj->pv[1];
  prj->w[6] = 180.0 / prj->pv[1];
  prj->w[7] = prj->pv[1] / 360.0;
  prj->w[8] = prj->w[3] * prj->w[0];
  prj->w[9] = prj->w[6] * prj->w[0];

  prj->prjx2s = hpxx2s;
  prj->prjs2x = hpxs2x;

  prj->flag = (prj->flag == 1) ? -HPX : HPX;

  return prjoff(prj, 0.0, 0.0);
}

//----------------------------------------------------------------------------

int hpxx2s(
  struct prjprm *prj,
  int nx,
  int ny,
  int sxy,
  int spt,
  const double x[],
  const double y[],
  double phi[],
  double theta[],
  int stat[])

{
  // Initialize.
  if (prj == 0x0) return PRJERR_NULL_POINTER;

  int status;
  if (abs(prj->flag) != HPX) {
    if ((status = hpxset(prj))) return status;
  }

  int mx, my;
  if (ny > 0) {
    mx = nx;
    my = ny;
  } else {
    mx = 1;
    my = 1;
    ny = nx;
  }

  status = 0;


  // Do x dependence.
  const double *xp = x;
  int rowoff = 0;
  int rowlen = nx*spt;
  for (int ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    double s = prj->w[1] * (*xp + prj->x0);
    // x_c for K odd or theta > 0.
    double t;
    t = -180.0 + (2.0 * floor((*xp + 180.0) * prj->w[7]) + 1.0) * prj->w[6];
    t = prj->w[1] * (*xp - t);

    double *phip   = phi + rowoff;
    double *thetap = theta + rowoff;
    for (int iy = 0; iy < my; iy++) {
      // theta[] is used to hold (x - x_c).
      *phip   = s;
      *thetap = t;
      phip   += rowlen;
      thetap += rowlen;
    }
  }


  // Do y dependence.
  const double *yp = y;
  double *phip   = phi;
  double *thetap = theta;
  int    *statp  = stat;

  double slim = prj->w[6] + 1e-12;
  double ylim = prj->w[9] * prj->w[4];

  for (int iy = 0; iy < ny; iy++, yp += sxy) {
    double yr = prj->w[1]*(*yp + prj->y0);
    double absy = fabs(yr);

    int istat = 0;
    if (absy <= prj->w[5]) {
      // Equatorial regime.
      double t = asind(yr/prj->w[3]);
      for (int ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
        *thetap = t;
        *statp  = 0;
      }

    } else if (absy <= ylim) {
      // Polar regime.
      int offset = (prj->n || *yp > 0.0) ? 0 : 1;

      double sigma = prj->w[4] - absy / prj->w[6];

      double s, t;
      if (sigma == 0.0) {
        s = 1e9;
        t = 90.0;

      } else {
        t = 1.0 - sigma*sigma/prj->pv[2];
        if (t < -1.0) {
          s = 0.0;
          t = 0.0;
          istat = 1;
          if (!status) status = PRJERR_BAD_PIX_SET("hpxx2s");
        } else {
          s = 1.0/sigma;
          t = asind(t);
        }
      }
      if (*yp < 0.0) t = -t;

      for (int ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
        if (offset) {
          // Offset the southern polar half-facets for even K.
          int h = (int)floor(*phip / prj->w[6]) + prj->m;
          if (h%2) {
            *thetap -= prj->w[6];
          } else {
            *thetap += prj->w[6];
          }
        }

        // Recall that theta[] holds (x - x_c).
        double r = s * *thetap;

        // Bounds checking.
        if (prj->bounds&2) {
          if (slim <= fabs(r)) {
            istat = 1;
            if (!status) status = PRJERR_BAD_PIX_SET("hpxx2s");
          }
        }

        if (r != 0.0) r -= *thetap;
        *phip  += r;
        *thetap = t;
        *statp  = istat;
      }

    } else {
      // Beyond latitude range.
      for (int ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
        *phip   = 0.0;
        *thetap = 0.0;
        *statp  = 1;
      }
      if (!status) status = PRJERR_BAD_PIX_SET("hpxx2s");
    }
  }


  // Do bounds checking on the native coordinates.
  if (prj->bounds&4 && prjbchk(1.0e-12, nx, my, spt, phi, theta, stat)) {
    if (!status) status = PRJERR_BAD_PIX_SET("hpxx2s");
  }

  return status;
}

//----------------------------------------------------------------------------

int hpxs2x(
  struct prjprm *prj,
  int nphi,
  int ntheta,
  int spt,
  int sxy,
  const double phi[],
  const double theta[],
  double x[],
  double y[],
  int stat[])

{
  // Initialize.
  if (prj == 0x0) return PRJERR_NULL_POINTER;

  int status;
  if (abs(prj->flag) != HPX) {
    if ((status = hpxset(prj))) return status;
  }

  int mphi, mtheta;
  if (ntheta > 0) {
    mphi   = nphi;
    mtheta = ntheta;
  } else {
    mphi   = 1;
    mtheta = 1;
    ntheta = nphi;
  }


  // Do phi dependence.
  const double *phip = phi;
  int rowoff = 0;
  int rowlen = nphi*sxy;
  for (int iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    double xi = prj->w[0] * (*phip) - prj->x0;

    // phi_c for K odd or theta > 0.
    double t;
    t = -180.0 + (2.0*floor((*phip+180.0) * prj->w[7]) + 1.0) * prj->w[6];
    t = prj->w[0] * (*phip - t);

    double *xp = x + rowoff;
    double *yp = y + rowoff;
    for (int itheta = 0; itheta < mtheta; itheta++) {
      // y[] is used to hold (phi - phi_c).
      *xp = xi;
      *yp = t;
      xp += rowlen;
      yp += rowlen;
    }
  }


  // Do theta dependence.
  const double *thetap = theta;
  double *xp = x;
  double *yp = y;
  int *statp = stat;
  for (int itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    double sinthe = sind(*thetap);
    double abssin = fabs(sinthe);

    double eta;
    if (abssin <= prj->w[2]) {
      // Equatorial regime.
      eta = prj->w[8] * sinthe - prj->y0;
      for (int iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
        *yp = eta;
        *statp = 0;
      }

    } else {
      // Polar regime.
      int offset = (prj->n || *thetap > 0.0) ? 0 : 1;

      double sigma = sqrt(prj->pv[2]*(1.0 - abssin));
      double xi = sigma - 1.0;

      eta = prj->w[9] * (prj->w[4] - sigma);
      if (*thetap < 0) eta = -eta;
      eta -= prj->y0;

      for (int iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
        if (offset) {
          // Offset the southern polar half-facets for even K.
          int h = (int)floor((*xp + prj->x0) / prj->w[9]) + prj->m;
          if (h%2) {
            *yp -= prj->w[9];
          } else {
            *yp += prj->w[9];
          }
        }

        // Recall that y[] holds (phi - phi_c).
        *xp += *yp * xi;
        *yp = eta;
        *statp = 0;

        // Put the phi = 180 meridian in the expected place.
        if (180.0 < *xp) *xp = 360.0 - *xp;
      }
    }
  }

  return 0;
}

/*============================================================================
*   XPH: HEALPix polar, aka "butterfly" projection.
*
*   Given and/or returned:
*      prj->r0      Reset to 180/pi if 0.
*      prj->phi0    Reset to 0.0 if undefined.
*      prj->theta0  Reset to 0.0 if undefined.
*
*   Returned:
*      prj->flag     XPH
*      prj->code    "XPH"
*      prj->x0      Fiducial offset in x.
*      prj->y0      Fiducial offset in y.
*      prj->w[0]    r0*(pi/180)/sqrt(2)
*      prj->w[1]    (180/pi)/r0/sqrt(2)
*      prj->w[2]    2/3
*      prj->w[3]    tol (= 1e-4)
*      prj->w[4]    sqrt(2/3)*(180/pi)
*      prj->w[5]    90 - tol*sqrt(2/3)*(180/pi)
*      prj->w[6]    sqrt(3/2)*(pi/180)
*      prj->prjx2s  Pointer to xphx2s().
*      prj->prjs2x  Pointer to xphs2x().
*===========================================================================*/

int xphset(struct prjprm *prj)

{
  if (prj == 0x0) return PRJERR_NULL_POINTER;
  if (prj->flag == -XPH) return 0;

  strncpy(prj->code, "XPH", 4);

  strncpy(prj->name, "butterfly", 40);
  prj->category  = HEALPIX;
  prj->pvrange   = 0;
  prj->simplezen = 0;
  prj->equiareal = 1;
  prj->conformal = 0;
  prj->global    = 1;
  prj->divergent = 0;

  if (prj->r0 == 0.0) {
    prj->r0 = R2D;
    prj->w[0] = 1.0;
    prj->w[1] = 1.0;
  } else {
    prj->w[0] = prj->r0*D2R;
    prj->w[1] = R2D/prj->r0;
  }

  prj->w[0] /= sqrt(2.0);
  prj->w[1] /= sqrt(2.0);
  prj->w[2]  = 2.0/3.0;
  prj->w[3]  = 1e-4;
  prj->w[4]  = sqrt(prj->w[2])*R2D;
  prj->w[5]  = 90.0 - prj->w[3]*prj->w[4];
  prj->w[6]  = sqrt(1.5)*D2R;

  prj->prjx2s = xphx2s;
  prj->prjs2x = xphs2x;

  prj->flag = (prj->flag == 1) ? -XPH : XPH;

  return prjoff(prj, 0.0, 90.0);
}

//----------------------------------------------------------------------------

int xphx2s(
  struct prjprm *prj,
  int nx,
  int ny,
  int sxy,
  int spt,
  const double x[],
  const double y[],
  double phi[],
  double theta[],
  int stat[])

{
  const double tol = 1.0e-12;

  // Initialize.
  if (prj == 0x0) return PRJERR_NULL_POINTER;

  int status;
  if (abs(prj->flag) != XPH) {
    if ((status = xphset(prj))) return status;
  }

  int mx, my;
  if (ny > 0) {
    mx = nx;
    my = ny;
  } else {
    mx = 1;
    my = 1;
    ny = nx;
  }

  status = 0;


  // Do x dependence.
  const double *xp = x;
  int rowoff = 0;
  int rowlen = nx*spt;
  for (int ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    double xr = (*xp + prj->x0)*prj->w[1];

    double *phip = phi + rowoff;
    for (int iy = 0; iy < my; iy++) {
      *phip = xr;
      phip  += rowlen;
    }
  }


  // Do y dependence.
  const double *yp = y;
  double *phip   = phi;
  double *thetap = theta;
  int    *statp  = stat;
  for (int iy = 0; iy < ny; iy++, yp += sxy) {
    double yr = (*yp + prj->y0)*prj->w[1];

    for (int ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
      double xr = *phip;

      double xi1, eta1;
      if (xr <= 0.0 && 0.0 < yr) {
        xi1  = -xr - yr;
        eta1 =  xr - yr;
        *phip = -180.0;
      } else if (xr < 0.0 && yr <= 0.0) {
        xi1  =  xr - yr;
        eta1 =  xr + yr;
        *phip = -90.0;
      } else if (0.0 <= xr && yr < 0.0) {
        xi1  =  xr + yr;
        eta1 = -xr + yr;
        *phip = 0.0;
      } else {
        xi1  = -xr + yr;
        eta1 = -xr - yr;
        *phip = 90.0;
      }

      double xi  = xi1  + 45.0;
      double eta = eta1 + 90.0;
      double abseta = fabs(eta);

      if (abseta <= 90.0) {
        if (abseta <= 45.0) {
          // Equatorial regime.
          *phip  += xi;
          *thetap = asind(eta/67.5);
          int istat = 0;

          // Bounds checking.
          if (prj->bounds&2) {
            if (45.0+tol < fabs(xi1)) {
              istat = 1;
              if (!status) status = PRJERR_BAD_PIX_SET("xphx2s");
            }
          }

          *statp = istat;

        } else {
          // Polar regime.
          double sigma = (90.0 - abseta) / 45.0;

          // Ensure an exact result for points on the boundary.
          if (xr == 0.0) {
            if (yr <= 0.0) {
              *phip = 0.0;
            } else {
              *phip = 180.0;
            }
          } else if (yr == 0.0) {
            if (xr < 0.0) {
              *phip = -90.0;
            } else {
              *phip =  90.0;
            }
          } else {
            *phip += 45.0 + xi1/sigma;
          }

          if (sigma < prj->w[3]) {
            *thetap = 90.0 - sigma*prj->w[4];
          } else {
            *thetap = asind(1.0 - sigma*sigma/3.0);
          }
          if (eta < 0.0) *thetap = -(*thetap);

          // Bounds checking.
          int istat = 0;
          if (prj->bounds&2) {
            if (eta < -45.0 && eta+90.0+tol < fabs(xi1)) {
              istat = 1;
              if (!status) status = PRJERR_BAD_PIX_SET("xphx2s");
            }
          }

          *statp = istat;
        }

      } else {
        // Beyond latitude range.
        *phip   = 0.0;
        *thetap = 0.0;
        *statp  = 1;
        if (!status) status = PRJERR_BAD_PIX_SET("xphx2s");
      }
    }
  }


  // Do bounds checking on the native coordinates.
  if (prj->bounds&4 && prjbchk(1.0e-12, nx, my, spt, phi, theta, stat)) {
    if (!status) status = PRJERR_BAD_PIX_SET("xphx2s");
  }

  return status;
}

//----------------------------------------------------------------------------

int xphs2x(
  struct prjprm *prj,
  int nphi,
  int ntheta,
  int spt,
  int sxy,
  const double phi[],
  const double theta[],
  double x[],
  double y[],
  int stat[])

{
  // Initialize.
  if (prj == 0x0) return PRJERR_NULL_POINTER;

  int status;
  if (abs(prj->flag) != XPH) {
    if ((status = xphset(prj))) return status;
  }

  int mphi, mtheta;
  if (ntheta > 0) {
    mphi   = nphi;
    mtheta = ntheta;
  } else {
    mphi   = 1;
    mtheta = 1;
    ntheta = nphi;
  }


  // Do phi dependence.
  const double *phip = phi;
  int rowoff = 0;
  int rowlen = nphi*sxy;

  double chi, psi;
  for (int iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    chi = *phip;
    if (180.0 <= fabs(chi)) {
      chi = fmod(chi, 360.0);
      if (chi < -180.0) {
        chi += 360.0;
      } else if (180.0 <= chi) {
        chi -= 360.0;
      }
    }

    // phi is also recomputed from chi to avoid rounding problems.
    chi += 180.0;
    psi = fmod(chi, 90.0);

    double *xp = x + rowoff;
    double *yp = y + rowoff;
    for (int itheta = 0; itheta < mtheta; itheta++) {
      // y[] is used to hold phi (rounded).
      *xp = psi;
      *yp = chi - 180.0;
      xp += rowlen;
      yp += rowlen;
    }
  }


  // Do theta dependence.
  const double *thetap = theta;
  double *xp = x;
  double *yp = y;
  int *statp = stat;
  for (int itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    double sinthe = sind(*thetap);
    double abssin = fabs(sinthe);

    for (int iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
      double xi, eta;
      if (abssin <= prj->w[2]) {
        // Equatorial regime.
        xi  = *xp;
        eta = 67.5 * sinthe;

      } else {
        // Polar regime.
        double sigma;
        if (*thetap < prj->w[5]) {
          sigma = sqrt(3.0*(1.0 - abssin));
        } else {
          sigma = (90.0 - *thetap)*prj->w[6];
        }

        xi  = 45.0 + (*xp - 45.0)*sigma;
        eta = 45.0 * (2.0 - sigma);
        if (*thetap < 0.0) eta = -eta;
      }

      xi  -= 45.0;
      eta -= 90.0;

      // Recall that y[] holds phi.
      if (*yp < -90.0) {
        *xp = prj->w[0]*(-xi + eta) - prj->x0;
        *yp = prj->w[0]*(-xi - eta) - prj->y0;

      } else if (*yp <  0.0) {
        *xp = prj->w[0]*(+xi + eta) - prj->x0;
        *yp = prj->w[0]*(-xi + eta) - prj->y0;

      } else if (*yp < 90.0) {
        *xp = prj->w[0]*( xi - eta) - prj->x0;
        *yp = prj->w[0]*( xi + eta) - prj->y0;

      } else {
        *xp = prj->w[0]*(-xi - eta) - prj->x0;
        *yp = prj->w[0]*( xi - eta) - prj->y0;
      }

      *statp = 0;
    }
  }

  return 0;
}
@


8.6
log
@WCSLIB 8.6
@
text
@d2 1
a2 1
  WCSLIB 8.6 - an implementation of the FITS WCS standard.
d22 1
a22 1
  $Id: prj.c,v 8.5.1.2 2026/03/29 13:36:16 mcalabre Exp mcalabre $
a111 2
#define copysign(X, Y) ((Y) < 0.0 ? -fabs(X) : fabs(X))

d144 1
a144 1
  strcpy(prj->code, "   ");
d155 1
a155 1
  strcpy(prj->name, "undefined");
d609 1
a609 1
  strcpy(prj->code, "AZP");
d615 1
a615 1
  strcpy(prj->name, "zenithal/azimuthal perspective");
d930 1
a930 1
  strcpy(prj->code, "SZP");
d937 1
a937 1
  strcpy(prj->name, "slant zenithal perspective");
d1255 1
a1255 1
  strcpy(prj->code, "TAN");
d1259 1
a1259 1
  strcpy(prj->name, "gnomonic");
d1478 1
a1478 1
  strcpy(prj->code, "STG");
d1480 1
a1480 1
  strcpy(prj->name, "stereographic");
d1696 1
a1696 1
  strcpy(prj->code, "SIN");
d1702 1
a1702 1
  strcpy(prj->name, "orthographic/synthesis");
d2034 1
a2034 1
  strcpy(prj->code, "ARC");
d2036 1
a2036 1
  strcpy(prj->name, "zenithal/azimuthal equidistant");
d2249 1
a2249 1
  strcpy(prj->code, "ZPN");
d2256 1
a2256 1
  strcpy(prj->name, "zenithal/azimuthal polynomial");
d2649 1
a2649 1
  strcpy(prj->code, "ZEA");
d2651 1
a2651 1
  strcpy(prj->name, "zenithal/azimuthal equal area");
d2884 1
a2884 1
  strcpy(prj->code, "AIR");
d2889 1
a2889 1
  strcpy(prj->name, "Airy's zenithal");
d3196 1
a3196 1
  strcpy(prj->code, "CYP");
d3201 1
a3201 1
  strcpy(prj->name, "cylindrical perspective");
d3432 1
a3432 1
  strcpy(prj->code, "CEA");
d3436 1
a3436 1
  strcpy(prj->name, "cylindrical equal area");
d3650 1
a3650 1
  strcpy(prj->code, "CAR");
d3652 1
a3652 1
  strcpy(prj->name, "plate caree");
d3841 1
a3841 1
  strcpy(prj->code, "MER");
d3843 1
a3843 1
  strcpy(prj->name, "Mercator's");
d4043 1
a4043 1
  strcpy(prj->code, "SFL");
d4045 1
a4045 1
  strcpy(prj->name, "Sanson-Flamsteed");
d4252 1
a4252 1
  strcpy(prj->code, "PAR");
d4254 1
a4254 1
  strcpy(prj->name, "parabolic");
d4492 1
a4492 1
  strcpy(prj->code, "MOL");
d4496 1
a4496 1
  strcpy(prj->name, "Mollweide's");
d4784 1
a4784 1
  strcpy(prj->code, "AIT");
d4788 1
a4788 1
  strcpy(prj->name, "Hammer-Aitoff");
d5033 1
a5033 1
  strcpy(prj->code, "COP");
d5041 1
a5041 1
  strcpy(prj->name, "conic perspective");
d5308 1
a5308 1
  strcpy(prj->code, "COE");
d5316 1
a5316 1
  strcpy(prj->name, "conic equal area");
d5573 1
a5573 1
  strcpy(prj->code, "COD");
d5581 1
a5581 1
  strcpy(prj->name, "conic equidistant");
d5808 1
a5808 1
  strcpy(prj->code, "COO");
d5816 1
a5816 1
  strcpy(prj->name, "conic orthomorphic");
d6075 1
a6075 1
  strcpy(prj->code, "BON");
d6086 1
a6086 1
  strcpy(prj->name, "Bonne's");
d6316 1
a6316 1
  strcpy(prj->code, "PCO");
d6318 1
a6318 1
  strcpy(prj->name, "polyconic");
d6604 1
a6604 1
  strcpy(prj->code, "TSC");
d6606 1
a6606 1
  strcpy(prj->name, "tangential spherical cube");
d6960 1
a6960 1
  strcpy(prj->code, "CSC");
d6962 1
a6962 1
  strcpy(prj->name, "COBE quadrilateralized spherical cube");
d7322 2
a7323 2
        x0  =  0.0;
        y0  =  0.0;
d7328 2
a7329 2
        x0  =  2.0;
        y0  =  0.0;
d7334 2
a7335 2
        x0  =  4.0;
        y0  =  0.0;
d7340 2
a7341 2
        x0  =  6.0;
        y0  =  0.0;
d7346 2
a7347 2
        x0  =  0.0;
        y0  = -2.0;
d7353 2
a7354 2
        x0  =  0.0;
        y0  =  2.0;
d7430 1
a7430 1
  strcpy(prj->code, "QSC");
d7432 1
a7432 1
  strcpy(prj->name, "quadrilateralized spherical cube");
a7606 1
        zeco =  2.0;
d7979 1
a7979 1
  strcpy(prj->code, "HPX");
d7984 1
a7984 1
  strcpy(prj->name, "HEALPix");
d8322 1
a8322 1
  strcpy(prj->code, "XPH");
d8324 1
a8324 1
  strcpy(prj->name, "butterfly");
@


8.6.1.1
log
@WCSLIB 8.6 development branch.
@
text
@d22 1
a22 1
  $Id: prj.c,v 8.6 2026/03/29 13:53:56 mcalabre Exp $
@


8.6.1.2
log
@Found by Claude Code:
 - Removed the copysign() macro, now provided by C99.
@
text
@d22 1
a22 1
  $Id: prj.c,v 8.6.1.1 2026/03/29 14:19:26 mcalabre Exp mcalabre $
d111 2
@


8.6.1.3
log
@Use strncpy(), rather than strcpy(), to copy string constants to prj::name
so that it will be null-filled (not suggested by clang-tidy).
Inconsequential changes prompted by clang-tidy:
 - Assign float constants, rather than double, to float variables in cscs2x()
   (bugprone-narrowing-conversions).
 - Removed an unused variable in qscx2s()
   (clang-analyzer-deadcode.DeadStores).
@
text
@d22 1
a22 1
  $Id: prj.c,v 8.6.1.2 2026/04/05 14:03:29 mcalabre Exp mcalabre $
d155 1
a155 1
  strncpy(prj->name, "undefined", 40);
d615 1
a615 1
  strncpy(prj->name, "zenithal/azimuthal perspective", 40);
d937 1
a937 1
  strncpy(prj->name, "slant zenithal perspective", 40);
d1259 1
a1259 1
  strncpy(prj->name, "gnomonic", 40);
d1480 1
a1480 1
  strncpy(prj->name, "stereographic", 40);
d1702 1
a1702 1
  strncpy(prj->name, "orthographic/synthesis", 40);
d2036 1
a2036 1
  strncpy(prj->name, "zenithal/azimuthal equidistant", 40);
d2256 1
a2256 1
  strncpy(prj->name, "zenithal/azimuthal polynomial", 40);
d2651 1
a2651 1
  strncpy(prj->name, "zenithal/azimuthal equal area", 40);
d2889 1
a2889 1
  strncpy(prj->name, "Airy's zenithal", 40);
d3201 1
a3201 1
  strncpy(prj->name, "cylindrical perspective", 40);
d3436 1
a3436 1
  strncpy(prj->name, "cylindrical equal area", 40);
d3652 1
a3652 1
  strncpy(prj->name, "plate caree", 40);
d3843 1
a3843 1
  strncpy(prj->name, "Mercator's", 40);
d4045 1
a4045 1
  strncpy(prj->name, "Sanson-Flamsteed", 40);
d4254 1
a4254 1
  strncpy(prj->name, "parabolic", 40);
d4496 1
a4496 1
  strncpy(prj->name, "Mollweide's", 40);
d4788 1
a4788 1
  strncpy(prj->name, "Hammer-Aitoff", 40);
d5041 1
a5041 1
  strncpy(prj->name, "conic perspective", 40);
d5316 1
a5316 1
  strncpy(prj->name, "conic equal area", 40);
d5581 1
a5581 1
  strncpy(prj->name, "conic equidistant", 40);
d5816 1
a5816 1
  strncpy(prj->name, "conic orthomorphic", 40);
d6086 1
a6086 1
  strncpy(prj->name, "Bonne's", 40);
d6318 1
a6318 1
  strncpy(prj->name, "polyconic", 40);
d6606 1
a6606 1
  strncpy(prj->name, "tangential spherical cube", 40);
d6962 1
a6962 1
  strncpy(prj->name, "COBE quadrilateralized spherical cube", 40);
d7322 2
a7323 2
        x0  =  0.0f;
        y0  =  0.0f;
d7328 2
a7329 2
        x0  =  2.0f;
        y0  =  0.0f;
d7334 2
a7335 2
        x0  =  4.0f;
        y0  =  0.0f;
d7340 2
a7341 2
        x0  =  6.0f;
        y0  =  0.0f;
d7346 2
a7347 2
        x0  =  0.0f;
        y0  = -2.0f;
d7353 2
a7354 2
        x0  =  0.0f;
        y0  =  2.0f;
d7432 1
a7432 1
  strncpy(prj->name, "quadrilateralized spherical cube", 40);
d7607 1
d7985 1
a7985 1
  strncpy(prj->name, "HEALPix", 40);
d8325 1
a8325 1
  strncpy(prj->name, "butterfly", 40);
@


8.6.1.4
log
@Use strncpy(), rather than strcpy(), to copy the projection codes to
prj::code.  This was simple to eliminate the last occurrences of strcpy()
from the library (not suggested by clang-tidy).
@
text
@d22 1
a22 1
  $Id: prj.c,v 8.6.1.3 2026/04/21 13:07:15 mcalabre Exp mcalabre $
d144 1
a144 1
  strncpy(prj->code, "   ", 4);
d609 1
a609 1
  strncpy(prj->code, "AZP", 4);
d930 1
a930 1
  strncpy(prj->code, "SZP", 4);
d1255 1
a1255 1
  strncpy(prj->code, "TAN", 4);
d1478 1
a1478 1
  strncpy(prj->code, "STG", 4);
d1696 1
a1696 1
  strncpy(prj->code, "SIN", 4);
d2034 1
a2034 1
  strncpy(prj->code, "ARC", 4);
d2249 1
a2249 1
  strncpy(prj->code, "ZPN", 4);
d2649 1
a2649 1
  strncpy(prj->code, "ZEA", 4);
d2884 1
a2884 1
  strncpy(prj->code, "AIR", 4);
d3196 1
a3196 1
  strncpy(prj->code, "CYP", 4);
d3432 1
a3432 1
  strncpy(prj->code, "CEA", 4);
d3650 1
a3650 1
  strncpy(prj->code, "CAR", 4);
d3841 1
a3841 1
  strncpy(prj->code, "MER", 4);
d4043 1
a4043 1
  strncpy(prj->code, "SFL", 4);
d4252 1
a4252 1
  strncpy(prj->code, "PAR", 4);
d4492 1
a4492 1
  strncpy(prj->code, "MOL", 4);
d4784 1
a4784 1
  strncpy(prj->code, "AIT", 4);
d5033 1
a5033 1
  strncpy(prj->code, "COP", 4);
d5308 1
a5308 1
  strncpy(prj->code, "COE", 4);
d5573 1
a5573 1
  strncpy(prj->code, "COD", 4);
d5808 1
a5808 1
  strncpy(prj->code, "COO", 4);
d6075 1
a6075 1
  strncpy(prj->code, "BON", 4);
d6316 1
a6316 1
  strncpy(prj->code, "PCO", 4);
d6604 1
a6604 1
  strncpy(prj->code, "TSC", 4);
d6960 1
a6960 1
  strncpy(prj->code, "CSC", 4);
d7430 1
a7430 1
  strncpy(prj->code, "QSC", 4);
d7979 1
a7979 1
  strncpy(prj->code, "HPX", 4);
d8322 1
a8322 1
  strncpy(prj->code, "XPH", 4);
@


8.5
log
@WCSLIB 8.5
@
text
@d2 2
a3 2
  WCSLIB 8.5 - an implementation of the FITS WCS standard.
  Copyright (C) 1995-2025, Mark Calabretta
d21 2
a22 2
  http://www.atnf.csiro.au/people/Mark.Calabretta
  $Id: prj.c,v 8.4.1.2 2025/12/06 13:37:15 mcalabre Exp mcalabre $
@


8.5.1.1
log
@WCSLIB 8.5 development branch.
@
text
@d22 1
a22 1
  $Id: prj.c,v 8.5 2025/12/06 13:47:41 mcalabre Exp $
@


8.5.1.2
log
@Updated date in copyright notice.
@
text
@d3 1
a3 1
  Copyright (C) 1995-2026, Mark Calabretta
d21 2
a22 2
  http://www.atnf.csiro.au/computing/software/wcs
  $Id: prj.c,v 8.5.1.1 2025/12/06 14:05:15 mcalabre Exp mcalabre $
@


8.4
log
@WCSLIB 8.4
@
text
@d2 2
a3 2
  WCSLIB 8.4 - an implementation of the FITS WCS standard.
  Copyright (C) 1995-2024, Mark Calabretta
d22 1
a22 1
  $Id: prj.c,v 8.3.1.2 2024/07/09 09:03:22 mcalabre Exp mcalabre $
@


8.4.1.1
log
@WCSLIB 8.4 development branch.
@
text
@d22 1
a22 1
  $Id: prj.c,v 8.4 2024/10/28 13:56:16 mcalabre Exp $
@


8.4.1.2
log
@Updated date in copyright notice.
@
text
@d3 1
a3 1
  Copyright (C) 1995-2025, Mark Calabretta
d22 1
a22 1
  $Id: prj.c,v 8.4.1.1 2024/10/28 13:58:41 mcalabre Exp mcalabre $
@


8.3
log
@WCSLIB 8.3
@
text
@d2 1
a2 1
  WCSLIB 8.3 - an implementation of the FITS WCS standard.
d22 1
a22 1
  $Id: prj.c,v 8.2.1.8 2024/05/10 14:34:04 mcalabre Exp mcalabre $
d312 1
a312 1
  // Work arrays.
d325 1
a325 1
  // Pointers to projection functions.
@


8.3.1.1
log
@WCSLIB 8.3 development branch.
@
text
@d22 1
a22 1
  $Id: prj.c,v 8.3 2024/05/13 16:33:00 mcalabre Exp $
@


8.3.1.2
log
@Tweaked a couple of comments in prjprt().
@
text
@d22 1
a22 1
  $Id: prj.c,v 8.3.1.1 2024/05/13 16:35:39 mcalabre Exp mcalabre $
d312 1
a312 1
  // Intermediate values set by prjset().
d325 1
a325 1
  // Pointers to projection and deprojection functions.
@


8.2
log
@WCSLIB 8.2
@
text
@d2 2
a3 2
  WCSLIB 8.2 - an implementation of the FITS WCS standard.
  Copyright (C) 1995-2023, Mark Calabretta
d22 1
a22 1
  $Id: prj.c,v 8.1.1.1 2023/07/05 17:15:00 mcalabre Exp mcalabre $
a59 30
const int AZP = 101;
const int SZP = 102;
const int TAN = 103;
const int STG = 104;
const int SIN = 105;
const int ARC = 106;
const int ZPN = 107;
const int ZEA = 108;
const int AIR = 109;
const int CYP = 201;
const int CEA = 202;
const int CAR = 203;
const int MER = 204;
const int SFL = 301;
const int PAR = 302;
const int MOL = 303;
const int AIT = 401;
const int COP = 501;
const int COE = 502;
const int COD = 503;
const int COO = 504;
const int BON = 601;
const int PCO = 602;
const int TSC = 701;
const int CSC = 702;
const int QSC = 703;
const int HPX = 801;
const int XPH = 802;


d68 29
d123 1
a123 1
* prjsize computed the size of a prjprm struct.
a143 2
  register int k;

a145 2
  prj->flag = 0;

d151 1
a151 1
  for (k = 4; k < PVN; prj->pv[k++] = 0.0);
d158 1
a158 1
  for (k = 9; k < 40; prj->name[k++] = '\0');
d172 1
a172 1
  for (k = 0; k < 10; prj->w[k++] = 0.0);
d178 2
d202 1
a202 1
    return PRJERR_SUCCESS;
d211 1
a212 2

  // prjprm::err.
d216 25
a240 1
  return PRJERR_SUCCESS;
a247 3
  char hext[32];
  int  i, n;

d250 1
d252 1
a252 1
  wcsprintf("       code: \"%s\"\n",  prj->code);
d256 1
a256 1
    n = (prj->pvrange)%100;
d265 1
a265 1
    for (i = 1; i <= n; i++) {
d292 1
d306 1
d312 1
d314 1
a314 1
  for (i = 0; i < 5; i++) {
d318 1
a318 1
  for (i = 5; i < 10; i++) {
d324 3
d361 7
a367 9
  int status = 0;
  register int iphi, itheta, *statp;
  register double *phip, *thetap;

  phip   = phi;
  thetap = theta;
  statp  = stat;
  for (itheta = 0; itheta < ntheta; itheta++) {
    for (iphi = 0; iphi < nphi; iphi++, phip += spt, thetap += spt, statp++) {
a414 3
  int status;
  struct wcserr **err;

d416 2
a417 1
  err = &(prj->err);
d421 2
a502 2
  int status;

d505 3
a507 1
  if (prj->flag == 0) {
a528 2
  int status;

d531 3
a533 1
  if (prj->flag == 0) {
d545 1
a545 1
int prjoff(
a550 3
  int    stat;
  double x0, y0;

d562 2
d609 1
a610 1
  prj->flag = AZP;
d652 2
a671 2
  int mx, my, rowlen, rowoff, status;
  double a, b, q, r, s, t, xj, yj, yc, yc2;
a672 4
  register int ix, iy, *statp;
  register const double *xp, *yp;
  register double *phip, *thetap;

d676 3
a678 1
  if (prj->flag != AZP) {
d682 1
d696 6
a701 5
  xp = x;
  rowoff = 0;
  rowlen = nx*spt;
  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    xj = *xp + prj->x0;
d704 1
a704 1
    for (iy = 0; iy < my; iy++) {
d712 3
a714 1
  yp = y;
d717 2
a718 3
  statp  = stat;
  for (iy = 0; iy < ny; iy++, yp += sxy) {
    yj = *yp + prj->y0;
d720 2
a721 2
    yc  = yj*prj->w[3];
    yc2 = yc*yc;
d723 1
a723 1
    q = prj->w[0] + yj*prj->w[4];
d725 2
a726 2
    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
      xj = *phip;
d728 1
a728 1
      r = sqrt(xj*xj + yc2);
d737 2
a738 2
        s = r / q;
        t = s*prj->pv[1]/sqrt(s*s + 1.0);
d754 2
a755 2
        a = s - t;
        b = s + t + 180.0;
a789 7
  int mphi, mtheta, rowlen, rowoff, status;
  double a, b, cosphi, costhe, r, s, sinphi, sinthe, t;
  register int iphi, itheta, istat, *statp;
  register const double *phip, *thetap;
  register double *xp, *yp;


d792 3
a794 1
  if (prj->flag != AZP) {
d798 1
d812 5
a816 4
  phip = phi;
  rowoff = 0;
  rowlen = nphi*sxy;
  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
d819 3
a821 3
    xp = x + rowoff;
    yp = y + rowoff;
    for (itheta = 0; itheta < mtheta; itheta++) {
d831 6
a836 5
  thetap = theta;
  xp = x;
  yp = y;
  statp = stat;
  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
d839 3
a841 3
    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
      s = prj->w[1]*(*yp);
      t = (prj->pv[1] + sinthe) + costhe*s;
d850 1
a850 1
        r = prj->w[0]*costhe/t;
d853 1
a853 1
        istat = 0;
d867 3
a869 2
              a = s - t;
              b = s + t + 180.0;
d930 1
a931 1
  prj->flag = SZP;
d971 2
a990 2
  int mx, my, rowlen, rowoff, status;
  double a, b, c, d, r2, sinth1, sinth2, sinthe, t, x1, xr, xy, y1, yr, z;
a991 4
  register int ix, iy, *statp;
  register const double *xp, *yp;
  register double *phip, *thetap;

d995 3
a997 1
  if (prj->flag != SZP) {
d1001 1
d1015 5
a1019 5
  xp = x;
  rowoff = 0;
  rowlen = nx*spt;
  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    xr = (*xp + prj->x0)*prj->w[0];
d1021 2
a1022 2
    phip = phi + rowoff;
    for (iy = 0; iy < my; iy++) {
d1030 14
a1043 14
  yp = y;
  phip   = phi;
  thetap = theta;
  statp  = stat;
  for (iy = 0; iy < ny; iy++, yp += sxy) {
    yr = (*yp + prj->y0)*prj->w[0];

    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
      xr = *phip;
      r2 = xr*xr + yr*yr;

      x1 = (xr - prj->w[1])/prj->w[3];
      y1 = (yr - prj->w[2])/prj->w[3];
      xy = xr*x1 + yr*y1;
d1045 1
d1052 5
a1056 5
        t = x1*x1 + y1*y1;
        a = t + 1.0;
        b = xy - t;
        c = r2 - xy - xy + t - 1.0;
        d = b*b - a*c;
d1069 3
a1071 3
        sinth1 = (-b + d)/a;
        sinth2 = (-b - d)/a;
        sinthe = (sinth1 > sinth2) ? sinth1 : sinth2;
a1127 7
  int mphi, mtheta, rowlen, rowoff, status;
  double a, b, cosphi, r, s, sinphi, t, u, v;
  register int iphi, itheta, istat, *statp;
  register const double *phip, *thetap;
  register double *xp, *yp;


d1130 3
a1132 1
  if (prj->flag != SZP) {
d1136 1
d1150 5
a1154 4
  phip = phi;
  rowoff = 0;
  rowlen = nphi*sxy;
  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
d1157 3
a1159 3
    xp = x + rowoff;
    yp = y + rowoff;
    for (itheta = 0; itheta < mtheta; itheta++) {
d1169 7
a1175 7
  thetap = theta;
  xp = x;
  yp = y;
  statp = stat;
  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    s = 1.0 - sind(*thetap);
    t = prj->w[3] - s;
d1178 1
a1178 1
      for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
d1187 3
a1189 3
      r = prj->w[6]*cosd(*thetap)/t;
      u = prj->w[4]*s/t + prj->x0;
      v = prj->w[5]*s/t + prj->y0;
d1191 1
a1191 1
      for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
d1193 1
a1193 1
        istat = 0;
d1208 3
a1210 2
              a = s - t;
              b = s + t + 180.0;
d1255 1
a1256 1
  prj->flag = TAN;
d1273 2
a1292 7
  int mx, my, rowlen, rowoff, status;
  double r, xj, yj, yj2;
  register int ix, iy, *statp;
  register const double *xp, *yp;
  register double *phip, *thetap;


d1295 3
a1297 1
  if (prj->flag != TAN) {
d1301 1
d1315 5
a1319 5
  xp = x;
  rowoff = 0;
  rowlen = nx*spt;
  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    xj = *xp + prj->x0;
d1321 2
a1322 2
    phip = phi + rowoff;
    for (iy = 0; iy < my; iy++) {
d1330 7
a1336 7
  yp = y;
  phip   = phi;
  thetap = theta;
  statp  = stat;
  for (iy = 0; iy < ny; iy++, yp += sxy) {
    yj  = *yp + prj->y0;
    yj2 = yj*yj;
d1338 2
a1339 2
    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
      xj = *phip;
d1341 1
a1341 1
      r = sqrt(xj*xj + yj2);
a1376 7
  int mphi, mtheta, rowlen, rowoff, status;
  double cosphi, r, s, sinphi;
  register int iphi, itheta, istat, *statp;
  register const double *phip, *thetap;
  register double *xp, *yp;


d1379 3
a1381 1
  if (prj->flag != TAN) {
d1385 1
d1399 5
a1403 4
  phip = phi;
  rowoff = 0;
  rowlen = nphi*sxy;
  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
d1406 3
a1408 3
    xp = x + rowoff;
    yp = y + rowoff;
    for (itheta = 0; itheta < mtheta; itheta++) {
d1418 6
a1423 6
  thetap = theta;
  xp = x;
  yp = y;
  statp = stat;
  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    s = sind(*thetap);
d1425 1
a1425 1
      for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
d1433 1
a1433 1
      r =  prj->r0*cosd(*thetap)/s;
d1436 1
a1436 1
      istat = 0;
d1444 1
a1444 1
      for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
d1478 1
a1479 1
  prj->flag = STG;
d1503 2
a1522 7
  int mx, my, rowlen, rowoff, status;
  double r, xj, yj, yj2;
  register int ix, iy, *statp;
  register const double *xp, *yp;
  register double *phip, *thetap;


d1525 3
a1527 1
  if (prj->flag != STG) {
d1531 1
d1543 5
a1547 5
  xp = x;
  rowoff = 0;
  rowlen = nx*spt;
  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    xj = *xp + prj->x0;
d1549 2
a1550 2
    phip = phi + rowoff;
    for (iy = 0; iy < my; iy++) {
d1558 7
a1564 7
  yp = y;
  phip   = phi;
  thetap = theta;
  statp  = stat;
  for (iy = 0; iy < ny; iy++, yp += sxy) {
    yj  = *yp + prj->y0;
    yj2 = yj*yj;
d1566 2
a1567 2
    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
      xj  = *phip;
d1569 1
a1569 1
      r = sqrt(xj*xj + yj2);
a1598 7
  int mphi, mtheta, rowlen, rowoff, status;
  double cosphi, r, s, sinphi;
  register int iphi, itheta, *statp;
  register const double *phip, *thetap;
  register double *xp, *yp;


d1601 3
a1603 1
  if (prj->flag != STG) {
d1607 1
d1621 5
a1625 4
  phip = phi;
  rowoff = 0;
  rowlen = nphi*sxy;
  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
d1628 3
a1630 3
    xp = x + rowoff;
    yp = y + rowoff;
    for (itheta = 0; itheta < mtheta; itheta++) {
d1640 6
a1645 6
  thetap = theta;
  xp = x;
  yp = y;
  statp = stat;
  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    s = 1.0 + sind(*thetap);
d1647 1
a1647 1
      for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
d1655 1
a1655 1
      r = prj->w[0]*cosd(*thetap)/s;
d1657 1
a1657 1
      for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
d1696 1
a1697 1
  prj->flag = SIN;
d1721 2
a1740 1
  int mx, my, rowlen, rowoff, status;
a1741 6
  double a, b, c, d, eta, r2, sinth1, sinth2, sinthe, x0, xi, x1, xy, y0, y02,
         y1, z;
  register int ix, iy, *statp;
  register const double *xp, *yp;
  register double *phip, *thetap;

d1745 3
a1747 1
  if (prj->flag != SIN) {
d1751 2
a1752 2
  xi  = prj->pv[1];
  eta = prj->pv[2];
d1754 1
d1768 5
a1772 5
  xp = x;
  rowoff = 0;
  rowlen = nx*spt;
  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    x0 = (*xp + prj->x0)*prj->w[0];
d1774 2
a1775 2
    phip = phi + rowoff;
    for (iy = 0; iy < my; iy++) {
d1783 7
a1789 7
  yp = y;
  phip   = phi;
  thetap = theta;
  statp  = stat;
  for (iy = 0; iy < ny; iy++, yp += sxy) {
    y0 = (*yp + prj->y0)*prj->w[0];
    y02 = y0*y0;
d1791 1
a1791 1
    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
d1793 2
a1794 2
      x0 = *phip;
      r2 = x0*x0 + y02;
d1816 1
a1816 1
        xy = x0*xi + y0*eta;
d1818 1
d1825 4
a1828 4
          a = prj->w[2];
          b = xy - prj->w[1];
          c = r2 - xy - xy + prj->w[3];
          d = b*b - a*c;
d1841 3
a1843 3
          sinth1 = (-b + d)/a;
          sinth2 = (-b - d)/a;
          sinthe = (sinth1 > sinth2) ? sinth1 : sinth2;
d1870 2
a1871 2
        x1 = -y0 + eta*z;
        y1 =  x0 -  xi*z;
a1906 7
  int mphi, mtheta, rowlen, rowoff, status;
  double cosphi, costhe, sinphi, r, t, z, z1, z2;
  register int iphi, itheta, istat, *statp;
  register const double *phip, *thetap;
  register double *xp, *yp;


d1909 3
a1911 1
  if (prj->flag != SIN) {
d1915 1
d1929 5
a1933 4
  phip = phi;
  rowoff = 0;
  rowlen = nphi*sxy;
  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
d1936 3
a1938 3
    xp = x + rowoff;
    yp = y + rowoff;
    for (itheta = 0; itheta < mtheta; itheta++) {
d1948 8
a1955 6
  thetap = theta;
  xp = x;
  yp = y;
  statp = stat;
  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    t = (90.0 - fabs(*thetap))*D2R;
d1967 1
a1967 1
    r = prj->r0*costhe;
d1971 1
a1971 1
      istat = 0;
d1979 1
a1979 1
      for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
d1988 2
a1989 2
      z1 = prj->pv[1]*z - prj->x0;
      z2 = prj->pv[2]*z - prj->y0;
d1991 2
a1992 2
      for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
        istat = 0;
d2034 1
a2035 1
  prj->flag = ARC;
d2059 2
a2078 7
  int mx, my, rowlen, rowoff, status;
  double r, xj, yj, yj2;
  register int ix, iy, *statp;
  register const double *xp, *yp;
  register double *phip, *thetap;


d2081 3
a2083 1
  if (prj->flag != ARC) {
d2087 1
d2101 5
a2105 5
  xp = x;
  rowoff = 0;
  rowlen = nx*spt;
  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    xj = *xp + prj->x0;
d2107 2
a2108 2
    phip = phi + rowoff;
    for (iy = 0; iy < my; iy++) {
d2116 7
a2122 7
  yp = y;
  phip   = phi;
  thetap = theta;
  statp  = stat;
  for (iy = 0; iy < ny; iy++, yp += sxy) {
    yj  = *yp + prj->y0;
    yj2 = yj*yj;
d2124 2
a2125 2
    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
      xj = *phip;
d2127 1
a2127 1
      r = sqrt(xj*xj + yj2);
a2163 7
  int mphi, mtheta, rowlen, rowoff, status;
  double cosphi, r, sinphi;
  register int iphi, itheta, *statp;
  register const double *phip, *thetap;
  register double *xp, *yp;


d2166 3
a2168 1
  if (prj->flag != ARC) {
d2172 1
d2184 5
a2188 4
  phip = phi;
  rowoff = 0;
  rowlen = nphi*sxy;
  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
d2191 3
a2193 3
    xp = x + rowoff;
    yp = y + rowoff;
    for (itheta = 0; itheta < mtheta; itheta++) {
d2203 6
a2208 6
  thetap = theta;
  xp = x;
  yp = y;
  statp = stat;
  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    r =  prj->w[0]*(90.0 - *thetap);
d2210 1
a2210 1
    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
a2245 2
  int j, k, m;
  double d, d1, d2, r, zd, zd1, zd2;
d2249 1
a2251 1
  prj->flag = ZPN;
d2268 1
d2282 3
a2284 2
    zd1 = 0.0;
    d1  = prj->pv[1];
d2290 4
d2297 1
a2297 1
      for (m = k; m > 0; m--) {
d2316 1
a2316 1
        for (m = k; m > 0; m--) {
d2332 2
a2333 2
    r = 0.0;
    for (m = k; m >= 0; m--) {
d2343 2
a2362 2
  int j, k, m, mx, my, rowlen, rowoff, status;
  double a, b, c, d, lambda, r, r1, r2, rt, xj, yj, yj2, zd, zd1, zd2;
a2363 4
  register int ix, iy, *statp;
  register const double *xp, *yp;
  register double *phip, *thetap;

d2367 3
a2369 1
  if (prj->flag != ZPN) {
d2373 1
a2373 1
  k = prj->n;
d2375 1
d2389 5
a2393 5
  xp = x;
  rowoff = 0;
  rowlen = nx*spt;
  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    xj = *xp + prj->x0;
d2395 2
a2396 2
    phip = phi + rowoff;
    for (iy = 0; iy < my; iy++) {
d2404 7
a2410 7
  yp = y;
  phip   = phi;
  thetap = theta;
  statp  = stat;
  for (iy = 0; iy < ny; iy++, yp += sxy) {
    yj  = *yp + prj->y0;
    yj2 = yj*yj;
d2412 2
a2413 2
    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
      xj = *phip;
d2415 1
a2415 1
      r = sqrt(xj*xj + yj2)/prj->r0;
d2422 1
d2433 3
a2435 3
        a = prj->pv[2];
        b = prj->pv[1];
        c = prj->pv[0] - r;
d2437 1
a2437 1
        d = b*b - 4.0*a*c;
d2447 3
a2449 2
        zd1 = (-b + d)/(2.0*a);
        zd2 = (-b - d)/(2.0*a);
d2471 4
a2474 4
        zd1 = 0.0;
        r1  = prj->pv[0];
        zd2 = prj->w[0];
        r2  = prj->w[1];
d2494 2
a2495 2
          for (j = 0; j < 100; j++) {
            lambda = (r2 - r)/(r2 - r1);
d2504 2
a2505 2
            rt = 0.0;
            for (m = k; m >= 0; m--) {
a2552 7
  int m, mphi, mtheta, rowlen, rowoff, status;
  double cosphi, r, s, sinphi;
  register int iphi, itheta, istat, *statp;
  register const double *phip, *thetap;
  register double *xp, *yp;


d2555 3
a2557 1
  if (prj->flag != ZPN) {
d2561 1
d2575 5
a2579 4
  phip = phi;
  rowoff = 0;
  rowlen = nphi*sxy;
  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
d2582 3
a2584 3
    xp = x + rowoff;
    yp = y + rowoff;
    for (itheta = 0; itheta < mtheta; itheta++) {
d2594 6
a2599 6
  thetap = theta;
  xp = x;
  yp = y;
  statp = stat;
  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    s = (90.0 - *thetap)*D2R;
d2601 2
a2602 2
    r = 0.0;
    for (m = prj->n; m >= 0; m--) {
d2608 1
a2608 1
    istat = 0;
d2616 1
a2616 1
    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
d2649 1
a2650 1
  prj->flag = ZEA;
d2674 2
a2693 2
  int mx, my, rowlen, rowoff, status;
  double r, s, xj, yj, yj2;
a2694 4
  register int ix, iy, *statp;
  register const double *xp, *yp;
  register double *phip, *thetap;

d2698 3
a2700 1
  if (prj->flag != ZEA) {
d2704 1
d2718 5
a2722 5
  xp = x;
  rowoff = 0;
  rowlen = nx*spt;
  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    xj = *xp + prj->x0;
d2724 2
a2725 2
    phip = phi + rowoff;
    for (iy = 0; iy < my; iy++) {
d2733 7
a2739 7
  yp = y;
  phip   = phi;
  thetap = theta;
  statp  = stat;
  for (iy = 0; iy < ny; iy++, yp += sxy) {
    yj  = *yp + prj->y0;
    yj2 = yj*yj;
d2741 2
a2742 2
    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
      xj  = *phip;
d2744 1
a2744 1
      r = sqrt(xj*xj + yj2);
d2751 1
a2751 1
      s = r*prj->w[1];
a2792 7
  int mphi, mtheta, rowlen, rowoff, status;
  double cosphi, r, sinphi;
  register int iphi, itheta, *statp;
  register const double *phip, *thetap;
  register double *xp, *yp;


d2795 3
a2797 1
  if (prj->flag != ZEA) {
d2801 1
d2813 5
a2817 4
  phip = phi;
  rowoff = 0;
  rowlen = nphi*sxy;
  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
d2820 3
a2822 3
    xp = x + rowoff;
    yp = y + rowoff;
    for (itheta = 0; itheta < mtheta; itheta++) {
d2832 6
a2837 6
  thetap = theta;
  xp = x;
  yp = y;
  statp = stat;
  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    r =  prj->w[0]*sind((90.0 - *thetap)/2.0);
d2839 1
a2839 1
    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
a2881 1
  double cosxi;
d2884 1
a2885 1
  prj->flag = AIR;
d2905 1
a2905 1
    cosxi = cosd((90.0 - prj->pv[1])/2.0);
d2920 2
a2939 2
  int k, mx, my, rowlen, rowoff, status;
  double cosxi, lambda, r, r1, r2, rt, tanxi, x1, x2, xi, xj, yj, yj2;
a2940 4
  register int ix, iy, *statp;
  register const double *xp, *yp;
  register double *phip, *thetap;

d2944 3
a2946 1
  if (prj->flag != AIR) {
d2950 1
d2964 5
a2968 5
  xp = x;
  rowoff = 0;
  rowlen = nx*spt;
  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    xj = *xp + prj->x0;
d2970 2
a2971 2
    phip = phi + rowoff;
    for (iy = 0; iy < my; iy++) {
d2979 7
a2985 7
  yp = y;
  phip   = phi;
  thetap = theta;
  statp  = stat;
  for (iy = 0; iy < ny; iy++, yp += sxy) {
    yj  = *yp + prj->y0;
    yj2 = yj*yj;
d2987 2
a2988 2
    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
      xj = *phip;
d2990 1
a2990 1
      r = sqrt(xj*xj + yj2)/prj->w[0];
d2997 1
a2997 1

d3004 6
a3009 2
        x1 = x2 = 1.0;
        r1 = r2 = 0.0;
d3012 1
a3012 1
          tanxi = sqrt(1.0-x2*x2)/x2;
d3026 1
d3029 1
a3029 1
          lambda = (r2-r)/(r2-r1);
d3037 2
a3038 2
          tanxi = sqrt(1.0-cosxi*cosxi)/cosxi;
          rt = -(log(cosxi)/tanxi + prj->w[1]*tanxi);
a3088 7
  int mphi, mtheta, rowlen, rowoff, status;
  double cosphi, cosxi, r, tanxi, xi, sinphi;
  register int iphi, itheta, istat, *statp;
  register const double *phip, *thetap;
  register double *xp, *yp;


d3091 3
a3093 1
  if (prj->flag != AIR) {
d3097 1
d3111 5
a3115 4
  phip = phi;
  rowoff = 0;
  rowlen = nphi*sxy;
  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
d3118 3
a3120 3
    xp = x + rowoff;
    yp = y + rowoff;
    for (itheta = 0; itheta < mtheta; itheta++) {
d3130 6
a3135 6
  thetap = theta;
  xp = x;
  yp = y;
  statp = stat;
  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    istat = 0;
d3137 1
d3141 1
a3141 1
      xi = D2R*(90.0 - *thetap)/2.0;
d3145 2
a3146 2
        cosxi = cosd((90.0 - *thetap)/2.0);
        tanxi = sqrt(1.0 - cosxi*cosxi)/cosxi;
d3155 1
a3155 1
    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
d3196 1
a3197 1
  prj->flag = CYP;
d3247 2
a3266 7
  int mx, my, rowlen, rowoff, status;
  double eta, s, t;
  register int ix, iy, *statp;
  register const double *xp, *yp;
  register double *phip, *thetap;


d3269 3
a3271 1
  if (prj->flag != CYP) {
d3275 1
d3289 5
a3293 5
  xp = x;
  rowoff = 0;
  rowlen = nx*spt;
  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    s = prj->w[1]*(*xp + prj->x0);
d3295 2
a3296 2
    phip = phi + rowoff;
    for (iy = 0; iy < my; iy++) {
d3304 6
a3309 6
  yp = y;
  thetap = theta;
  statp = stat;
  for (iy = 0; iy < ny; iy++, yp += sxy) {
    eta = prj->w[3]*(*yp + prj->y0);
    t = atan2d(eta,1.0) + asind(eta*prj->pv[1]/sqrt(eta*eta+1.0));
d3311 1
a3311 1
    for (ix = 0; ix < mx; ix++, thetap += spt, statp++) {
a3340 7
  int mphi, mtheta, rowlen, rowoff, status;
  double eta, xi;
  register int iphi, itheta, istat, *statp;
  register const double *phip, *thetap;
  register double *xp, *yp;


d3343 3
a3345 1
  if (prj->flag != CYP) {
d3349 1
d3363 5
a3367 5
  phip = phi;
  rowoff = 0;
  rowlen = nphi*sxy;
  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    xi = prj->w[0]*(*phip) - prj->x0;
d3369 2
a3370 2
    xp = x + rowoff;
    for (itheta = 0; itheta < mtheta; itheta++) {
d3378 5
a3382 5
  thetap = theta;
  yp = y;
  statp = stat;
  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    eta = prj->pv[1] + cosd(*thetap);
d3384 1
a3384 1
    istat = 0;
d3394 1
a3394 1
    for (iphi = 0; iphi < mphi; iphi++, yp += sxy, statp++) {
d3432 1
a3433 1
  prj->flag = CEA;
d3469 2
a3488 2
  int mx, my, rowlen, rowoff, status;
  double s;
a3489 4
  register int istat, ix, iy, *statp;
  register const double *xp, *yp;
  register double *phip, *thetap;

d3493 3
a3495 1
  if (prj->flag != CEA) {
d3499 1
d3513 5
a3517 5
  xp = x;
  rowoff = 0;
  rowlen = nx*spt;
  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    s = prj->w[1]*(*xp + prj->x0);
d3519 2
a3520 2
    phip = phi + rowoff;
    for (iy = 0; iy < my; iy++) {
d3528 5
a3532 5
  yp = y;
  thetap = theta;
  statp = stat;
  for (iy = 0; iy < ny; iy++, yp += sxy) {
    s = prj->w[3]*(*yp + prj->y0);
d3534 1
a3534 1
    istat = 0;
d3547 1
a3547 1
    for (ix = 0; ix < mx; ix++, thetap += spt, statp++) {
a3576 7
  int mphi, mtheta, rowlen, rowoff, status;
  double eta, xi;
  register int iphi, itheta, *statp;
  register const double *phip, *thetap;
  register double *xp, *yp;


d3579 3
a3581 1
  if (prj->flag != CEA) {
d3585 1
d3597 5
a3601 5
  phip = phi;
  rowoff = 0;
  rowlen = nphi*sxy;
  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    xi = prj->w[0]*(*phip) - prj->x0;
d3603 2
a3604 2
    xp = x + rowoff;
    for (itheta = 0; itheta < mtheta; itheta++) {
d3612 5
a3616 5
  thetap = theta;
  yp = y;
  statp = stat;
  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    eta = prj->w[2]*sind(*thetap) - prj->y0;
d3618 1
a3618 1
    for (iphi = 0; iphi < mphi; iphi++, yp += sxy, statp++) {
d3650 1
a3651 1
  prj->flag = CAR;
d3675 2
a3694 7
  int mx, my, rowlen, rowoff, status;
  double s, t;
  register int ix, iy, *statp;
  register const double *xp, *yp;
  register double *phip, *thetap;


d3697 3
a3699 1
  if (prj->flag != CAR) {
d3703 1
d3717 5
a3721 5
  xp = x;
  rowoff = 0;
  rowlen = nx*spt;
  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    s = prj->w[1]*(*xp + prj->x0);
d3723 2
a3724 2
    phip = phi + rowoff;
    for (iy = 0; iy < my; iy++) {
d3732 5
a3736 5
  yp = y;
  thetap = theta;
  statp = stat;
  for (iy = 0; iy < ny; iy++, yp += sxy) {
    t = prj->w[1]*(*yp + prj->y0);
d3738 1
a3738 1
    for (ix = 0; ix < mx; ix++, thetap += spt, statp++) {
a3767 7
  int mphi, mtheta, rowlen, rowoff, status;
  double eta, xi;
  register int iphi, itheta, *statp;
  register const double *phip, *thetap;
  register double *xp, *yp;


d3770 3
a3772 1
  if (prj->flag != CAR) {
d3776 1
d3788 5
a3792 5
  phip = phi;
  rowoff = 0;
  rowlen = nphi*sxy;
  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    xi = prj->w[0]*(*phip) - prj->x0;
d3794 2
a3795 2
    xp = x + rowoff;
    for (itheta = 0; itheta < mtheta; itheta++) {
d3803 5
a3807 5
  thetap = theta;
  yp = y;
  statp = stat;
  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    eta = prj->w[0]*(*thetap) - prj->y0;
d3809 1
a3809 1
    for (iphi = 0; iphi < mphi; iphi++, yp += sxy, statp++) {
d3841 1
a3842 1
  prj->flag = MER;
d3866 2
a3885 7
  int mx, my, rowlen, rowoff, status;
  double s, t;
  register int ix, iy, *statp;
  register const double *xp, *yp;
  register double *phip, *thetap;


d3888 3
a3890 1
  if (prj->flag != MER) {
d3894 1
d3908 5
a3912 5
  xp = x;
  rowoff = 0;
  rowlen = nx*spt;
  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    s = prj->w[1]*(*xp + prj->x0);
d3914 2
a3915 2
    phip = phi + rowoff;
    for (iy = 0; iy < my; iy++) {
d3923 5
a3927 5
  yp = y;
  thetap = theta;
  statp  = stat;
  for (iy = 0; iy < ny; iy++, yp += sxy) {
    t = 2.0*atand(exp((*yp + prj->y0)/prj->r0)) - 90.0;
d3929 1
a3929 1
    for (ix = 0; ix < mx; ix++, thetap += spt, statp++) {
a3958 7
  int mphi, mtheta, rowlen, rowoff, status;
  double eta, xi;
  register int iphi, itheta, istat, *statp;
  register const double *phip, *thetap;
  register double *xp, *yp;


d3961 3
a3963 1
  if (prj->flag != MER) {
d3967 1
d3981 5
a3985 5
  phip = phi;
  rowoff = 0;
  rowlen = nphi*sxy;
  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    xi  = prj->w[0]*(*phip) - prj->x0;
d3987 2
a3988 2
    xp = x + rowoff;
    for (itheta = 0; itheta < mtheta; itheta++) {
d3996 5
a4000 5
  thetap = theta;
  yp = y;
  statp = stat;
  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    istat = 0;
d4002 1
d4011 1
a4011 1
    for (iphi = 0; iphi < mphi; iphi++, yp += sxy, statp++) {
d4043 1
a4044 1
  prj->flag = SFL;
d4068 2
a4087 7
  int mx, my, rowlen, rowoff, status;
  double s, t, yj;
  register int istat, ix, iy, *statp;
  register const double *xp, *yp;
  register double *phip, *thetap;


d4090 3
a4092 1
  if (prj->flag != SFL) {
d4096 1
d4110 5
a4114 5
  xp = x;
  rowoff = 0;
  rowlen = nx*spt;
  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    s = prj->w[1]*(*xp + prj->x0);
d4116 2
a4117 2
    phip = phi + rowoff;
    for (iy = 0; iy < my; iy++) {
d4125 7
a4131 7
  yp = y;
  phip   = phi;
  thetap = theta;
  statp  = stat;
  for (iy = 0; iy < ny; iy++, yp += sxy) {
    yj = *yp + prj->y0;
    s = cos(yj/prj->r0);
d4133 1
a4133 1
    istat = 0;
d4141 1
a4141 1
    t = prj->w[1]*yj;
d4143 1
a4143 1
    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
a4173 7
  int mphi, mtheta, rowlen, rowoff, status;
  double eta, xi;
  register int iphi, itheta, *statp;
  register const double *phip, *thetap;
  register double *xp, *yp;


d4176 3
a4178 1
  if (prj->flag != SFL) {
d4182 1
d4194 5
a4198 5
  phip = phi;
  rowoff = 0;
  rowlen = nphi*sxy;
  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    xi = prj->w[0]*(*phip);
d4200 2
a4201 2
    xp = x + rowoff;
    for (itheta = 0; itheta < mtheta; itheta++) {
d4209 7
a4215 7
  thetap = theta;
  xp = x;
  yp = y;
  statp = stat;
  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    xi  = cosd(*thetap);
    eta = prj->w[0]*(*thetap) - prj->y0;
d4217 1
a4217 1
    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
d4252 1
a4253 1
  prj->flag = PAR;
d4281 2
a4300 2
  int mx, my, rowlen, rowoff, status;
  double r, s, t, xj;
a4301 4
  register int istat, ix, iy, *statp;
  register const double *xp, *yp;
  register double *phip, *thetap;

d4305 3
a4307 1
  if (prj->flag != PAR) {
d4311 1
d4325 11
a4335 11
  xp = x;
  rowoff = 0;
  rowlen = nx*spt;
  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    xj = *xp + prj->x0;
    s = prj->w[1]*xj;
    t = fabs(xj) - tol;

    phip   = phi   + rowoff;
    thetap = theta + rowoff;
    for (iy = 0; iy < my; iy++) {
d4345 6
a4350 6
  yp = y;
  phip   = phi;
  thetap = theta;
  statp  = stat;
  for (iy = 0; iy < ny; iy++, yp += sxy) {
    r = prj->w[3]*(*yp + prj->y0);
d4352 2
a4353 1
    istat = 0;
d4372 1
a4372 1
    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
a4412 7
  int mphi, mtheta, rowlen, rowoff, status;
  double eta, s, xi;
  register int iphi, itheta, *statp;
  register const double *phip, *thetap;
  register double *xp, *yp;


d4415 3
a4417 1
  if (prj->flag != PAR) {
d4421 1
d4433 5
a4437 5
  phip = phi;
  rowoff = 0;
  rowlen = nphi*sxy;
  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    xi = prj->w[0]*(*phip);
d4439 2
a4440 2
    xp = x + rowoff;
    for (itheta = 0; itheta < mtheta; itheta++) {
d4448 8
a4455 8
  thetap = theta;
  xp = x;
  yp = y;
  statp = stat;
  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    s = sind((*thetap)/3.0);
    xi = (1.0 - 4.0*s*s);
    eta = prj->w[2]*s - prj->y0;
d4457 1
a4457 1
    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
d4492 1
a4493 1
  prj->flag = MOL;
d4516 2
a4535 2
  int mx, my, rowlen, rowoff, status;
  double r, s, t, xj, y0, yj, z;
a4536 4
  register int istat, ix, iy, *statp;
  register const double *xp, *yp;
  register double *phip, *thetap;

d4540 3
a4542 1
  if (prj->flag != MOL) {
d4546 1
d4560 11
a4570 11
  xp = x;
  rowoff = 0;
  rowlen = nx*spt;
  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    xj = *xp + prj->x0;
    s = prj->w[3]*xj;
    t = fabs(xj) - tol;

    phip   = phi   + rowoff;
    thetap = theta + rowoff;
    for (iy = 0; iy < my; iy++) {
d4580 8
a4587 8
  yp = y;
  phip   = phi;
  thetap = theta;
  statp  = stat;
  for (iy = 0; iy < ny; iy++, yp += sxy) {
    yj = *yp + prj->y0;
    y0 = yj/prj->r0;
    r  = 2.0 - y0*y0;
d4589 2
a4590 1
    istat = 0;
d4608 1
a4608 1
    z = yj*prj->w[2];
d4631 1
a4631 1
    t = asind(z);
d4633 1
a4633 1
    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
a4673 2
  int k, mphi, mtheta, rowlen, rowoff, status;
  double eta, gamma, resid, u, v, v0, v1, xi;
a4674 4
  register int iphi, itheta, *statp;
  register const double *phip, *thetap;
  register double *xp, *yp;

d4678 3
a4680 1
  if (prj->flag != MOL) {
d4684 1
d4696 5
a4700 5
  phip = phi;
  rowoff = 0;
  rowlen = nphi*sxy;
  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    xi = prj->w[1]*(*phip);
d4702 2
a4703 2
    xp = x + rowoff;
    for (itheta = 0; itheta < mtheta; itheta++) {
d4711 7
a4717 5
  thetap = theta;
  xp = x;
  yp = y;
  statp = stat;
  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
d4727 6
a4732 6
      u  = PI*sind(*thetap);
      v0 = -PI;
      v1 =  PI;
      v  = u;
      for (k = 0; k < 100; k++) {
        resid = (v - u) + sin(v);
d4743 1
a4743 1
      gamma = v/2.0;
d4749 1
a4749 1
    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
d4784 1
a4785 1
  prj->flag = AIT;
d4807 2
a4826 2
  int mx, my, rowlen, rowoff, status;
  double s, t, x0, xj, y0, yj, yj2, z;
a4827 4
  register int ix, iy, istat, *statp;
  register const double *xp, *yp;
  register double *phip, *thetap;

d4831 3
a4833 1
  if (prj->flag != AIT) {
d4837 1
d4851 11
a4861 11
  xp = x;
  rowoff = 0;
  rowlen = nx*spt;
  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    xj = *xp + prj->x0;
    s  = 1.0 - xj*xj*prj->w[2];
    t  = xj*prj->w[3];

    phip   = phi   + rowoff;
    thetap = theta + rowoff;
    for (iy = 0; iy < my; iy++) {
d4871 7
a4877 7
  yp = y;
  phip   = phi;
  thetap = theta;
  statp  = stat;
  for (iy = 0; iy < ny; iy++, yp += sxy) {
    yj  = *yp + prj->y0;
    yj2 = yj*yj*prj->w[1];
d4879 2
a4880 2
    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
      s = *phip - yj2;
d4882 1
a4882 1
      istat = 0;
d4892 3
a4894 3
      z = sqrt(s);
      x0 = 2.0*z*z - 1.0;
      y0 = z*(*thetap);
d4901 1
a4901 1
      t = z*yj/prj->r0;
a4941 7
  int mphi, mtheta, rowlen, rowoff, status;
  double cosphi, costhe, sinphi, sinthe, w;
  register int iphi, itheta, *statp;
  register const double *phip, *thetap;
  register double *xp, *yp;


d4944 3
a4946 1
  if (prj->flag != AIT) {
d4950 1
d4962 6
a4967 5
  phip = phi;
  rowoff = 0;
  rowlen = nphi*sxy;
  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    w = (*phip)/2.0;
d4970 3
a4972 3
    xp = x + rowoff;
    yp = y + rowoff;
    for (itheta = 0; itheta < mtheta; itheta++) {
d4982 6
a4987 5
  thetap = theta;
  xp = x;
  yp = y;
  statp = stat;
  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
d4990 2
a4991 2
    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
      w = sqrt(prj->w[0]/(1.0 + costhe*(*yp)));
d5033 1
a5034 1
  prj->flag = COP;
a5035 1
  strcpy(prj->name, "conic perspective");
d5043 1
d5072 2
a5091 6
  int mx, my, rowlen, rowoff, status;
  double alpha, dy, dy2, r, xj;
  register int ix, iy, *statp;
  register const double *xp, *yp;
  register double *phip, *thetap;

d5094 3
a5096 1
  if (prj->flag != COP) {
d5100 1
d5114 5
a5118 5
  xp = x;
  rowoff = 0;
  rowlen = nx*spt;
  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    xj = *xp + prj->x0;
d5120 2
a5121 2
    phip = phi + rowoff;
    for (iy = 0; iy < my; iy++) {
d5129 7
a5135 7
  yp = y;
  phip   = phi;
  thetap = theta;
  statp  = stat;
  for (iy = 0; iy < ny; iy++, yp += sxy) {
    dy  = prj->w[2] - (*yp + prj->y0);
    dy2 = dy*dy;
d5137 2
a5138 2
    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
      xj = *phip;
d5140 1
a5140 1
      r = sqrt(xj*xj + dy2);
d5143 1
a5179 6
  int mphi, mtheta, rowlen, rowoff, status;
  double alpha, cosalpha, r, s, t, sinalpha, y0;
  register int iphi, itheta, istat, *statp;
  register const double *phip, *thetap;
  register double *xp, *yp;

d5182 3
a5184 1
  if (prj->flag != COP) {
d5188 1
d5202 6
a5207 5
  phip = phi;
  rowoff = 0;
  rowlen = nphi*sxy;
  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    alpha = prj->w[0]*(*phip);
d5210 3
a5212 3
    xp = x + rowoff;
    yp = y + rowoff;
    for (itheta = 0; itheta < mtheta; itheta++) {
d5222 8
a5229 8
  thetap = theta;
  xp = x;
  yp = y;
  statp = stat;
  y0 = prj->y0 - prj->w[2];
  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    t = *thetap - prj->pv[1];
    s = cosd(t);
d5231 2
a5232 1
    istat = 0;
d5263 1
a5263 1
    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
a5306 2
  double theta1, theta2;

d5308 1
a5309 1
  prj->flag = COE;
a5310 1
  strcpy(prj->name, "conic equal area");
d5318 1
d5327 2
a5328 2
  theta1 = prj->pv[1] - prj->pv[2];
  theta2 = prj->pv[1] + prj->pv[2];
d5349 2
a5368 2
  int mx, my, rowlen, rowoff, status;
  double alpha, dy, dy2, r, t, w, xj;
a5369 3
  register int ix, iy, istat, *statp;
  register const double *xp, *yp;
  register double *phip, *thetap;
d5373 3
a5375 1
  if (prj->flag != COE) {
d5379 1
d5393 5
a5397 5
  xp = x;
  rowoff = 0;
  rowlen = nx*spt;
  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    xj = *xp + prj->x0;
d5399 2
a5400 2
    phip = phi + rowoff;
    for (iy = 0; iy < my; iy++) {
d5408 7
a5414 7
  yp = y;
  phip   = phi;
  thetap = theta;
  statp  = stat;
  for (iy = 0; iy < ny; iy++, yp += sxy) {
    dy  = prj->w[2] - (*yp + prj->y0);
    dy2 = dy*dy;
d5416 2
a5417 2
    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
      xj = *phip;
d5419 1
a5419 1
      r = sqrt(xj*xj + dy2);
d5422 1
d5429 2
a5430 1
      istat = 0;
d5434 1
a5434 1
        w = (prj->w[6] - r*r)*prj->w[7];
a5479 6
  int mphi, mtheta, rowlen, rowoff, status;
  double alpha, cosalpha, r, sinalpha, y0;
  register int iphi, itheta, *statp;
  register const double *phip, *thetap;
  register double *xp, *yp;

d5482 3
a5484 1
  if (prj->flag != COE) {
d5488 1
d5500 6
a5505 5
  phip = phi;
  rowoff = 0;
  rowlen = nphi*sxy;
  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    alpha = prj->w[0]*(*phip);
d5508 3
a5510 3
    xp = x + rowoff;
    yp = y + rowoff;
    for (itheta = 0; itheta < mtheta; itheta++) {
d5520 7
a5526 6
  thetap = theta;
  xp = x;
  yp = y;
  statp = stat;
  y0 = prj->y0 - prj->w[2];
  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
d5533 1
a5533 1
    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
d5573 1
a5574 1
  prj->flag = COD;
a5575 1
  strcpy(prj->name, "conic equidistant");
d5583 1
d5609 2
a5628 6
  int mx, my, rowlen, rowoff, status;
  double alpha, dy, dy2, r, xj;
  register int ix, iy, *statp;
  register const double *xp, *yp;
  register double *phip, *thetap;

d5631 3
a5633 1
  if (prj->flag != COD) {
d5637 1
d5651 5
a5655 5
  xp = x;
  rowoff = 0;
  rowlen = nx*spt;
  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    xj = *xp + prj->x0;
d5657 2
a5658 2
    phip = phi + rowoff;
    for (iy = 0; iy < my; iy++) {
d5666 7
a5672 7
  yp = y;
  phip   = phi;
  thetap = theta;
  statp  = stat;
  for (iy = 0; iy < ny; iy++, yp += sxy) {
    dy  = prj->w[2] - (*yp + prj->y0);
    dy2 = dy*dy;
d5674 2
a5675 2
    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
      xj = *phip;
d5677 1
a5677 1
      r = sqrt(xj*xj + dy2);
d5680 1
a5716 6
  int mphi, mtheta, rowlen, rowoff, status;
  double alpha, cosalpha, r, sinalpha, y0;
  register int iphi, itheta, *statp;
  register const double *phip, *thetap;
  register double *xp, *yp;

d5719 3
a5721 1
  if (prj->flag != COD) {
d5725 1
d5737 6
a5742 5
  phip = phi;
  rowoff = 0;
  rowlen = nphi*sxy;
  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    alpha = prj->w[0]*(*phip);
d5745 3
a5747 3
    xp = x + rowoff;
    yp = y + rowoff;
    for (itheta = 0; itheta < mtheta; itheta++) {
d5757 7
a5763 7
  thetap = theta;
  xp = x;
  yp = y;
  statp = stat;
  y0 = prj->y0 - prj->w[2];
  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    r = prj->w[3] - *thetap;
d5765 1
a5765 1
    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
a5806 2
  double cos1, cos2, tan1, tan2, theta1, theta2;

d5808 1
a5809 1
  prj->flag = COO;
a5810 1
  strcpy(prj->name, "conic orthomorphic");
d5818 1
d5827 2
a5828 2
  theta1 = prj->pv[1] - prj->pv[2];
  theta2 = prj->pv[1] + prj->pv[2];
d5830 2
a5831 2
  tan1 = tand((90.0 - theta1)/2.0);
  cos1 = cosd(theta1);
d5836 2
a5837 2
    tan2 = tand((90.0 - theta2)/2.0);
    cos2 = cosd(theta2);
d5856 2
a5875 6
  int mx, my, rowlen, rowoff, status;
  double alpha, dy, dy2, r, t, xj;
  register int ix, iy, istat, *statp;
  register const double *xp, *yp;
  register double *phip, *thetap;

d5878 3
a5880 1
  if (prj->flag != COO) {
d5884 1
d5898 5
a5902 5
  xp = x;
  rowoff = 0;
  rowlen = nx*spt;
  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    xj = *xp + prj->x0;
d5904 2
a5905 2
    phip = phi + rowoff;
    for (iy = 0; iy < my; iy++) {
d5913 7
a5919 7
  yp = y;
  phip   = phi;
  thetap = theta;
  statp  = stat;
  for (iy = 0; iy < ny; iy++, yp += sxy) {
    dy  = prj->w[2] - (*yp + prj->y0);
    dy2 = dy*dy;
d5921 2
a5922 2
    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
      xj = *phip;
d5924 1
a5924 1
      r = sqrt(xj*xj + dy2);
d5927 1
d5934 2
a5935 1
      istat = 0;
a5977 6
  int mphi, mtheta, rowlen, rowoff, status;
  double alpha, cosalpha, r, sinalpha, y0;
  register int iphi, itheta, istat, *statp;
  register const double *phip, *thetap;
  register double *xp, *yp;

d5980 3
a5982 1
  if (prj->flag != COO) {
d5986 1
d6000 6
a6005 5
  phip = phi;
  rowoff = 0;
  rowlen = nphi*sxy;
  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    alpha = prj->w[0]*(*phip);
d6008 3
a6010 3
    xp = x + rowoff;
    yp = y + rowoff;
    for (itheta = 0; itheta < mtheta; itheta++) {
d6020 7
a6026 7
  thetap = theta;
  xp = x;
  yp = y;
  statp = stat;
  y0 = prj->y0 - prj->w[2];
  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    istat = 0;
d6028 1
d6039 1
a6039 1
    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
d6075 1
a6076 1
  prj->flag = BON;
a6077 1
  strcpy(prj->name, "Bonne's");
d6088 1
d6109 2
a6128 7
  int mx, my, rowlen, rowoff, status;
  double alpha, dy, dy2, costhe, r, s, t, xj;
  register int ix, iy, *statp;
  register const double *xp, *yp;
  register double *phip, *thetap;


d6136 2
a6137 1
  if (prj->flag != BON) {
d6141 1
d6155 5
a6159 5
  xp = x;
  rowoff = 0;
  rowlen = nx*spt;
  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    xj = *xp + prj->x0;
d6161 2
a6162 2
    phip = phi + rowoff;
    for (iy = 0; iy < my; iy++) {
d6170 7
a6176 7
  yp = y;
  phip   = phi;
  thetap = theta;
  statp  = stat;
  for (iy = 0; iy < ny; iy++, yp += sxy) {
    dy  = prj->w[2] - (*yp + prj->y0);
    dy2 = dy*dy;
d6178 2
a6179 2
    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
      xj = *phip;
d6181 1
a6181 1
      r = sqrt(xj*xj + dy2);
d6184 1
d6191 3
a6193 2
      t = (prj->w[2] - r)/prj->w[1];
      costhe = cosd(t);
a6229 6
  int mphi, mtheta, rowlen, rowoff, status;
  double alpha, cosalpha, r, s, sinalpha, y0;
  register int iphi, itheta, *statp;
  register const double *phip, *thetap;
  register double *xp, *yp;

d6237 2
a6238 1
  if (prj->flag != BON) {
d6242 1
a6251 2
  y0 = prj->y0 - prj->w[2];

d6254 5
a6258 5
  phip = phi;
  rowoff = 0;
  rowlen = nphi*sxy;
  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    s = prj->r0*(*phip);
d6260 2
a6261 2
    xp = x + rowoff;
    for (itheta = 0; itheta < mtheta; itheta++) {
d6269 12
a6280 10
  thetap = theta;
  xp = x;
  yp = y;
  statp = stat;
  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    r = prj->w[2] - prj->w[1]*(*thetap);
    s = cosd(*thetap)/r;

    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
      alpha = s*(*xp);
d6316 1
a6317 1
  prj->flag = PCO;
d6344 2
a6363 3
  int mx, my, rowlen, rowoff, status;
  double f, fneg, fpos, lambda, tanthe, the, theneg, thepos, w, x1, xj, xx,
         yj, ymthe, y1;
a6364 4
  register int ix, iy, k, *statp;
  register const double *xp, *yp;
  register double *phip, *thetap;

d6368 3
a6370 1
  if (prj->flag != PCO) {
d6374 1
d6388 5
a6392 5
  xp = x;
  rowoff = 0;
  rowlen = nx*spt;
  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    xj = *xp + prj->x0;
d6394 2
a6395 2
    phip = phi + rowoff;
    for (iy = 0; iy < my; iy++) {
d6403 7
a6409 7
  yp = y;
  phip   = phi;
  thetap = theta;
  statp  = stat;
  for (iy = 0; iy < ny; iy++, yp += sxy) {
    yj = *yp + prj->y0;
    w  = fabs(yj*prj->w[1]);
d6411 2
a6412 2
    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
      xj = *phip;
d6423 1
d6432 2
a6433 2
          thepos = yj / prj->w[0];
          theneg = 0.0;
d6436 3
a6438 3
          xx = xj*xj;
          fpos  =  xx;
          fneg  = -xx;
d6440 1
a6440 1
          for (k = 0; k < 64; k++) {
d6442 1
a6442 1
            lambda = fpos/(fpos-fneg);
d6453 1
a6453 1
            f = xx + ymthe*(ymthe - prj->w[2]/tanthe);
d6470 2
a6471 2
        x1 = prj->r0 - ymthe*tanthe;
        y1 = xj*tanthe;
a6508 6
  int mphi, mtheta, rowlen, rowoff, status;
  double cospsi, costhe, cotthe, sinpsi, sinthe, therad;
  register int iphi, itheta, *statp;
  register const double *phip, *thetap;
  register double *xp, *yp;

d6511 3
a6513 1
  if (prj->flag != PCO) {
d6517 1
d6529 6
a6534 6
  phip = phi;
  rowoff = 0;
  rowlen = nphi*sxy;
  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    xp = x + rowoff;
    for (itheta = 0; itheta < mtheta; itheta++) {
d6542 5
a6546 5
  thetap = theta;
  xp = x;
  yp = y;
  statp = stat;
  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
d6548 1
a6548 1
      for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
d6556 1
a6556 1
      for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
d6563 2
a6564 1
      therad = (*thetap)*D2R;
d6567 2
a6568 1
      for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
d6570 1
a6570 1
        cotthe = costhe/sinthe;
d6604 1
a6605 1
  prj->flag = TSC;
d6629 2
a6648 7
  int mx, my, rowlen, rowoff, status;
  double l, m, n, xf, yf;
  register int ix, iy, *statp;
  register const double *xp, *yp;
  register double *phip, *thetap;


d6651 3
a6653 1
  if (prj->flag != TSC) {
d6657 1
d6671 5
a6675 5
  xp = x;
  rowoff = 0;
  rowlen = nx*spt;
  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    xf = (*xp + prj->x0)*prj->w[1];
d6677 2
a6678 2
    phip = phi + rowoff;
    for (iy = 0; iy < my; iy++) {
d6686 6
a6691 6
  yp = y;
  phip   = phi;
  thetap = theta;
  statp  = stat;
  for (iy = 0; iy < ny; iy++, yp += sxy) {
    yf = (*yp + prj->y0)*prj->w[1];
d6693 2
a6694 2
    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
      xf = *phip;
d6719 1
a6791 2
  int face, mphi, mtheta, rowlen, rowoff, status;
  double cosphi, costhe, l, m, n, sinphi, sinthe, x0, xf, y0, yf, zeta;
a6792 3
  register int iphi, istat, itheta, *statp;
  register const double *phip, *thetap;
  register double *xp, *yp;
d6796 3
a6798 1
  if (prj->flag != TSC) {
d6802 1
d6816 5
a6820 4
  phip = phi;
  rowoff = 0;
  rowlen = nphi*sxy;
  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
d6823 3
a6825 3
    xp = x + rowoff;
    yp = y + rowoff;
    for (itheta = 0; itheta < mtheta; itheta++) {
d6835 6
a6840 5
  thetap = theta;
  xp = x;
  yp = y;
  statp = stat;
  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
d6843 4
a6846 4
    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
      l = costhe*(*xp);
      m = costhe*(*yp);
      n = sinthe;
d6848 2
a6849 2
      face = 0;
      zeta = n;
d6871 1
d6912 1
a6912 1
      istat = 0;
d6960 1
a6961 1
  prj->flag = CSC;
d6985 2
a7004 7
  int face, mx, my, rowlen, rowoff, status;
  double l, m, n, t;
  register int ix, iy, *statp;
  register const double *xp, *yp;
  register double *phip, *thetap;

  float chi, psi, xf, xx, yf, yy, z0, z1, z2, z3, z4, z5, z6;
d7036 3
a7038 1
  if (prj->flag != CSC) {
d7042 1
d7056 5
a7060 5
  xp = x;
  rowoff = 0;
  rowlen = nx*spt;
  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    xf = (float)((*xp + prj->x0)*prj->w[1]);
d7062 2
a7063 2
    phip = phi + rowoff;
    for (iy = 0; iy < my; iy++) {
d7071 6
a7076 6
  yp = y;
  phip   = phi;
  thetap = theta;
  statp  = stat;
  for (iy = 0; iy < ny; iy++, yp += sxy) {
    yf = (float)((*yp + prj->y0)*prj->w[1]);
d7078 2
a7079 2
    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
      xf = (float)(*phip);
d7104 1
d7124 2
a7125 2
      xx  =  xf*xf;
      yy  =  yf*yf;
d7127 1
d7137 1
d7150 1
d7154 2
a7155 1
      t = 1.0/sqrt((double)(chi*chi + psi*psi) + 1.0);
a7224 2
  int face, mphi, mtheta, rowlen, rowoff, status;
  double cosphi, costhe, eta, l, m, n, sinphi, sinthe, xi, zeta;
a7225 3
  register int iphi, istat, itheta, *statp;
  register const double *phip, *thetap;
  register double *xp, *yp;
a7226 2
  float chi, chi2, chi2psi2, chi4, chipsi, psi, psi2, psi4, chi2co, psi2co,
        x0, xf, y0, yf;
d7243 3
a7245 1
  if (prj->flag != CSC) {
d7249 1
d7263 5
a7267 4
  phip = phi;
  rowoff = 0;
  rowlen = nphi*sxy;
  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
d7270 3
a7272 3
    xp = x + rowoff;
    yp = y + rowoff;
    for (itheta = 0; itheta < mtheta; itheta++) {
d7282 6
a7287 5
  thetap = theta;
  xp = x;
  yp = y;
  statp = stat;
  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
d7290 4
a7293 4
    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
      l = costhe*(*xp);
      m = costhe*(*yp);
      n = sinthe;
d7295 2
a7296 2
      face = 0;
      zeta = n;
d7318 2
d7360 2
a7361 2
      chi = (float)( xi/zeta);
      psi = (float)(eta/zeta);
d7363 4
a7366 4
      chi2 = chi*chi;
      psi2 = psi*psi;
      chi2co = 1.0f - chi2;
      psi2co = 1.0f - psi2;
d7369 4
a7372 4
      chipsi = (float)fabs((double)(chi*psi));
      chi4   = (chi2 > 1.0e-16f) ? chi2*chi2 : 0.0f;
      psi4   = (psi2 > 1.0e-16f) ? psi2*psi2 : 0.0f;
      chi2psi2 = (chipsi > 1.0e-16f) ? chi2*psi2 : 0.0f;
d7374 1
d7382 1
a7382 1
      istat = 0;
d7430 1
a7431 1
  prj->flag = QSC;
d7455 2
a7474 2
  int direct, face, mx, my, rowlen, rowoff, status;
  double cosw, l, m, n, omega, sinw, tau, xf, yf, w, zeco, zeta;
a7475 4
  register int ix, iy, *statp;
  register const double *xp, *yp;
  register double *phip, *thetap;

d7479 3
a7481 1
  if (prj->flag != QSC) {
d7485 1
d7499 5
a7503 5
  xp = x;
  rowoff = 0;
  rowlen = nx*spt;
  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    xf = (*xp + prj->x0)*prj->w[1];
d7505 2
a7506 2
    phip = phi + rowoff;
    for (iy = 0; iy < my; iy++) {
d7514 6
a7519 6
  yp = y;
  phip   = phi;
  thetap = theta;
  statp  = stat;
  for (iy = 0; iy < ny; iy++, yp += sxy) {
    yf = (*yp + prj->y0)*prj->w[1];
d7521 2
a7522 2
    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
      xf = *phip;
d7546 1
d7567 2
a7568 1
      direct = (fabs(xf) > fabs(yf));
d7590 1
d7615 1
a7726 3
  int face, mphi, mtheta, rowlen, rowoff, status;
  double cosphi, costhe, eta, l, m, n, omega, p, sinphi, sinthe, t, tau, x0,
         xf, xi, y0, yf, zeco, zeta;
a7727 4
  register int iphi, istat, itheta, *statp;
  register const double *phip, *thetap;
  register double *xp, *yp;

d7731 3
a7733 1
  if (prj->flag != QSC) {
d7737 1
d7751 5
a7755 4
  phip = phi;
  rowoff = 0;
  rowlen = nphi*sxy;
  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
d7758 3
a7760 3
    xp = x + rowoff;
    yp = y + rowoff;
    for (itheta = 0; itheta < mtheta; itheta++) {
d7770 6
a7775 5
  thetap = theta;
  xp = x;
  yp = y;
  statp = stat;
  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
d7778 1
a7778 1
    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
d7786 3
a7788 3
      l = costhe*(*xp);
      m = costhe*(*yp);
      n = sinthe;
d7790 2
a7791 2
      face = 0;
      zeta = n;
d7813 1
a7813 1
      zeco = 1.0 - zeta;
d7815 1
d7822 2
a7823 2
          t = (*thetap)*D2R;
          p = atan2(*yp, *xp);
d7834 2
a7835 2
          t = (*thetap)*D2R;
          p = atan2(*yp, *xp) - PI/2.0;
d7846 2
a7847 2
          t = (*thetap)*D2R;
          p = atan2(*yp, *xp);
d7859 2
a7860 2
          t = (*thetap)*D2R;
          p = atan2(*yp, *xp) + PI/2.0;
d7871 1
a7871 1
          t = (*thetap + 90.0)*D2R;
d7883 1
a7883 1
          t = (90.0 - *thetap)*D2R;
d7891 3
a7893 2
      xf = 0.0;
      yf = 0.0;
d7918 1
a7918 1
      istat = 0;
d7980 1
a7981 1
  prj->flag = HPX;
d8024 2
a8043 7
  int h, mx, my, offset, rowlen, rowoff, status;
  double absy, r, s, sigma, slim, t, ylim, yr;
  register int istat, ix, iy, *statp;
  register const double *xp, *yp;
  register double *phip, *thetap;


d8046 3
a8048 1
  if (prj->flag != HPX) {
d8052 1
a8052 3
  slim = prj->w[6] + 1e-12;
  ylim = prj->w[9] * prj->w[4];

d8066 5
a8070 5
  xp = x;
  rowoff = 0;
  rowlen = nx*spt;
  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    s = prj->w[1] * (*xp + prj->x0);
d8072 1
d8076 3
a8078 3
    phip   = phi + rowoff;
    thetap = theta + rowoff;
    for (iy = 0; iy < my; iy++) {
d8089 11
a8099 7
  yp = y;
  phip   = phi;
  thetap = theta;
  statp  = stat;
  for (iy = 0; iy < ny; iy++, yp += sxy) {
    yr = prj->w[1]*(*yp + prj->y0);
    absy = fabs(yr);
d8101 1
a8101 1
    istat = 0;
d8104 2
a8105 2
      t = asind(yr/prj->w[3]);
      for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
d8112 1
a8112 1
      offset = (prj->n || *yp > 0.0) ? 0 : 1;
d8114 1
a8114 1
      sigma = prj->w[4] - absy / prj->w[6];
d8116 1
d8135 1
a8135 1
      for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
d8138 1
a8138 1
          h = (int)floor(*phip / prj->w[6]) + prj->m;
d8147 1
a8147 1
        r = s * *thetap;
d8165 1
a8165 1
      for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
a8197 7
  int h, mphi, mtheta, offset, rowlen, rowoff, status;
  double abssin, eta, sigma, sinthe, t, xi;
  register int iphi, itheta, *statp;
  register const double *phip, *thetap;
  register double *xp, *yp;


d8200 3
a8202 1
  if (prj->flag != HPX) {
d8206 1
d8218 5
a8222 5
  phip = phi;
  rowoff = 0;
  rowlen = nphi*sxy;
  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    xi = prj->w[0] * (*phip) - prj->x0;
d8225 1
d8229 3
a8231 3
    xp = x + rowoff;
    yp = y + rowoff;
    for (itheta = 0; itheta < mtheta; itheta++) {
d8242 7
a8248 7
  thetap = theta;
  xp = x;
  yp = y;
  statp = stat;
  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    sinthe = sind(*thetap);
    abssin = fabs(sinthe);
d8250 1
d8254 1
a8254 1
      for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
d8261 1
a8261 1
      offset = (prj->n || *thetap > 0.0) ? 0 : 1;
d8263 2
a8264 2
      sigma = sqrt(prj->pv[2]*(1.0 - abssin));
      xi = sigma - 1.0;
d8270 1
a8270 1
      for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
d8273 1
a8273 1
          h = (int)floor((*xp + prj->x0) / prj->w[9]) + prj->m;
d8323 1
a8324 1
  prj->flag = XPH;
d8356 2
a8375 2
  int mx, my, rowlen, rowoff, status;
  double abseta, eta, eta1, sigma, xi, xi1, xr, yr;
a8376 4
  register int istat, ix, iy, *statp;
  register const double *xp, *yp;
  register double *phip, *thetap;

d8380 3
a8382 1
  if (prj->flag != XPH) {
d8386 1
d8400 5
a8404 5
  xp = x;
  rowoff = 0;
  rowlen = nx*spt;
  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    xr = (*xp + prj->x0)*prj->w[1];
d8406 2
a8407 2
    phip = phi + rowoff;
    for (iy = 0; iy < my; iy++) {
d8415 6
a8420 6
  yp = y;
  phip   = phi;
  thetap = theta;
  statp  = stat;
  for (iy = 0; iy < ny; iy++, yp += sxy) {
    yr = (*yp + prj->y0)*prj->w[1];
d8422 2
a8423 2
    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
      xr = *phip;
d8425 1
d8444 3
a8446 3
      xi  = xi1  + 45.0;
      eta = eta1 + 90.0;
      abseta = fabs(eta);
d8453 1
a8453 1
          istat = 0;
d8467 1
a8467 1
          sigma = (90.0 - abseta) / 45.0;
d8494 1
a8494 1
          istat = 0;
a8538 7
  int mphi, mtheta, rowlen, rowoff, status;
  double abssin, chi, eta, psi, sigma, sinthe, xi;
  register int iphi, itheta, *statp;
  register const double *phip, *thetap;
  register double *xp, *yp;


d8541 3
a8543 1
  if (prj->flag != XPH) {
d8547 1
d8559 6
a8564 4
  phip = phi;
  rowoff = 0;
  rowlen = nphi*sxy;
  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
d8579 3
a8581 3
    xp = x + rowoff;
    yp = y + rowoff;
    for (itheta = 0; itheta < mtheta; itheta++) {
d8592 7
a8598 7
  thetap = theta;
  xp = x;
  yp = y;
  statp = stat;
  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    sinthe = sind(*thetap);
    abssin = fabs(sinthe);
d8600 2
a8601 1
    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
d8609 1
@


8.2.1.1
log
@WCSLIB 8.2 development branch.
@
text
@d22 1
a22 1
  $Id: prj.c,v 8.2 2023/11/16 10:00:29 mcalabre Exp $
@


8.2.1.2
log
@Declared AZP, SZP, etc. to be static to avoid namespace conflicts arising
in Link Time Optimization (LTO) builds of the Rwcs wrappers.  Likewise, for
helper function, prjoff().
@
text
@d22 1
a22 1
  $Id: prj.c,v 8.2.1.1 2023/11/16 10:05:57 mcalabre Exp mcalabre $
d60 30
a97 29
static const int AZP = 101;
static const int SZP = 102;
static const int TAN = 103;
static const int STG = 104;
static const int SIN = 105;
static const int ARC = 106;
static const int ZPN = 107;
static const int ZEA = 108;
static const int AIR = 109;
static const int CYP = 201;
static const int CEA = 202;
static const int CAR = 203;
static const int MER = 204;
static const int SFL = 301;
static const int PAR = 302;
static const int MOL = 303;
static const int AIT = 401;
static const int COP = 501;
static const int COE = 502;
static const int COD = 503;
static const int COO = 504;
static const int BON = 601;
static const int PCO = 602;
static const int TSC = 701;
static const int CSC = 702;
static const int QSC = 703;
static const int HPX = 801;
static const int XPH = 802;

d124 1
a124 1
* prjsize computes the size of a prjprm struct.
d523 1
a523 1
static int prjoff(
@


8.2.1.3
log
@Updated date in copyright notice.
@
text
@d3 1
a3 1
  Copyright (C) 1995-2024, Mark Calabretta
d22 1
a22 1
  $Id: prj.c,v 8.2.1.2 2023/11/29 07:39:01 mcalabre Exp mcalabre $
@


8.2.1.4
log
@Converted to C99-style intermingled variable declarations.
@
text
@d22 1
a22 1
  $Id: prj.c,v 8.2.1.3 2024/04/02 14:01:58 mcalabre Exp mcalabre $
d144 2
d155 1
a155 1
  for (int k = 4; k < PVN; prj->pv[k++] = 0.0);
d162 1
a162 1
  for (int k = 9; k < 40; prj->name[k++] = '\0');
d176 1
a176 1
  for (int k = 0; k < 10; prj->w[k++] = 0.0);
d213 2
a215 1
  int exsizes[2];
d227 3
d237 1
a237 1
    int n = (prj->pvrange)%100;
d246 1
a246 1
    for (int i = 1; i <= n; i++) {
d292 1
a292 1
  for (int i = 0; i < 5; i++) {
d296 1
a296 1
  for (int i = 5; i < 10; i++) {
a301 2

  char hext[32];
d336 9
a344 7
  double *phip   = phi;
  double *thetap = theta;
  int    *statp  = stat;
  int    status  = 0;
  for (int itheta = 0; itheta < ntheta; itheta++) {
    for (int iphi = 0; iphi < nphi; iphi++, phip += spt, thetap += spt,
         statp++) {
d392 3
d396 1
a396 1
  struct wcserr **err = &(prj->err);
a399 2

  int status;
d480 2
a483 2

  int status;
d506 2
a509 2

  int status;
d528 3
a541 2
    double x0, y0;
    int    stat;
d648 2
d651 4
a657 2

  int status;
a661 1
  int mx, my;
d675 5
a679 6
  const double *xp = x;
  double *phip, *thetap;
  int rowoff = 0;
  int rowlen = nx*spt;
  for (int ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    double xj = *xp + prj->x0;
d682 1
a682 1
    for (int iy = 0; iy < my; iy++) {
d690 1
a690 3
  const double *yp = y;
  int *statp  = stat;

d693 3
a695 2
  for (int iy = 0; iy < ny; iy++, yp += sxy) {
    double yj = *yp + prj->y0;
d697 2
a698 2
    double yc  = yj*prj->w[3];
    double yc2 = yc*yc;
d700 1
a700 1
    double q = prj->w[0] + yj*prj->w[4];
d702 2
a703 2
    for (int ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
      double xj = *phip;
d705 1
a705 1
      double r = sqrt(xj*xj + yc2);
d714 2
a715 2
        double s = r / q;
        double t = s*prj->pv[1]/sqrt(s*s + 1.0);
d731 2
a732 2
        double a = s - t;
        double b = s + t + 180.0;
d767 7
a775 2

  int status;
a779 1
  int mphi, mtheta;
d793 4
a796 5
  const double *phip = phi;
  int rowoff = 0;
  int rowlen = nphi*sxy;
  for (int iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    double sinphi, cosphi;
d799 3
a801 3
    double *xp = x + rowoff;
    double *yp = y + rowoff;
    for (int itheta = 0; itheta < mtheta; itheta++) {
d811 5
a815 6
  const double *thetap = theta;
  double *xp = x;
  double *yp = y;
  int *statp = stat;
  for (int itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    double sinthe, costhe;
d818 3
a820 3
    for (int iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
      double s = prj->w[1]*(*yp);
      double t = (prj->pv[1] + sinthe) + costhe*s;
d829 1
a829 1
        double r = prj->w[0]*costhe/t;
d832 1
a832 1
        int istat = 0;
d846 2
a847 3

              double a = s - t;
              double b = s + t + 180.0;
d967 2
d970 4
a976 2

  int status;
a980 1
  int mx, my;
d994 5
a998 5
  const double *xp = x;
  int rowoff = 0;
  int rowlen = nx*spt;
  for (int ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    double xr = (*xp + prj->x0)*prj->w[0];
d1000 2
a1001 2
    double *phip = phi + rowoff;
    for (int iy = 0; iy < my; iy++) {
d1009 14
a1022 14
  const double *yp = y;
  double *phip   = phi;
  double *thetap = theta;
  int     *statp = stat;
  for (int iy = 0; iy < ny; iy++, yp += sxy) {
    double yr = (*yp + prj->y0)*prj->w[0];

    for (int ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
      double xr = *phip;
      double r2 = xr*xr + yr*yr;

      double x1 = (xr - prj->w[1])/prj->w[3];
      double y1 = (yr - prj->w[2])/prj->w[3];
      double xy = xr*x1 + yr*y1;
a1023 1
      double z;
d1030 5
a1034 5
        double t = x1*x1 + y1*y1;
        double a = t + 1.0;
        double b = xy - t;
        double c = r2 - xy - xy + t - 1.0;
        double d = b*b - a*c;
d1047 3
a1049 3
        double sinth1 = (-b + d)/a;
        double sinth2 = (-b - d)/a;
        double sinthe = (sinth1 > sinth2) ? sinth1 : sinth2;
d1106 7
a1114 2

  int status;
a1118 1
  int mphi, mtheta;
d1132 4
a1135 5
  const double *phip = phi;
  int rowoff = 0;
  int rowlen = nphi*sxy;
  for (int iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    double sinphi, cosphi;
d1138 3
a1140 3
    double *xp = x + rowoff;
    double *yp = y + rowoff;
    for (int itheta = 0; itheta < mtheta; itheta++) {
d1150 7
a1156 7
  const double *thetap = theta;
  double *xp = x;
  double *yp = y;
  int *statp = stat;
  for (int itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    double s = 1.0 - sind(*thetap);
    double t = prj->w[3] - s;
d1159 1
a1159 1
      for (int iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
d1168 3
a1170 3
      double r = prj->w[6]*cosd(*thetap)/t;
      double u = prj->w[4]*s/t + prj->x0;
      double v = prj->w[5]*s/t + prj->y0;
d1172 1
a1172 1
      for (int iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
d1174 1
a1174 1
        int istat = 0;
d1189 2
a1190 3

              double a = s - t;
              double b = s + t + 180.0;
d1271 7
a1279 2

  int status;
a1283 1
  int mx, my;
d1297 5
a1301 5
  const double *xp = x;
  int rowoff = 0;
  int rowlen = nx*spt;
  for (int ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    double xj = *xp + prj->x0;
d1303 2
a1304 2
    double *phip = phi + rowoff;
    for (int iy = 0; iy < my; iy++) {
d1312 7
a1318 7
  const double *yp = y;
  double *phip   = phi;
  double *thetap = theta;
  int    *statp  = stat;
  for (int iy = 0; iy < ny; iy++, yp += sxy) {
    double yj  = *yp + prj->y0;
    double yj2 = yj*yj;
d1320 2
a1321 2
    for (int ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
      double xj = *phip;
d1323 1
a1323 1
      double r = sqrt(xj*xj + yj2);
d1359 7
a1367 2

  int status;
a1371 1
  int mphi, mtheta;
d1385 4
a1388 5
  const double *phip = phi;
  int rowoff = 0;
  int rowlen = nphi*sxy;
  for (int iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    double sinphi, cosphi;
d1391 3
a1393 3
    double *xp = x + rowoff;
    double *yp = y + rowoff;
    for (int itheta = 0; itheta < mtheta; itheta++) {
d1403 6
a1408 6
  const double *thetap = theta;
  double *xp = x;
  double *yp = y;
  int *statp = stat;
  for (int itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    double s = sind(*thetap);
d1410 1
a1410 1
      for (int iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
d1418 1
a1418 1
      double r =  prj->r0*cosd(*thetap)/s;
d1421 1
a1421 1
      int istat = 0;
d1429 1
a1429 1
      for (int iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
d1506 7
a1514 2

  int status;
a1518 1
  int mx, my;
d1530 5
a1534 5
  const double *xp = x;
  int rowoff = 0;
  int rowlen = nx*spt;
  for (int ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    double xj = *xp + prj->x0;
d1536 2
a1537 2
    double *phip = phi + rowoff;
    for (int iy = 0; iy < my; iy++) {
d1545 7
a1551 7
  const double *yp = y;
  double *phip   = phi;
  double *thetap = theta;
  int    *statp  = stat;
  for (int iy = 0; iy < ny; iy++, yp += sxy) {
    double yj  = *yp + prj->y0;
    double yj2 = yj*yj;
d1553 2
a1554 2
    for (int ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
      double xj  = *phip;
d1556 1
a1556 1
      double r = sqrt(xj*xj + yj2);
d1586 7
a1594 2

  int status;
a1598 1
  int mphi, mtheta;
d1612 4
a1615 5
  const double *phip = phi;
  int rowoff = 0;
  int rowlen = nphi*sxy;
  for (int iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    double sinphi, cosphi;
d1618 3
a1620 3
    double *xp = x + rowoff;
    double *yp = y + rowoff;
    for (int itheta = 0; itheta < mtheta; itheta++) {
d1630 6
a1635 6
  const double *thetap = theta;
  double *xp = x;
  double *yp = y;
  int *statp = stat;
  for (int itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    double s = 1.0 + sind(*thetap);
d1637 1
a1637 1
      for (int iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
d1645 1
a1645 1
      double r = prj->w[0]*cosd(*thetap)/s;
d1647 1
a1647 1
      for (int iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
d1729 1
d1731 6
a1739 2

  int status;
d1744 2
a1745 2
  double xi  = prj->pv[1];
  double eta = prj->pv[2];
a1746 1
  int mx, my;
d1760 5
a1764 5
  const double *xp = x;
  int rowoff = 0;
  int rowlen = nx*spt;
  for (int ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    double x0 = (*xp + prj->x0)*prj->w[0];
d1766 2
a1767 2
    double *phip = phi + rowoff;
    for (int iy = 0; iy < my; iy++) {
d1775 7
a1781 7
  const double *yp = y;
  double *phip   = phi;
  double *thetap = theta;
  int    *statp  = stat;
  for (int iy = 0; iy < ny; iy++, yp += sxy) {
    double y0 = (*yp + prj->y0)*prj->w[0];
    double y02 = y0*y0;
d1783 1
a1783 1
    for (int ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
d1785 2
a1786 2
      double x0 = *phip;
      double r2 = x0*x0 + y02;
d1808 1
a1808 1
        double xy = x0*xi + y0*eta;
a1809 1
        double z;
d1816 4
a1819 4
          double a = prj->w[2];
          double b = xy - prj->w[1];
          double c = r2 - xy - xy + prj->w[3];
          double d = b*b - a*c;
d1832 3
a1834 3
          double sinth1 = (-b + d)/a;
          double sinth2 = (-b - d)/a;
          double sinthe = (sinth1 > sinth2) ? sinth1 : sinth2;
d1861 2
a1862 2
        double x1 = -y0 + eta*z;
        double y1 =  x0 -  xi*z;
d1898 7
a1906 2

  int status;
a1910 1
  int mphi, mtheta;
d1924 4
a1927 5
  const double *phip = phi;
  int rowoff = 0;
  int rowlen = nphi*sxy;
  for (int iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    double sinphi, cosphi;
d1930 3
a1932 3
    double *xp = x + rowoff;
    double *yp = y + rowoff;
    for (int itheta = 0; itheta < mtheta; itheta++) {
d1942 6
a1947 8
  const double *thetap = theta;
  double *xp = x;
  double *yp = y;
  int *statp = stat;
  for (int itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    double costhe, z;

    double t = (90.0 - fabs(*thetap))*D2R;
d1959 1
a1959 1
    double r = prj->r0*costhe;
d1963 1
a1963 1
      int istat = 0;
d1971 1
a1971 1
      for (int iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
d1980 2
a1981 2
      double z1 = prj->pv[1]*z - prj->x0;
      double z2 = prj->pv[2]*z - prj->y0;
d1983 2
a1984 2
      for (int iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
        int istat = 0;
d2069 7
a2077 2

  int status;
a2081 1
  int mx, my;
d2095 5
a2099 5
  const double *xp = x;
  int rowoff = 0;
  int rowlen = nx*spt;
  for (int ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    double xj = *xp + prj->x0;
d2101 2
a2102 2
    double *phip = phi + rowoff;
    for (int iy = 0; iy < my; iy++) {
d2110 7
a2116 7
  const double *yp = y;
  double *phip   = phi;
  double *thetap = theta;
  int    *statp  = stat;
  for (int iy = 0; iy < ny; iy++, yp += sxy) {
    double yj  = *yp + prj->y0;
    double yj2 = yj*yj;
d2118 2
a2119 2
    for (int ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
      double xj = *phip;
d2121 1
a2121 1
      double r = sqrt(xj*xj + yj2);
d2158 7
a2166 2

  int status;
a2170 1
  int mphi, mtheta;
d2182 4
a2185 5
  const double *phip = phi;
  int rowoff = 0;
  int rowlen = nphi*sxy;
  for (int iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    double sinphi, cosphi;
d2188 3
a2190 3
    double *xp = x + rowoff;
    double *yp = y + rowoff;
    for (int itheta = 0; itheta < mtheta; itheta++) {
d2200 6
a2205 6
  const double *thetap = theta;
  double *xp = x;
  double *yp = y;
  int *statp = stat;
  for (int itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    double r =  prj->w[0]*(90.0 - *thetap);
d2207 1
a2207 1
    for (int iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
d2243 2
a2266 1
  int k;
d2280 2
a2281 3
    double d, d1, d2;

    d1 = prj->pv[1];
a2286 4
    int j;
    double zd, zd1, zd2;

    zd1 = 0.0;
d2290 1
a2290 1
      for (int m = k; m > 0; m--) {
d2309 1
a2309 1
        for (int m = k; m > 0; m--) {
d2325 2
a2326 2
    double r = 0.0;
    for (int m = k; m >= 0; m--) {
d2354 2
d2357 4
a2363 2

  int status;
d2368 1
a2368 1
  int k = prj->n;
a2369 1
  int mx, my;
d2383 5
a2387 5
  const double *xp = x;
  int rowoff = 0;
  int rowlen = nx*spt;
  for (int ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    double xj = *xp + prj->x0;
d2389 2
a2390 2
    double *phip = phi + rowoff;
    for (int iy = 0; iy < my; iy++) {
d2398 7
a2404 7
  const double *yp = y;
  double *phip   = phi;
  double *thetap = theta;
  int    *statp  = stat;
  for (int iy = 0; iy < ny; iy++, yp += sxy) {
    double yj  = *yp + prj->y0;
    double yj2 = yj*yj;
d2406 2
a2407 2
    for (int ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
      double xj = *phip;
d2409 1
a2409 1
      double r = sqrt(xj*xj + yj2)/prj->r0;
a2415 1
      double zd;
d2426 3
a2428 3
        double a = prj->pv[2];
        double b = prj->pv[1];
        double c = prj->pv[0] - r;
d2430 1
a2430 1
        double d = b*b - 4.0*a*c;
d2440 2
a2441 3
        double zd1 = (-b + d)/(2.0*a);
        double zd2 = (-b - d)/(2.0*a);

d2463 4
a2466 4
        double zd1 = 0.0;
        double r1  = prj->pv[0];
        double zd2 = prj->w[0];
        double r2  = prj->w[1];
d2486 2
a2487 2
          for (int j = 0; j < 100; j++) {
            double lambda = (r2 - r)/(r2 - r1);
d2496 2
a2497 2
            double rt = 0.0;
            for (int m = k; m >= 0; m--) {
d2545 7
a2553 2

  int status;
a2557 1
  int mphi, mtheta;
d2571 4
a2574 5
  const double *phip = phi;
  int rowoff = 0;
  int rowlen = nphi*sxy;
  for (int iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    double sinphi, cosphi;
d2577 3
a2579 3
    double *xp = x + rowoff;
    double *yp = y + rowoff;
    for (int itheta = 0; itheta < mtheta; itheta++) {
d2589 6
a2594 6
  const double *thetap = theta;
  double *xp = x;
  double *yp = y;
  int *statp = stat;
  for (int itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    double s = (90.0 - *thetap)*D2R;
d2596 2
a2597 2
    double r = 0.0;
    for (int m = prj->n; m >= 0; m--) {
d2603 1
a2603 1
    int istat = 0;
d2611 1
a2611 1
    for (int iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
d2687 2
d2690 4
a2696 2

  int status;
a2700 1
  int mx, my;
d2714 5
a2718 5
  const double *xp = x;
  int rowoff = 0;
  int rowlen = nx*spt;
  for (int ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    double xj = *xp + prj->x0;
d2720 2
a2721 2
    double *phip = phi + rowoff;
    for (int iy = 0; iy < my; iy++) {
d2729 7
a2735 7
  const double *yp = y;
  double *phip   = phi;
  double *thetap = theta;
  int    *statp  = stat;
  for (int iy = 0; iy < ny; iy++, yp += sxy) {
    double yj  = *yp + prj->y0;
    double yj2 = yj*yj;
d2737 2
a2738 2
    for (int ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
      double xj  = *phip;
d2740 1
a2740 1
      double r = sqrt(xj*xj + yj2);
d2747 1
a2747 1
      double s = r*prj->w[1];
d2789 7
a2797 2

  int status;
a2801 1
  int mphi, mtheta;
d2813 4
a2816 5
  const double *phip = phi;
  int rowoff = 0;
  int rowlen = nphi*sxy;
  for (int iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    double sinphi, cosphi;
d2819 3
a2821 3
    double *xp = x + rowoff;
    double *yp = y + rowoff;
    for (int itheta = 0; itheta < mtheta; itheta++) {
d2831 6
a2836 6
  const double *thetap = theta;
  double *xp = x;
  double *yp = y;
  int *statp = stat;
  for (int itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    double r =  prj->w[0]*sind((90.0 - *thetap)/2.0);
d2838 1
a2838 1
    for (int iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
d2881 1
d2905 1
a2905 1
    double cosxi = cosd((90.0 - prj->pv[1])/2.0);
d2938 2
d2941 4
a2947 2

  int status;
a2951 1
  int mx, my;
d2965 5
a2969 5
  const double *xp = x;
  int rowoff = 0;
  int rowlen = nx*spt;
  for (int ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    double xj = *xp + prj->x0;
d2971 2
a2972 2
    double *phip = phi + rowoff;
    for (int iy = 0; iy < my; iy++) {
d2980 7
a2986 7
  const double *yp = y;
  double *phip   = phi;
  double *thetap = theta;
  int    *statp  = stat;
  for (int iy = 0; iy < ny; iy++, yp += sxy) {
    double yj  = *yp + prj->y0;
    double yj2 = yj*yj;
d2988 2
a2989 2
    for (int ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
      double xj = *phip;
d2991 1
a2991 1
      double r = sqrt(xj*xj + yj2)/prj->w[0];
d2998 1
a2998 1
      double xi;
d3005 2
a3006 6
        double x1 = 1.0;
        double x2 = 1.0;
        double r1 = 0.0;
        double r2 = 0.0;

        int k;
d3009 1
a3009 1
          double tanxi = sqrt(1.0-x2*x2)/x2;
a3022 1
        double cosxi;
d3025 1
a3025 1
          double lambda = (r2-r)/(r2-r1);
d3033 2
a3034 2
          double tanxi = sqrt(1.0-cosxi*cosxi)/cosxi;
          double rt = -(log(cosxi)/tanxi + prj->w[1]*tanxi);
d3085 7
a3093 2

  int status;
a3097 1
  int mphi, mtheta;
d3111 4
a3114 5
  const double *phip = phi;
  int rowoff = 0;
  int rowlen = nphi*sxy;
  for (int iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    double sinphi, cosphi;
d3117 3
a3119 3
    double *xp = x + rowoff;
    double *yp = y + rowoff;
    for (int itheta = 0; itheta < mtheta; itheta++) {
d3129 6
a3134 6
  const double *thetap = theta;
  double *xp = x;
  double *yp = y;
  int *statp = stat;
  for (int itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    int istat = 0;
a3135 1
    double r;
d3139 1
a3139 1
      double xi = D2R*(90.0 - *thetap)/2.0;
d3143 2
a3144 2
        double cosxi = cosd((90.0 - *thetap)/2.0);
        double tanxi = sqrt(1.0 - cosxi*cosxi)/cosxi;
d3153 1
a3153 1
    for (int iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
d3263 7
a3271 2

  int status;
a3275 1
  int mx, my;
d3289 5
a3293 5
  const double *xp = x;
  int rowoff = 0;
  int rowlen = nx*spt;
  for (int ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    double s = prj->w[1]*(*xp + prj->x0);
d3295 2
a3296 2
    double *phip = phi + rowoff;
    for (int iy = 0; iy < my; iy++) {
d3304 6
a3309 6
  const double *yp = y;
  double *thetap = theta;
  int    *statp  = stat;
  for (int iy = 0; iy < ny; iy++, yp += sxy) {
    double eta = prj->w[3]*(*yp + prj->y0);
    double t = atan2d(eta,1.0) + asind(eta*prj->pv[1]/sqrt(eta*eta+1.0));
d3311 1
a3311 1
    for (int ix = 0; ix < mx; ix++, thetap += spt, statp++) {
d3341 7
a3349 2

  int status;
a3353 1
  int mphi, mtheta;
d3367 5
a3371 5
  const double *phip = phi;
  int rowoff = 0;
  int rowlen = nphi*sxy;
  for (int iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    double xi = prj->w[0]*(*phip) - prj->x0;
d3373 2
a3374 2
    double *xp = x + rowoff;
    for (int itheta = 0; itheta < mtheta; itheta++) {
d3382 5
a3386 5
  const double *thetap = theta;
  double *yp = y;
  int *statp = stat;
  for (int itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    double eta = prj->pv[1] + cosd(*thetap);
d3388 1
a3388 1
    int istat = 0;
d3398 1
a3398 1
    for (int iphi = 0; iphi < mphi; iphi++, yp += sxy, statp++) {
d3491 2
d3494 4
a3500 2

  int status;
a3504 1
  int mx, my;
d3518 5
a3522 5
  const double *xp = x;
  int rowoff = 0;
  int rowlen = nx*spt;
  for (int ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    double s = prj->w[1]*(*xp + prj->x0);
d3524 2
a3525 2
    double *phip = phi + rowoff;
    for (int iy = 0; iy < my; iy++) {
d3533 5
a3537 5
  const double *yp = y;
  double *thetap = theta;
  int    *statp  = stat;
  for (int iy = 0; iy < ny; iy++, yp += sxy) {
    double s = prj->w[3]*(*yp + prj->y0);
d3539 1
a3539 1
    int istat = 0;
d3552 1
a3552 1
    for (int ix = 0; ix < mx; ix++, thetap += spt, statp++) {
d3582 7
a3590 2

  int status;
a3594 1
  int mphi, mtheta;
d3606 5
a3610 5
  const double *phip = phi;
  int rowoff = 0;
  int rowlen = nphi*sxy;
  for (int iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    double xi = prj->w[0]*(*phip) - prj->x0;
d3612 2
a3613 2
    double *xp = x + rowoff;
    for (int itheta = 0; itheta < mtheta; itheta++) {
d3621 5
a3625 5
  const double *thetap = theta;
  double *yp = y;
  int *statp = stat;
  for (int itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    double eta = prj->w[2]*sind(*thetap) - prj->y0;
d3627 1
a3627 1
    for (int iphi = 0; iphi < mphi; iphi++, yp += sxy, statp++) {
d3702 7
a3710 2

  int status;
a3714 1
  int mx, my;
d3728 5
a3732 5
  const double *xp = x;
  int rowoff = 0;
  int rowlen = nx*spt;
  for (int ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    double s = prj->w[1]*(*xp + prj->x0);
d3734 2
a3735 2
    double *phip = phi + rowoff;
    for (int iy = 0; iy < my; iy++) {
d3743 5
a3747 5
  const double *yp = y;
  double *thetap = theta;
  int    *statp  = stat;
  for (int iy = 0; iy < ny; iy++, yp += sxy) {
    double t = prj->w[1]*(*yp + prj->y0);
d3749 1
a3749 1
    for (int ix = 0; ix < mx; ix++, thetap += spt, statp++) {
d3779 7
a3787 2

  int status;
a3791 1
  int mphi, mtheta;
d3803 5
a3807 5
  const double *phip = phi;
  int rowoff = 0;
  int rowlen = nphi*sxy;
  for (int iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    double xi = prj->w[0]*(*phip) - prj->x0;
d3809 2
a3810 2
    double *xp = x + rowoff;
    for (int itheta = 0; itheta < mtheta; itheta++) {
d3818 5
a3822 5
  const double *thetap = theta;
  double *yp = y;
  int *statp = stat;
  for (int itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    double eta = prj->w[0]*(*thetap) - prj->y0;
d3824 1
a3824 1
    for (int iphi = 0; iphi < mphi; iphi++, yp += sxy, statp++) {
d3899 7
a3907 2

  int status;
a3911 1
  int mx, my;
d3925 5
a3929 5
  const double *xp = x;
  int rowoff = 0;
  int rowlen = nx*spt;
  for (int ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    double s = prj->w[1]*(*xp + prj->x0);
d3931 2
a3932 2
    double *phip = phi + rowoff;
    for (int iy = 0; iy < my; iy++) {
d3940 5
a3944 5
  const double *yp = y;
  double *thetap = theta;
  int    *statp  = stat;
  for (int iy = 0; iy < ny; iy++, yp += sxy) {
    double t = 2.0*atand(exp((*yp + prj->y0)/prj->r0)) - 90.0;
d3946 1
a3946 1
    for (int ix = 0; ix < mx; ix++, thetap += spt, statp++) {
d3976 7
a3984 2

  int status;
a3988 1
  int mphi, mtheta;
d4002 5
a4006 5
  const double *phip = phi;
  int rowoff = 0;
  int rowlen = nphi*sxy;
  for (int iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    double xi  = prj->w[0]*(*phip) - prj->x0;
d4008 2
a4009 2
    double *xp = x + rowoff;
    for (int itheta = 0; itheta < mtheta; itheta++) {
d4017 5
a4021 5
  const double *thetap = theta;
  double *yp = y;
  int *statp = stat;
  for (int itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    int istat = 0;
a4022 1
    double eta;
d4031 1
a4031 1
    for (int iphi = 0; iphi < mphi; iphi++, yp += sxy, statp++) {
d4106 7
a4114 2

  int status;
a4118 1
  int mx, my;
d4132 5
a4136 5
  const double *xp = x;
  int rowoff = 0;
  int rowlen = nx*spt;
  for (int ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    double s = prj->w[1]*(*xp + prj->x0);
d4138 2
a4139 2
    double *phip = phi + rowoff;
    for (int iy = 0; iy < my; iy++) {
d4147 7
a4153 7
  const double *yp = y;
  double *phip   = phi;
  double *thetap = theta;
  int    *statp  = stat;
  for (int iy = 0; iy < ny; iy++, yp += sxy) {
    double yj = *yp + prj->y0;
    double s = cos(yj/prj->r0);
d4155 1
a4155 1
    int istat = 0;
d4163 1
a4163 1
    double t = prj->w[1]*yj;
d4165 1
a4165 1
    for (int ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
d4196 7
a4204 2

  int status;
a4208 1
  int mphi, mtheta;
d4220 5
a4224 5
  const double *phip = phi;
  int rowoff = 0;
  int rowlen = nphi*sxy;
  for (int iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    double xi = prj->w[0]*(*phip);
d4226 2
a4227 2
    double *xp = x + rowoff;
    for (int itheta = 0; itheta < mtheta; itheta++) {
d4235 7
a4241 7
  const double *thetap = theta;
  double *xp = x;
  double *yp = y;
  int *statp = stat;
  for (int itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    double xi  = cosd(*thetap);
    double eta = prj->w[0]*(*thetap) - prj->y0;
d4243 1
a4243 1
    for (int iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
d4325 2
d4328 4
a4334 2

  int status;
a4338 1
  int mx, my;
d4352 11
a4362 11
  const double *xp = x;
  int rowoff = 0;
  int rowlen = nx*spt;
  for (int ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    double xj = *xp + prj->x0;
    double s = prj->w[1]*xj;
    double t = fabs(xj) - tol;

    double *phip   = phi   + rowoff;
    double *thetap = theta + rowoff;
    for (int iy = 0; iy < my; iy++) {
d4372 6
a4377 6
  const double *yp = y;
  double *phip   = phi;
  double *thetap = theta;
  int    *statp  = stat;
  for (int iy = 0; iy < ny; iy++, yp += sxy) {
    double r = prj->w[3]*(*yp + prj->y0);
d4379 1
a4379 2
    int istat = 0;
    double s, t;
d4398 1
a4398 1
    for (int ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
d4439 7
a4447 2

  int status;
a4451 1
  int mphi, mtheta;
d4463 5
a4467 5
  const double *phip = phi;
  int rowoff = 0;
  int rowlen = nphi*sxy;
  for (int iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    double xi = prj->w[0]*(*phip);
d4469 2
a4470 2
    double *xp = x + rowoff;
    for (int itheta = 0; itheta < mtheta; itheta++) {
d4478 8
a4485 8
  const double *thetap = theta;
  double *xp = x;
  double *yp = y;
  int *statp = stat;
  for (int itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    double s = sind((*thetap)/3.0);
    double xi = (1.0 - 4.0*s*s);
    double eta = prj->w[2]*s - prj->y0;
d4487 1
a4487 1
    for (int iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
d4564 2
d4567 4
a4573 2

  int status;
a4577 1
  int mx, my;
d4591 11
a4601 11
  const double *xp = x;
  int rowoff = 0;
  int rowlen = nx*spt;
  for (int ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    double xj = *xp + prj->x0;
    double s = prj->w[3]*xj;
    double t = fabs(xj) - tol;

    double *phip   = phi   + rowoff;
    double *thetap = theta + rowoff;
    for (int iy = 0; iy < my; iy++) {
d4611 8
a4618 8
  const double *yp = y;
  double *phip   = phi;
  double *thetap = theta;
  int    *statp  = stat;
  for (int iy = 0; iy < ny; iy++, yp += sxy) {
    double yj = *yp + prj->y0;
    double y0 = yj/prj->r0;
    double r  = 2.0 - y0*y0;
d4620 1
a4620 2
    int istat = 0;
    double s;
d4638 1
a4638 1
    double z = yj*prj->w[2];
d4661 1
a4661 1
    double t = asind(z);
d4663 1
a4663 1
    for (int ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
d4704 2
d4707 4
a4713 2

  int status;
a4717 1
  int mphi, mtheta;
d4729 5
a4733 5
  const double *phip = phi;
  int rowoff = 0;
  int rowlen = nphi*sxy;
  for (int iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    double xi = prj->w[1]*(*phip);
d4735 2
a4736 2
    double *xp = x + rowoff;
    for (int itheta = 0; itheta < mtheta; itheta++) {
d4744 5
a4748 7
  const double *thetap = theta;
  double *xp = x;
  double *yp = y;
  int *statp = stat;
  for (int itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    double xi, eta;

d4758 6
a4763 6
      double u  = PI*sind(*thetap);
      double v0 = -PI;
      double v1 =  PI;
      double v  = u;
      for (int k = 0; k < 100; k++) {
        double resid = (v - u) + sin(v);
d4774 1
a4774 1
      double gamma = v/2.0;
d4780 1
a4780 1
    for (int iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
d4856 2
d4859 4
a4865 2

  int status;
a4869 1
  int mx, my;
d4883 11
a4893 11
  const double *xp = x;
  int rowoff = 0;
  int rowlen = nx*spt;
  for (int ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    double xj = *xp + prj->x0;
    double s  = 1.0 - xj*xj*prj->w[2];
    double t  = xj*prj->w[3];

    double *phip   = phi   + rowoff;
    double *thetap = theta + rowoff;
    for (int iy = 0; iy < my; iy++) {
d4903 7
a4909 7
  const double *yp = y;
  double *phip   = phi;
  double *thetap = theta;
  int    *statp  = stat;
  for (int iy = 0; iy < ny; iy++, yp += sxy) {
    double yj  = *yp + prj->y0;
    double yj2 = yj*yj*prj->w[1];
d4911 2
a4912 2
    for (int ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
      double s = *phip - yj2;
d4914 1
a4914 1
      int istat = 0;
d4924 3
a4926 3
      double z = sqrt(s);
      double x0 = 2.0*z*z - 1.0;
      double y0 = z*(*thetap);
d4933 1
a4933 1
      double t = z*yj/prj->r0;
d4974 7
a4982 2

  int status;
a4986 1
  int mphi, mtheta;
a4996 1
double cosphi, costhe, sinphi, sinthe;
d4998 5
a5002 6
  const double *phip = phi;
  int rowoff = 0;
  int rowlen = nphi*sxy;
  for (int iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    double w = (*phip)/2.0;
    double sinphi, cosphi;
d5005 3
a5007 3
    double *xp = x + rowoff;
    double *yp = y + rowoff;
    for (int itheta = 0; itheta < mtheta; itheta++) {
d5017 5
a5021 6
  const double *thetap = theta;
  double *xp = x;
  double *yp = y;
  int *statp = stat;
  for (int itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    double sinthe, costhe;
d5024 2
a5025 2
    for (int iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
      double w = sqrt(prj->w[0]/(1.0 + costhe*(*yp)));
d5124 6
a5131 2

  int status;
a5135 1
  int mx, my;
d5149 5
a5153 5
  const double *xp = x;
  int rowoff = 0;
  int rowlen = nx*spt;
  for (int ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    double xj = *xp + prj->x0;
d5155 2
a5156 2
    double *phip = phi + rowoff;
    for (int iy = 0; iy < my; iy++) {
d5164 7
a5170 7
  const double *yp = y;
  double *phip   = phi;
  double *thetap = theta;
  int    *statp  = stat;
  for (int iy = 0; iy < ny; iy++, yp += sxy) {
    double dy  = prj->w[2] - (*yp + prj->y0);
    double dy2 = dy*dy;
d5172 2
a5173 2
    for (int ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
      double xj = *phip;
d5175 1
a5175 1
      double r = sqrt(xj*xj + dy2);
a5177 1
      double alpha;
d5214 6
a5221 2

  int status;
a5225 1
  int mphi, mtheta;
d5239 5
a5243 6
  const double *phip = phi;
  int rowoff = 0;
  int rowlen = nphi*sxy;
  for (int iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    double alpha = prj->w[0]*(*phip);
    double sinalpha, cosalpha;
d5246 3
a5248 3
    double *xp = x + rowoff;
    double *yp = y + rowoff;
    for (int itheta = 0; itheta < mtheta; itheta++) {
d5258 8
a5265 8
  const double *thetap = theta;
  double *xp = x;
  double *yp = y;
  int *statp = stat;
  double y0 = prj->y0 - prj->w[2];
  for (int itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    double t = *thetap - prj->pv[1];
    double s = cosd(t);
d5267 1
a5267 2
    int istat = 0;
    double r;
d5298 1
a5298 1
    for (int iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
d5342 2
d5364 2
a5365 2
  double theta1 = prj->pv[1] - prj->pv[2];
  double theta2 = prj->pv[1] + prj->pv[2];
d5404 2
d5407 3
a5412 2

  int status;
a5416 1
  int mx, my;
d5430 5
a5434 5
  const double *xp = x;
  int rowoff = 0;
  int rowlen = nx*spt;
  for (int ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    double xj = *xp + prj->x0;
d5436 2
a5437 2
    double *phip = phi + rowoff;
    for (int iy = 0; iy < my; iy++) {
d5445 7
a5451 7
  const double *yp = y;
  double *phip   = phi;
  double *thetap = theta;
  int    *statp  = stat;
  for (int iy = 0; iy < ny; iy++, yp += sxy) {
    double dy  = prj->w[2] - (*yp + prj->y0);
    double dy2 = dy*dy;
d5453 2
a5454 2
    for (int ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
      double xj = *phip;
d5456 1
a5456 1
      double r = sqrt(xj*xj + dy2);
a5458 1
      double alpha;
d5465 1
a5465 2
      int istat = 0;
      double t;
d5469 1
a5469 1
        double w = (prj->w[6] - r*r)*prj->w[7];
d5515 6
a5522 2

  int status;
a5526 1
  int mphi, mtheta;
d5538 5
a5542 6
  const double *phip = phi;
  int rowoff = 0;
  int rowlen = nphi*sxy;
  for (int iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    double alpha = prj->w[0]*(*phip);
    double sinalpha, cosalpha;
d5545 3
a5547 3
    double *xp = x + rowoff;
    double *yp = y + rowoff;
    for (int itheta = 0; itheta < mtheta; itheta++) {
d5557 6
a5562 7
  const double *thetap = theta;
  double *xp = x;
  double *yp = y;
  int *statp = stat;
  double y0 = prj->y0 - prj->w[2];
  for (int itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    double r;
d5569 1
a5569 1
    for (int iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
d5663 6
a5670 2

  int status;
a5674 1
  int mx, my;
d5688 5
a5692 5
  const double *xp = x;
  int rowoff = 0;
  int rowlen = nx*spt;
  for (int ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    double xj = *xp + prj->x0;
d5694 2
a5695 2
    double *phip = phi + rowoff;
    for (int iy = 0; iy < my; iy++) {
d5703 7
a5709 7
  const double *yp = y;
  double *phip   = phi;
  double *thetap = theta;
  int    *statp  = stat;
  for (int iy = 0; iy < ny; iy++, yp += sxy) {
    double dy  = prj->w[2] - (*yp + prj->y0);
    double dy2 = dy*dy;
d5711 2
a5712 2
    for (int ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
      double xj = *phip;
d5714 1
a5714 1
      double r = sqrt(xj*xj + dy2);
a5716 1
      double alpha;
d5753 6
a5760 2

  int status;
a5764 1
  int mphi, mtheta;
d5776 5
a5780 6
  const double *phip = phi;
  int rowoff = 0;
  int rowlen = nphi*sxy;
  for (int iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    double alpha = prj->w[0]*(*phip);
    double sinalpha, cosalpha;
d5783 3
a5785 3
    double *xp = x + rowoff;
    double *yp = y + rowoff;
    for (int itheta = 0; itheta < mtheta; itheta++) {
d5795 7
a5801 7
  const double *thetap = theta;
  double *xp = x;
  double *yp = y;
  int *statp = stat;
  double y0 = prj->y0 - prj->w[2];
  for (int itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    double r = prj->w[3] - *thetap;
d5803 1
a5803 1
    for (int iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
d5845 2
d5867 2
a5868 2
  double theta1 = prj->pv[1] - prj->pv[2];
  double theta2 = prj->pv[1] + prj->pv[2];
d5870 2
a5871 2
  double tan1 = tand((90.0 - theta1)/2.0);
  double cos1 = cosd(theta1);
d5876 2
a5877 2
    double tan2 = tand((90.0 - theta2)/2.0);
    double cos2 = cosd(theta2);
d5914 6
a5921 2

  int status;
a5925 1
  int mx, my;
d5939 5
a5943 5
  const double *xp = x;
  int rowoff = 0;
  int rowlen = nx*spt;
  for (int ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    double xj = *xp + prj->x0;
d5945 2
a5946 2
    double *phip = phi + rowoff;
    for (int iy = 0; iy < my; iy++) {
d5954 7
a5960 7
  const double *yp = y;
  double *phip   = phi;
  double *thetap = theta;
  int    *statp  = stat;
  for (int iy = 0; iy < ny; iy++, yp += sxy) {
    double dy  = prj->w[2] - (*yp + prj->y0);
    double dy2 = dy*dy;
d5962 2
a5963 2
    for (int ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
      double xj = *phip;
d5965 1
a5965 1
      double r = sqrt(xj*xj + dy2);
a5967 1
      double alpha;
d5974 1
a5974 2
      int istat = 0;
      double t;
d6017 6
a6024 2

  int status;
a6028 1
  int mphi, mtheta;
d6042 5
a6046 6
  const double *phip = phi;
  int rowoff = 0;
  int rowlen = nphi*sxy;
  for (int iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    double alpha = prj->w[0]*(*phip);
    double sinalpha, cosalpha;
d6049 3
a6051 3
    double *xp = x + rowoff;
    double *yp = y + rowoff;
    for (int itheta = 0; itheta < mtheta; itheta++) {
d6061 7
a6067 7
  const double *thetap = theta;
  double *xp = x;
  double *yp = y;
  int *statp = stat;
  double y0 = prj->y0 - prj->w[2];
  for (int itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    int istat = 0;
a6068 1
    double r;
d6079 1
a6079 1
    for (int iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
d6167 7
a6180 1
  int status;
a6184 1
  int mx, my;
d6198 5
a6202 5
  const double *xp = x;
  int rowoff = 0;
  int rowlen = nx*spt;
  for (int ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    double xj = *xp + prj->x0;
d6204 2
a6205 2
    double *phip = phi + rowoff;
    for (int iy = 0; iy < my; iy++) {
d6213 7
a6219 7
  const double *yp = y;
  double *phip   = phi;
  double *thetap = theta;
  int    *statp  = stat;
  for (int iy = 0; iy < ny; iy++, yp += sxy) {
    double dy  = prj->w[2] - (*yp + prj->y0);
    double dy2 = dy*dy;
d6221 2
a6222 2
    for (int ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
      double xj = *phip;
d6224 1
a6224 1
      double r = sqrt(xj*xj + dy2);
a6226 1
      double alpha;
d6233 2
a6234 3
      double s;
      double t = (prj->w[2] - r)/prj->w[1];
      double costhe = cosd(t);
d6271 6
a6283 1
  int status;
a6287 1
  int mphi, mtheta;
d6297 2
d6301 5
a6305 5
  const double *phip = phi;
  int rowoff = 0;
  int rowlen = nphi*sxy;
  for (int iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    double s = prj->r0*(*phip);
d6307 2
a6308 2
    double *xp = x + rowoff;
    for (int itheta = 0; itheta < mtheta; itheta++) {
d6316 10
a6325 12
  const double *thetap = theta;
  double *xp = x;
  double *yp = y;
  int *statp = stat;
  double y0 = prj->y0 - prj->w[2];
  for (int itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    double r = prj->w[2] - prj->w[1]*(*thetap);
    double s = cosd(*thetap)/r;

    for (int iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
      double alpha = s*(*xp);
      double sinalpha, cosalpha;
d6407 3
d6411 4
a6417 2

  int status;
a6421 1
  int mx, my;
d6435 5
a6439 5
  const double *xp = x;
  int rowoff = 0;
  int rowlen = nx*spt;
  for (int ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    double xj = *xp + prj->x0;
d6441 2
a6442 2
    double *phip = phi + rowoff;
    for (int iy = 0; iy < my; iy++) {
d6450 7
a6456 7
  const double *yp = y;
  double *phip   = phi;
  double *thetap = theta;
  int    *statp  = stat;
  for (int iy = 0; iy < ny; iy++, yp += sxy) {
    double yj = *yp + prj->y0;
    double w  = fabs(yj*prj->w[1]);
d6458 2
a6459 2
    for (int ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
      double xj = *phip;
a6469 1
        double the, ymthe, tanthe;
d6478 2
a6479 2
          double thepos = yj / prj->w[0];
          double theneg = 0.0;
d6482 3
a6484 3
          double xx = xj*xj;
          double fpos =  xx;
          double fneg = -xx;
d6486 1
a6486 1
          for (int k = 0; k < 64; k++) {
d6488 1
a6488 1
            double lambda = fpos/(fpos-fneg);
d6499 1
a6499 1
            double f = xx + ymthe*(ymthe - prj->w[2]/tanthe);
d6516 2
a6517 2
        double x1 = prj->r0 - ymthe*tanthe;
        double y1 = xj*tanthe;
d6555 6
a6562 2

  int status;
a6566 1
  int mphi, mtheta;
d6578 6
a6583 6
  const double *phip = phi;
  int rowoff = 0;
  int rowlen = nphi*sxy;
  for (int iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    double *xp = x + rowoff;
    for (int itheta = 0; itheta < mtheta; itheta++) {
d6591 5
a6595 5
  const double *thetap = theta;
  double *xp = x;
  double *yp = y;
  int *statp = stat;
  for (int itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
d6597 1
a6597 1
      for (int iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
d6605 1
a6605 1
      for (int iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
d6612 1
a6612 2
      double therad = (*thetap)*D2R;
      double sinthe, costhe;
d6615 1
a6615 2
      for (int iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
        double sinpsi, cospsi;
d6617 1
a6617 1
        double cotthe = costhe/sinthe;
d6694 7
a6702 2

  int status;
a6706 1
  int mx, my;
d6720 5
a6724 5
  const double *xp = x;
  int rowoff = 0;
  int rowlen = nx*spt;
  for (int ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    double xf = (*xp + prj->x0)*prj->w[1];
d6726 2
a6727 2
    double *phip = phi + rowoff;
    for (int iy = 0; iy < my; iy++) {
d6735 6
a6740 6
  const double *yp = y;
  double *phip   = phi;
  double *thetap = theta;
  int    *statp  = stat;
  for (int iy = 0; iy < ny; iy++, yp += sxy) {
    double yf = (*yp + prj->y0)*prj->w[1];
d6742 2
a6743 2
    for (int ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
      double xf = *phip;
a6767 1
      double l, m, n;
d6840 2
d6843 3
a6848 2

  int status;
a6852 1
  int mphi, mtheta;
d6866 4
a6869 5
  const double *phip = phi;
  int rowoff = 0;
  int rowlen = nphi*sxy;
  for (int iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    double sinphi, cosphi;
d6872 3
a6874 3
    double *xp = x + rowoff;
    double *yp = y + rowoff;
    for (int itheta = 0; itheta < mtheta; itheta++) {
d6884 5
a6888 6
  const double *thetap = theta;
  double *xp = x;
  double *yp = y;
  int *statp = stat;
  for (int itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    double sinthe, costhe;
d6891 4
a6894 4
    for (int iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
      double l = costhe*(*xp);
      double m = costhe*(*yp);
      double n = sinthe;
d6896 2
a6897 2
      int face = 0;
      double zeta = n;
a6918 1
      double xf, yf, x0, y0;
d6959 1
a6959 1
      int istat = 0;
d7050 7
a7087 2

  int status;
a7091 1
  int mx, my;
d7105 5
a7109 5
  const double *xp = x;
  int rowoff = 0;
  int rowlen = nx*spt;
  for (int ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    float xf = (float)((*xp + prj->x0)*prj->w[1]);
d7111 2
a7112 2
    double *phip = phi + rowoff;
    for (int iy = 0; iy < my; iy++) {
d7120 6
a7125 6
  const double *yp = y;
  double *phip   = phi;
  double *thetap = theta;
  int    *statp  = stat;
  for (int iy = 0; iy < ny; iy++, yp += sxy) {
    float yf = (float)((*yp + prj->y0)*prj->w[1]);
d7127 2
a7128 2
    for (int ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
      float xf = (float)(*phip);
a7152 1
      int face = 0;
d7172 2
a7173 2
      float xx  =  xf*xf;
      float yy  =  yf*yf;
a7174 1
      float z0, z1, z2, z3, z4, z5, z6;
a7183 1
      float chi;
a7195 1
      float psi;
d7199 1
a7199 2
      double l, m, n;
      double t = 1.0/sqrt((double)(chi*chi + psi*psi) + 1.0);
d7269 2
d7272 3
d7276 2
a7293 2

  int status;
a7297 1
  int mphi, mtheta;
d7311 4
a7314 5
  const double *phip = phi;
  int rowoff = 0;
  int rowlen = nphi*sxy;
  for (int iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    double sinphi, cosphi;
d7317 3
a7319 3
    double *xp = x + rowoff;
    double *yp = y + rowoff;
    for (int itheta = 0; itheta < mtheta; itheta++) {
d7329 5
a7333 6
  const double *thetap = theta;
  double *xp = x;
  double *yp = y;
  int *statp = stat;
  for (int itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    double sinthe, costhe;
d7336 4
a7339 4
    for (int iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
      double l = costhe*(*xp);
      double m = costhe*(*yp);
      double n = sinthe;
d7341 2
a7342 2
      int face = 0;
      double zeta = n;
a7363 2
      double eta, xi;
      float  x0, y0;
d7404 2
a7405 2
      float chi = (float)( xi/zeta);
      float psi = (float)(eta/zeta);
d7407 4
a7410 4
      float chi2 = chi*chi;
      float psi2 = psi*psi;
      float chi2co = 1.0f - chi2;
      float psi2co = 1.0f - psi2;
d7413 4
a7416 4
      float chipsi = (float)fabs((double)(chi*psi));
      float chi4   = (chi2 > 1.0e-16f) ? chi2*chi2 : 0.0f;
      float psi4   = (psi2 > 1.0e-16f) ? psi2*psi2 : 0.0f;
      float chi2psi2 = (chipsi > 1.0e-16f) ? chi2*psi2 : 0.0f;
a7417 1
      float xf, yf;
d7425 1
a7425 1
      int istat = 0;
d7516 2
d7519 4
a7525 2

  int status;
a7529 1
  int mx, my;
d7543 5
a7547 5
  const double *xp = x;
  int rowoff = 0;
  int rowlen = nx*spt;
  for (int ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    double xf = (*xp + prj->x0)*prj->w[1];
d7549 2
a7550 2
    double *phip = phi + rowoff;
    for (int iy = 0; iy < my; iy++) {
d7558 6
a7563 6
  const double *yp = y;
  double *phip   = phi;
  double *thetap = theta;
  int    *statp  = stat;
  for (int iy = 0; iy < ny; iy++, yp += sxy) {
    double yf = (*yp + prj->y0)*prj->w[1];
d7565 2
a7566 2
    for (int ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
      double xf = *phip;
a7589 1
      int face = 0;
d7610 1
a7610 2
      double omega, tau, w, zeta, zeco;
      int direct = (fabs(xf) > fabs(yf));
a7631 1
          double sinw, cosw;
a7655 1
      double l, m, n;
d7767 3
d7771 4
a7777 2

  int status;
a7781 1
  int mphi, mtheta;
d7795 4
a7798 5
  const double *phip = phi;
  int rowoff = 0;
  int rowlen = nphi*sxy;
  for (int iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    double sinphi, cosphi;
d7801 3
a7803 3
    double *xp = x + rowoff;
    double *yp = y + rowoff;
    for (int itheta = 0; itheta < mtheta; itheta++) {
d7813 5
a7817 6
  const double *thetap = theta;
  double *xp = x;
  double *yp = y;
  int *statp = stat;
  for (int itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    double sinthe, costhe;
d7820 1
a7820 1
    for (int iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
d7828 3
a7830 3
      double l = costhe*(*xp);
      double m = costhe*(*yp);
      double n = sinthe;
d7832 2
a7833 2
      int face = 0;
      double zeta = n;
d7855 1
a7855 1
      double zeco = 1.0 - zeta;
a7856 1
      double xi, eta, x0, y0;
d7863 2
a7864 2
          double t = (*thetap)*D2R;
          double p = atan2(*yp, *xp);
d7875 2
a7876 2
          double t = (*thetap)*D2R;
          double p = atan2(*yp, *xp) - PI/2.0;
d7887 2
a7888 2
          double t = (*thetap)*D2R;
          double p = atan2(*yp, *xp);
d7900 2
a7901 2
          double t = (*thetap)*D2R;
          double p = atan2(*yp, *xp) + PI/2.0;
d7912 1
a7912 1
          double t = (*thetap + 90.0)*D2R;
d7924 1
a7924 1
          double t = (90.0 - *thetap)*D2R;
d7932 2
a7933 3
      double omega, tau;
      double xf = 0.0;
      double yf = 0.0;
d7958 1
a7958 1
      int istat = 0;
d8082 7
a8090 2

  int status;
d8095 3
a8097 1
  int mx, my;
d8111 5
a8115 5
  const double *xp = x;
  int rowoff = 0;
  int rowlen = nx*spt;
  for (int ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    double s = prj->w[1] * (*xp + prj->x0);
a8116 1
    double t;
d8120 3
a8122 3
    double *phip   = phi + rowoff;
    double *thetap = theta + rowoff;
    for (int iy = 0; iy < my; iy++) {
d8133 7
a8139 11
  const double *yp = y;
  double *phip   = phi;
  double *thetap = theta;
  int    *statp  = stat;

  double slim = prj->w[6] + 1e-12;
  double ylim = prj->w[9] * prj->w[4];

  for (int iy = 0; iy < ny; iy++, yp += sxy) {
    double yr = prj->w[1]*(*yp + prj->y0);
    double absy = fabs(yr);
d8141 1
a8141 1
    int istat = 0;
d8144 2
a8145 2
      double t = asind(yr/prj->w[3]);
      for (int ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
d8152 1
a8152 1
      int offset = (prj->n || *yp > 0.0) ? 0 : 1;
d8154 1
a8154 1
      double sigma = prj->w[4] - absy / prj->w[6];
a8155 1
      double s, t;
d8174 1
a8174 1
      for (int ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
d8177 1
a8177 1
          int h = (int)floor(*phip / prj->w[6]) + prj->m;
d8186 1
a8186 1
        double r = s * *thetap;
d8204 1
a8204 1
      for (int ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
d8237 7
a8245 2

  int status;
a8249 1
  int mphi, mtheta;
d8261 5
a8265 5
  const double *phip = phi;
  int rowoff = 0;
  int rowlen = nphi*sxy;
  for (int iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    double xi = prj->w[0] * (*phip) - prj->x0;
a8267 1
    double t;
d8271 3
a8273 3
    double *xp = x + rowoff;
    double *yp = y + rowoff;
    for (int itheta = 0; itheta < mtheta; itheta++) {
d8284 7
a8290 7
  const double *thetap = theta;
  double *xp = x;
  double *yp = y;
  int *statp = stat;
  for (int itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    double sinthe = sind(*thetap);
    double abssin = fabs(sinthe);
a8291 1
    double eta;
d8295 1
a8295 1
      for (int iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
d8302 1
a8302 1
      int offset = (prj->n || *thetap > 0.0) ? 0 : 1;
d8304 2
a8305 2
      double sigma = sqrt(prj->pv[2]*(1.0 - abssin));
      double xi = sigma - 1.0;
d8311 1
a8311 1
      for (int iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
d8314 1
a8314 1
          int h = (int)floor((*xp + prj->x0) / prj->w[9]) + prj->m;
d8415 2
d8418 4
a8424 2

  int status;
a8428 1
  int mx, my;
d8442 5
a8446 5
  const double *xp = x;
  int rowoff = 0;
  int rowlen = nx*spt;
  for (int ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    double xr = (*xp + prj->x0)*prj->w[1];
d8448 2
a8449 2
    double *phip = phi + rowoff;
    for (int iy = 0; iy < my; iy++) {
d8457 6
a8462 6
  const double *yp = y;
  double *phip   = phi;
  double *thetap = theta;
  int    *statp  = stat;
  for (int iy = 0; iy < ny; iy++, yp += sxy) {
    double yr = (*yp + prj->y0)*prj->w[1];
d8464 2
a8465 2
    for (int ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
      double xr = *phip;
a8466 1
      double xi1, eta1;
d8485 3
a8487 3
      double xi  = xi1  + 45.0;
      double eta = eta1 + 90.0;
      double abseta = fabs(eta);
d8494 1
a8494 1
          int istat = 0;
d8508 1
a8508 1
          double sigma = (90.0 - abseta) / 45.0;
d8535 1
a8535 1
          int istat = 0;
d8580 7
a8588 2

  int status;
a8592 1
  int mphi, mtheta;
d8604 4
a8607 6
  const double *phip = phi;
  int rowoff = 0;
  int rowlen = nphi*sxy;

  double chi, psi;
  for (int iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
d8622 3
a8624 3
    double *xp = x + rowoff;
    double *yp = y + rowoff;
    for (int itheta = 0; itheta < mtheta; itheta++) {
d8635 7
a8641 7
  const double *thetap = theta;
  double *xp = x;
  double *yp = y;
  int *statp = stat;
  for (int itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    double sinthe = sind(*thetap);
    double abssin = fabs(sinthe);
d8643 1
a8643 2
    for (int iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
      double xi, eta;
a8650 1
        double sigma;
@


8.2.1.5
log
@Changes required to support bypass mode in prjset() and the specific *set()
functions.
@
text
@d22 1
a22 1
  $Id: prj.c,v 8.2.1.4 2024/05/07 12:15:44 mcalabre Exp mcalabre $
d146 2
a179 2
  prj->flag = 0;

d202 1
a202 1
    return 0;
d216 1
a216 1
  return 0;
a225 1
  // Parameters supplied.
d227 1
a227 1
  wcsprintf("       code: \"%s\"\n", prj->code);
a266 1
  // Derived values.
a279 1
  // Error handling.
a284 1
  // Work arrays.
a296 1
  // Pointers to projection functions.
a386 1
  if (prj->flag < 0) return 0;
d477 1
a477 1
  if (abs(prj->flag) < 100) {
d503 1
a503 1
  if (abs(prj->flag) < 100) {
a578 1
  if (prj->flag == -AZP) return 0;
d580 1
a621 2
  prj->flag = (prj->flag == 1) ? -AZP : AZP;

d646 1
a646 1
  if (abs(prj->flag) != AZP) {
d762 1
a762 1
  if (abs(prj->flag) != AZP) {
a897 1
  if (prj->flag == -SZP) return 0;
d899 1
a938 2
  prj->flag = (prj->flag == 1) ? -SZP : SZP;

d963 1
a963 1
  if (abs(prj->flag) != SZP) {
d1098 1
a1098 1
  if (abs(prj->flag) != SZP) {
a1220 1
  if (prj->flag == -TAN) return 0;
d1222 1
a1238 2
  prj->flag = (prj->flag == 1) ? -TAN : TAN;

d1261 1
a1261 1
  if (abs(prj->flag) != TAN) {
d1345 1
a1345 1
  if (abs(prj->flag) != TAN) {
a1441 1
  if (prj->flag == -STG) return 0;
d1443 1
a1466 2
  prj->flag = (prj->flag == 1) ? -STG : STG;

d1489 1
a1489 1
  if (abs(prj->flag) != STG) {
d1565 1
a1565 1
  if (abs(prj->flag) != STG) {
a1657 1
  if (prj->flag == -SIN) return 0;
d1659 1
a1682 2
  prj->flag = (prj->flag == 1) ? -SIN : SIN;

d1707 1
a1707 1
  if (abs(prj->flag) != SIN) {
d1871 1
a1871 1
  if (abs(prj->flag) != SIN) {
a1993 1
  if (prj->flag == -ARC) return 0;
d1995 1
a2018 2
  prj->flag = (prj->flag == 1) ? -ARC : ARC;

d2041 1
a2041 1
  if (abs(prj->flag) != ARC) {
d2126 1
a2126 1
  if (abs(prj->flag) != ARC) {
a2206 1
  if (prj->flag == -ZPN) return 0;
d2209 1
a2300 2
  prj->flag = (prj->flag == 1) ? -ZPN : ZPN;

d2325 1
a2325 1
  if (abs(prj->flag) != ZPN) {
d2513 1
a2513 1
  if (abs(prj->flag) != ZPN) {
a2604 1
  if (prj->flag == -ZEA) return 0;
d2606 1
a2629 2
  prj->flag = (prj->flag == 1) ? -ZEA : ZEA;

d2654 1
a2654 1
  if (abs(prj->flag) != ZEA) {
d2751 1
a2751 1
  if (abs(prj->flag) != ZEA) {
a2837 1
  if (prj->flag == -AIR) return 0;
d2839 1
a2873 2
  prj->flag = (prj->flag == 1) ? -AIR : AIR;

d2898 1
a2898 1
  if (abs(prj->flag) != AIR) {
d3045 1
a3045 1
  if (abs(prj->flag) != AIR) {
a3147 1
  if (prj->flag == -CYP) return 0;
d3149 1
a3198 2
  prj->flag = (prj->flag == 1) ? -CYP : CYP;

d3221 1
a3221 1
  if (abs(prj->flag) != CYP) {
d3295 1
a3295 1
  if (abs(prj->flag) != CYP) {
a3381 1
  if (prj->flag == -CEA) return 0;
d3383 1
a3418 2
  prj->flag = (prj->flag == 1) ? -CEA : CEA;

d3443 1
a3443 1
  if (abs(prj->flag) != CEA) {
d3529 1
a3529 1
  if (abs(prj->flag) != CEA) {
a3597 1
  if (prj->flag == -CAR) return 0;
d3599 1
a3622 2
  prj->flag = (prj->flag == 1) ? -CAR : CAR;

d3645 1
a3645 1
  if (abs(prj->flag) != CAR) {
d3718 1
a3718 1
  if (abs(prj->flag) != CAR) {
a3786 1
  if (prj->flag == -MER) return 0;
d3788 1
a3811 2
  prj->flag = (prj->flag == 1) ? -MER : MER;

d3834 1
a3834 1
  if (abs(prj->flag) != MER) {
d3907 1
a3907 1
  if (abs(prj->flag) != MER) {
a3986 1
  if (prj->flag == -SFL) return 0;
d3988 1
a4011 2
  prj->flag = (prj->flag == 1) ? -SFL : SFL;

d4034 1
a4034 1
  if (abs(prj->flag) != SFL) {
d4120 1
a4120 1
  if (abs(prj->flag) != SFL) {
a4193 1
  if (prj->flag == -PAR) return 0;
d4195 1
a4222 2
  prj->flag = (prj->flag == 1) ? -PAR : PAR;

d4247 1
a4247 1
  if (abs(prj->flag) != PAR) {
d4357 1
a4357 1
  if (abs(prj->flag) != PAR) {
a4431 1
  if (prj->flag == -MOL) return 0;
d4433 1
a4455 2
  prj->flag = (prj->flag == 1) ? -MOL : MOL;

d4480 1
a4480 1
  if (abs(prj->flag) != MOL) {
d4618 1
a4618 1
  if (abs(prj->flag) != MOL) {
a4721 1
  if (prj->flag == -AIT) return 0;
d4723 1
a4744 2
  prj->flag = (prj->flag == 1) ? -AIT : AIT;

d4769 1
a4769 1
  if (abs(prj->flag) != AIT) {
d4882 1
a4882 1
  if (abs(prj->flag) != AIT) {
a4969 1
  if (prj->flag == -COP) return 0;
d4971 1
d4973 1
a4980 1
  strcpy(prj->name, "conic perspective");
a5008 2
  prj->flag = (prj->flag == 1) ? -COP : COP;

d5031 1
a5031 1
  if (abs(prj->flag) != COP) {
d5119 1
a5119 1
  if (abs(prj->flag) != COP) {
a5242 1
  if (prj->flag == -COE) return 0;
d5244 1
d5246 1
a5253 1
  strcpy(prj->name, "conic equal area");
a5283 2
  prj->flag = (prj->flag == 1) ? -COE : COE;

d5308 1
a5308 1
  if (abs(prj->flag) != COE) {
d5417 1
a5417 1
  if (abs(prj->flag) != COE) {
a5505 1
  if (prj->flag == -COD) return 0;
d5507 1
d5509 1
a5516 1
  strcpy(prj->name, "conic equidistant");
a5541 2
  prj->flag = (prj->flag == 1) ? -COD : COD;

d5564 1
a5564 1
  if (abs(prj->flag) != COD) {
d5652 1
a5652 1
  if (abs(prj->flag) != COD) {
a5738 1
  if (prj->flag == -COO) return 0;
d5740 1
d5742 1
a5749 1
  strcpy(prj->name, "conic orthomorphic");
a5786 2
  prj->flag = (prj->flag == 1) ? -COO : COO;

d5809 1
a5809 1
  if (abs(prj->flag) != COO) {
d5911 1
a5911 1
  if (abs(prj->flag) != COO) {
a6003 1
  if (prj->flag == -BON) return 0;
d6005 1
d6007 1
a6017 1
  strcpy(prj->name, "Bonne's");
a6037 2
  prj->flag = (prj->flag == 1) ? -BON : BON;

d6064 1
a6064 1
  if (abs(prj->flag) != BON) {
d6165 1
a6165 1
  if (abs(prj->flag) != BON) {
a6242 1
  if (prj->flag == -PCO) return 0;
d6244 1
a6270 2
  prj->flag = (prj->flag == 1) ? -PCO : PCO;

d6295 1
a6295 1
  if (abs(prj->flag) != PCO) {
d6438 1
a6438 1
  if (abs(prj->flag) != PCO) {
a6528 1
  if (prj->flag == -TSC) return 0;
d6530 1
a6553 2
  prj->flag = (prj->flag == 1) ? -TSC : TSC;

d6576 1
a6576 1
  if (abs(prj->flag) != TSC) {
d6721 1
a6721 1
  if (abs(prj->flag) != TSC) {
a6882 1
  if (prj->flag == -CSC) return 0;
d6884 1
a6907 2
  prj->flag = (prj->flag == 1) ? -CSC : CSC;

d6959 1
a6959 1
  if (abs(prj->flag) != CSC) {
d7166 1
a7166 1
  if (abs(prj->flag) != CSC) {
a7350 1
  if (prj->flag == -QSC) return 0;
d7352 1
a7375 2
  prj->flag = (prj->flag == 1) ? -QSC : QSC;

d7400 1
a7400 1
  if (abs(prj->flag) != QSC) {
d7652 1
a7652 1
  if (abs(prj->flag) != QSC) {
a7898 1
  if (prj->flag == -HPX) return 0;
d7900 1
a7942 2
  prj->flag = (prj->flag == 1) ? -HPX : HPX;

d7965 1
a7965 1
  if (abs(prj->flag) != HPX) {
d8119 1
a8119 1
  if (abs(prj->flag) != HPX) {
a8239 1
  if (prj->flag == -XPH) return 0;
d8241 1
a8272 2
  prj->flag = (prj->flag == 1) ? -XPH : XPH;

d8297 1
a8297 1
  if (abs(prj->flag) != XPH) {
d8458 1
a8458 1
  if (abs(prj->flag) != XPH) {
@


8.2.1.6
log
@Added prjenq().
@
text
@d22 1
a22 1
  $Id: prj.c,v 8.2.1.5 2024/05/08 08:47:50 mcalabre Exp mcalabre $
a216 26
}

//----------------------------------------------------------------------------

int prjenq(const struct prjprm *prj, int enquiry)

{
  static const char *function = "prjenq";

  // Initialize.
  if (prj == 0x0) return PRJERR_NULL_POINTER;

  int answer = 0;
  int absflag = abs(prj->flag);

  if (enquiry & PRJENQ_SET) {
    if (absflag < 100 || 1000 < absflag) return 0;
    answer = 1;
  }

  if (enquiry & PRJENQ_BYP) {
    if (0 < prj->flag || absflag < 100 || 1000 < absflag) return 0;
    answer = 1;
  }

  return answer;
@


8.2.1.7
log
@Attended to compiler warnings about unused variables.
@
text
@d22 1
a22 1
  $Id: prj.c,v 8.2.1.6 2024/05/08 15:14:58 mcalabre Exp mcalabre $
d224 2
d4963 1
@


8.2.1.8
log
@In prjenq(), fixed the test for bypass mode.  The prjprm struct is also in
bypass mode, though unset, if disprm::flag == 1.
@
text
@d22 1
a22 1
  $Id: prj.c,v 8.2.1.7 2024/05/08 15:39:34 mcalabre Exp mcalabre $
d236 1
a236 1
    if (prj->flag != 1 && !(-1000 < prj->flag && prj->flag < -100)) return 0;
@


8.1
log
@WCSLIB 8.1
@
text
@d2 1
a2 1
  WCSLIB 8.1 - an implementation of the FITS WCS standard.
d22 1
a22 1
  $Id: prj.c,v 8.0.1.1 2023/07/01 06:22:44 mcalabre Exp mcalabre $
@


8.1.1.1
log
@WCSLIB 8.1 development branch.
@
text
@d22 1
a22 1
  $Id: prj.c,v 8.1 2023/07/05 17:12:07 mcalabre Exp $
@


8.0
log
@WCSLIB 8.0
@
text
@d2 1
a2 1
  WCSLIB 8.0 - an implementation of the FITS WCS standard.
d22 1
a22 1
  $Id: prj.c,v 7.13.1.2 2023/06/15 04:17:19 mcalabre Exp mcalabre $
@


8.0.1.1
log
@WCSLIB 8.0 development branch.
@
text
@d22 1
a22 1
  $Id: prj.c,v 8.0 2023/07/01 06:15:04 mcalabre Exp $
@


7.13
log
@WCSLIB 7.13
@
text
@d2 2
a3 2
  WCSLIB 7.13 - an implementation of the FITS WCS standard.
  Copyright (C) 1995-2022, Mark Calabretta
d22 1
a22 1
  $Id: prj.c,v 7.12.1.1 2022/09/09 05:00:36 mcalabre Exp mcalabre $
@


7.13.1.1
log
@WCSLIB 7.13 development branch.
@
text
@d22 1
a22 1
  $Id: prj.c,v 7.13 2022/10/07 03:43:35 mcalabre Exp $
@


7.13.1.2
log
@Updated date in copyright notice.
@
text
@d3 1
a3 1
  Copyright (C) 1995-2023, Mark Calabretta
d22 1
a22 1
  $Id: prj.c,v 7.13.1.1 2022/10/07 03:45:47 mcalabre Exp mcalabre $
@


7.12
log
@WCSLIB 7.12
@
text
@d2 1
a2 1
  WCSLIB 7.12 - an implementation of the FITS WCS standard.
d22 1
a22 1
  $Id: prj.c,v 7.11.1.2 2022/09/04 07:16:21 mcalabre Exp mcalabre $
@


7.12.1.1
log
@WCSLIB 7.12 development branch.
@
text
@d22 1
a22 1
  $Id: prj.c,v 7.12 2022/09/09 04:57:58 mcalabre Exp $
@


7.11
log
@WCSLIB 7.11
@
text
@d2 1
a2 1
  WCSLIB 7.11 - an implementation of the FITS WCS standard.
d22 1
a22 1
  $Id: prj.c,v 7.10.1.1 2022/04/23 14:26:54 mcalabre Exp mcalabre $
d703 1
a703 1
    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
d710 1
a710 1
        *(statp++) = 0;
d723 1
a723 1
            *(statp++) = 1;
d739 1
a739 1
        *(statp++) = 0;
d819 1
a819 1
    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
d826 1
a826 1
        *(statp++) = 1;
d863 1
a863 1
        *(statp++) = istat;
d1017 1
a1017 1
    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
d1041 1
a1041 1
          *(statp++) = 1;
d1068 1
a1068 1
          *(statp++) = 1;
d1079 1
a1079 1
      *(statp++) = 0;
d1160 1
a1160 1
      for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
d1163 1
a1163 1
        *(statp++) = 1;
d1173 1
a1173 1
      for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
d1206 1
a1206 1
        *(statp++) = istat;
d1321 1
a1321 1
    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
d1332 1
a1332 1
      *(statp++) = 0;
d1411 1
a1411 1
      for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
d1414 1
a1414 1
        *(statp++) = 1;
d1430 1
a1430 1
      for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
d1433 1
a1433 1
        *(statp++) = istat;
d1554 1
a1554 1
    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
d1565 1
a1565 1
      *(statp++) = 0;
d1638 1
a1638 1
      for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
d1641 1
a1641 1
        *(statp++) = 1;
d1648 1
a1648 1
      for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
d1651 1
a1651 1
        *(statp++) = 0;
d1784 1
a1784 1
    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
d1802 1
a1802 1
          *(statp++) = 1;
d1826 1
a1826 1
            *(statp++) = 1;
d1853 1
a1853 1
            *(statp++) = 1;
d1871 1
a1871 1
      *(statp++) = 0;
d1972 1
a1972 1
      for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
d1975 1
a1975 1
        *(statp++) = istat;
d1984 1
a1984 1
      for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
d1996 1
a1996 1
        *(statp++) = istat;
d2119 1
a2119 1
    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
d2131 1
a2131 1
      *(statp++) = 0;
d2208 1
a2208 1
    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
d2211 1
a2211 1
      *(statp++) = 0;
d2407 1
a2407 1
    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
d2434 1
a2434 1
          *(statp++) = 1;
d2448 1
a2448 1
            *(statp++) = 1;
d2456 1
a2456 1
            *(statp++) = 1;
d2472 1
a2472 1
            *(statp++) = 1;
d2480 1
a2480 1
            *(statp++) = 1;
d2518 1
a2518 1
      *(statp++) = 0;
d2612 1
a2612 1
    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
d2615 1
a2615 1
      *(statp++) = istat;
d2738 1
a2738 1
    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
d2754 1
a2754 1
          *(statp++) = 1;
d2762 1
a2762 1
      *(statp++) = 0;
d2839 1
a2839 1
    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
d2842 1
a2842 1
      *(statp++) = 0;
d2989 1
a2989 1
    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
d3019 1
a3019 1
          *(statp++) = 1;
d3049 1
a3049 1
          *(statp++) = 1;
d3058 1
a3058 1
      *(statp++) = 0;
d3154 1
a3154 1
    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
d3157 1
a3157 1
      *(statp++) = istat;
d3312 1
a3312 1
    for (ix = 0; ix < mx; ix++, thetap += spt) {
d3314 1
a3314 1
      *(statp++) = 0;
d3399 1
a3399 1
    for (iphi = 0; iphi < mphi; iphi++, yp += sxy) {
d3401 1
a3401 1
      *(statp++) = istat;
d3553 1
a3553 1
    for (ix = 0; ix < mx; ix++, thetap += spt) {
d3555 1
a3555 1
      *(statp++) = istat;
d3628 1
a3628 1
    for (iphi = 0; iphi < mphi; iphi++, yp += sxy) {
d3630 1
a3630 1
      *(statp++) = 0;
d3750 1
a3750 1
    for (ix = 0; ix < mx; ix++, thetap += spt) {
d3752 1
a3752 1
      *(statp++) = 0;
d3825 1
a3825 1
    for (iphi = 0; iphi < mphi; iphi++, yp += sxy) {
d3827 1
a3827 1
      *(statp++) = 0;
d3947 1
a3947 1
    for (ix = 0; ix < mx; ix++, thetap += spt) {
d3949 1
a3949 1
      *(statp++) = 0;
d4032 1
a4032 1
    for (iphi = 0; iphi < mphi; iphi++, yp += sxy) {
d4034 1
a4034 1
      *(statp++) = istat;
d4166 1
a4166 1
    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
d4169 1
a4169 1
      *(statp++) = istat;
d4244 1
a4244 1
    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
d4247 1
a4247 1
      *(statp++) = 0;
d4399 1
a4399 1
    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
d4402 1
a4402 1
          *(statp++) = 0;
d4404 1
a4404 1
          *(statp++) = 1;
d4408 1
a4408 1
        *(statp++) = istat;
d4488 1
a4488 1
    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
d4491 1
a4491 1
      *(statp++) = 0;
d4664 1
a4664 1
    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
d4667 1
a4667 1
          *(statp++) = 0;
d4669 1
a4669 1
          *(statp++) = 1;
d4673 1
a4673 1
        *(statp++) = istat;
d4781 1
a4781 1
    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
d4784 1
a4784 1
      *(statp++) = 0;
d4912 1
a4912 1
    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
d4947 1
a4947 1
      *(statp++) = istat;
d5025 1
a5025 1
    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
d5029 1
a5029 1
      *(statp++) = 0;
d5173 1
a5173 1
    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
d5187 1
a5187 1
      *(statp++) = 0;
d5299 1
a5299 1
    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
d5302 1
a5302 1
      *(statp++) = istat;
d5454 1
a5454 1
    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
d5488 1
a5488 1
      *(statp++) = istat;
d5570 1
a5570 1
    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
d5573 1
a5573 1
      *(statp++) = 0;
d5712 1
a5712 1
    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
d5726 1
a5726 1
      *(statp++) = 0;
d5804 1
a5804 1
    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
d5807 1
a5807 1
      *(statp++) = 0;
d5963 1
a5963 1
    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
d5990 1
a5990 1
      *(statp++) = istat;
d6080 1
a6080 1
    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
d6083 1
a6083 1
      *(statp++) = istat;
d6222 1
a6222 1
    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
d6244 1
a6244 1
      *(statp++) = 0;
d6325 1
a6325 1
    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
d6330 1
a6330 1
      *(statp++) = 0;
d6459 1
a6459 1
    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
d6528 1
a6528 1
      *(statp++) = 0;
d6598 1
a6598 1
      for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
d6601 1
a6601 1
        *(statp++) = 0;
d6606 1
a6606 1
      for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
d6609 1
a6609 1
        *(statp++) = 0;
d6616 1
a6616 1
      for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
d6621 1
a6621 1
        *(statp++) = 0;
d6743 1
a6743 1
    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
d6751 1
a6751 1
          *(statp++) = 1;
d6759 1
a6759 1
          *(statp++) = 1;
d6813 1
a6813 1
      *(statp++) = 0;
d6892 1
a6892 1
    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
d6978 1
a6978 1
      *(statp++) = istat;
d7128 1
a7128 1
    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
d7136 1
a7136 1
          *(statp++) = 1;
d7144 1
a7144 1
          *(statp++) = 1;
d7242 1
a7242 1
      *(statp++) = 0;
d7337 1
a7337 1
    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
d7444 1
a7444 1
      *(statp++) = istat;
d7566 1
a7566 1
    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
d7574 1
a7574 1
          *(statp++) = 1;
d7582 1
a7582 1
          *(statp++) = 1;
d7645 1
a7645 1
          *(statp++) = 1;
d7740 1
a7740 1
      *(statp++) = 0;
d7821 1
a7821 1
    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
d7825 1
a7825 1
        *(statp++) = 0;
d7977 1
a7977 1
      *(statp++) = istat;
d8146 1
a8146 1
      for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
d8148 1
a8148 1
        *(statp++) = 0;
d8175 1
a8175 1
      for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
d8200 1
a8200 2

        *(statp++) = istat;
d8205 1
a8205 1
      for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
d8208 1
a8208 1
        *(statp++) = 1;
d8296 1
a8296 1
      for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
d8298 1
a8298 1
        *(statp++) = 0;
d8312 1
a8312 1
      for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
d8326 1
a8326 1
        *(statp++) = 0;
d8465 1
a8465 1
    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
d8505 1
a8505 1
          *(statp++) = istat;
d8544 1
a8544 1
          *(statp++) = istat;
d8551 1
a8551 1
        *(statp++) = 1;
d8644 1
a8644 1
    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
d8684 1
a8684 1
      *(statp++) = 0;
@


7.11.1.1
log
@WCSLIB 7.11 development branch.
@
text
@d22 1
a22 1
  $Id: prj.c,v 7.11 2022/04/26 06:13:52 mcalabre Exp $
@


7.11.1.2
log
@Increment the statp pointer within the for loop control statement as it
seems simpler and more consistent with the way the other pointers are
incremented.
@
text
@d22 1
a22 1
  $Id: prj.c,v 7.11.1.1 2022/04/26 06:15:32 mcalabre Exp mcalabre $
d703 1
a703 1
    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
d710 1
a710 1
        *statp  = 0;
d723 1
a723 1
            *statp  = 1;
d739 1
a739 1
        *statp  = 0;
d819 1
a819 1
    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
d826 1
a826 1
        *statp = 1;
d863 1
a863 1
        *statp = istat;
d1017 1
a1017 1
    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
d1041 1
a1041 1
          *statp  = 1;
d1068 1
a1068 1
          *statp  = 1;
d1079 1
a1079 1
      *statp = 0;
d1160 1
a1160 1
      for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
d1163 1
a1163 1
        *statp = 1;
d1173 1
a1173 1
      for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
d1206 1
a1206 1
        *statp = istat;
d1321 1
a1321 1
    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
d1332 1
a1332 1
      *statp  = 0;
d1411 1
a1411 1
      for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
d1414 1
a1414 1
        *statp = 1;
d1430 1
a1430 1
      for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
d1433 1
a1433 1
        *statp = istat;
d1554 1
a1554 1
    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
d1565 1
a1565 1
      *statp  = 0;
d1638 1
a1638 1
      for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
d1641 1
a1641 1
        *statp = 1;
d1648 1
a1648 1
      for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
d1651 1
a1651 1
        *statp = 0;
d1784 1
a1784 1
    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
d1802 1
a1802 1
          *statp = 1;
d1826 1
a1826 1
            *statp  = 1;
d1853 1
a1853 1
            *statp  = 1;
d1871 1
a1871 1
      *statp = 0;
d1972 1
a1972 1
      for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
d1975 1
a1975 1
        *statp = istat;
d1984 1
a1984 1
      for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
d1996 1
a1996 1
        *statp = istat;
d2119 1
a2119 1
    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
d2131 1
a2131 1
      *statp = 0;
d2208 1
a2208 1
    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
d2211 1
a2211 1
      *statp = 0;
d2407 1
a2407 1
    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
d2434 1
a2434 1
          *statp  = 1;
d2448 1
a2448 1
            *statp  = 1;
d2456 1
a2456 1
            *statp  = 1;
d2472 1
a2472 1
            *statp  = 1;
d2480 1
a2480 1
            *statp  = 1;
d2518 1
a2518 1
      *statp  = 0;
d2612 1
a2612 1
    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
d2615 1
a2615 1
      *statp = istat;
d2738 1
a2738 1
    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
d2754 1
a2754 1
          *statp  = 1;
d2762 1
a2762 1
      *statp = 0;
d2839 1
a2839 1
    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
d2842 1
a2842 1
      *statp = 0;
d2989 1
a2989 1
    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
d3019 1
a3019 1
          *statp  = 1;
d3049 1
a3049 1
          *statp  = 1;
d3058 1
a3058 1
      *statp  = 0;
d3154 1
a3154 1
    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
d3157 1
a3157 1
      *statp = istat;
d3312 1
a3312 1
    for (ix = 0; ix < mx; ix++, thetap += spt, statp++) {
d3314 1
a3314 1
      *statp  = 0;
d3399 1
a3399 1
    for (iphi = 0; iphi < mphi; iphi++, yp += sxy, statp++) {
d3401 1
a3401 1
      *statp = istat;
d3553 1
a3553 1
    for (ix = 0; ix < mx; ix++, thetap += spt, statp++) {
d3555 1
a3555 1
      *statp  = istat;
d3628 1
a3628 1
    for (iphi = 0; iphi < mphi; iphi++, yp += sxy, statp++) {
d3630 1
a3630 1
      *statp = 0;
d3750 1
a3750 1
    for (ix = 0; ix < mx; ix++, thetap += spt, statp++) {
d3752 1
a3752 1
      *statp  = 0;
d3825 1
a3825 1
    for (iphi = 0; iphi < mphi; iphi++, yp += sxy, statp++) {
d3827 1
a3827 1
      *statp = 0;
d3947 1
a3947 1
    for (ix = 0; ix < mx; ix++, thetap += spt, statp++) {
d3949 1
a3949 1
      *statp  = 0;
d4032 1
a4032 1
    for (iphi = 0; iphi < mphi; iphi++, yp += sxy, statp++) {
d4034 1
a4034 1
      *statp = istat;
d4166 1
a4166 1
    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
d4169 1
a4169 1
      *statp  = istat;
d4244 1
a4244 1
    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
d4247 1
a4247 1
      *statp = 0;
d4399 1
a4399 1
    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
d4402 1
a4402 1
          *statp = 0;
d4404 1
a4404 1
          *statp = 1;
d4408 1
a4408 1
        *statp = istat;
d4488 1
a4488 1
    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
d4491 1
a4491 1
      *statp = 0;
d4664 1
a4664 1
    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
d4667 1
a4667 1
          *statp = 0;
d4669 1
a4669 1
          *statp = 1;
d4673 1
a4673 1
        *statp = istat;
d4781 1
a4781 1
    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
d4784 1
a4784 1
      *statp = 0;
d4912 1
a4912 1
    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
d4947 1
a4947 1
      *statp  = istat;
d5025 1
a5025 1
    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
d5029 1
a5029 1
      *statp = 0;
d5173 1
a5173 1
    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
d5187 1
a5187 1
      *statp  = 0;
d5299 1
a5299 1
    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
d5302 1
a5302 1
      *statp = istat;
d5454 1
a5454 1
    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
d5488 1
a5488 1
      *statp  = istat;
d5570 1
a5570 1
    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
d5573 1
a5573 1
      *statp = 0;
d5712 1
a5712 1
    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
d5726 1
a5726 1
      *statp  = 0;
d5804 1
a5804 1
    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
d5807 1
a5807 1
      *statp = 0;
d5963 1
a5963 1
    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
d5990 1
a5990 1
      *statp  = istat;
d6080 1
a6080 1
    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
d6083 1
a6083 1
      *statp = istat;
d6222 1
a6222 1
    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
d6244 1
a6244 1
      *statp  = 0;
d6325 1
a6325 1
    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
d6330 1
a6330 1
      *statp = 0;
d6459 1
a6459 1
    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
d6528 1
a6528 1
      *statp = 0;
d6598 1
a6598 1
      for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
d6601 1
a6601 1
        *statp = 0;
d6606 1
a6606 1
      for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
d6609 1
a6609 1
        *statp = 0;
d6616 1
a6616 1
      for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
d6621 1
a6621 1
        *statp = 0;
d6743 1
a6743 1
    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
d6751 1
a6751 1
          *statp  = 1;
d6759 1
a6759 1
          *statp  = 1;
d6813 1
a6813 1
      *statp  = 0;
d6892 1
a6892 1
    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
d6978 1
a6978 1
      *statp = istat;
d7128 1
a7128 1
    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
d7136 1
a7136 1
          *statp  = 1;
d7144 1
a7144 1
          *statp  = 1;
d7242 1
a7242 1
      *statp  = 0;
d7337 1
a7337 1
    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
d7444 1
a7444 1
      *statp = istat;
d7566 1
a7566 1
    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
d7574 1
a7574 1
          *statp  = 1;
d7582 1
a7582 1
          *statp  = 1;
d7645 1
a7645 1
          *statp  = 1;
d7740 1
a7740 1
      *statp  = 0;
d7821 1
a7821 1
    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
d7825 1
a7825 1
        *statp = 0;
d7977 1
a7977 1
      *statp = istat;
d8146 1
a8146 1
      for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
d8148 1
a8148 1
        *statp  = 0;
d8175 1
a8175 1
      for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
d8200 2
a8201 1
        *statp  = istat;
d8206 1
a8206 1
      for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
d8209 1
a8209 1
        *statp  = 1;
d8297 1
a8297 1
      for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
d8299 1
a8299 1
        *statp = 0;
d8313 1
a8313 1
      for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
d8327 1
a8327 1
        *statp = 0;
d8466 1
a8466 1
    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt, statp++) {
d8506 1
a8506 1
          *statp = istat;
d8545 1
a8545 1
          *statp = istat;
d8552 1
a8552 1
        *statp  = 1;
d8645 1
a8645 1
    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy, statp++) {
d8685 1
a8685 1
      *statp = 0;
@


7.10
log
@WCSLIB 7.10
@
text
@d2 1
a2 1
  WCSLIB 7.10 - an implementation of the FITS WCS standard.
d22 1
a22 1
  $Id: prj.c,v 7.9.1.1 2022/03/25 15:16:40 mcalabre Exp mcalabre $
@


7.10.1.1
log
@WCSLIB 7.10 development branch.
@
text
@d22 1
a22 1
  $Id: prj.c,v 7.10 2022/04/23 14:25:15 mcalabre Exp $
@


7.9
log
@WCSLIB 7.9
@
text
@d2 1
a2 1
  WCSLIB 7.9 - an implementation of the FITS WCS standard.
d22 1
a22 1
  $Id: prj.c,v 7.8.1.1 2022/03/25 06:14:14 mcalabre Exp mcalabre $
@


7.9.1.1
log
@WCSLIB 7.9 development branch.
@
text
@d22 1
a22 1
  $Id: prj.c,v 7.9 2022/03/25 15:14:48 mcalabre Exp $
@


7.8
log
@WCSLIB 7.8
@
text
@d2 1
a2 1
  WCSLIB 7.8 - an implementation of the FITS WCS standard.
d22 1
a22 1
  $Id: prj.c,v 7.7.1.2 2022/03/25 06:05:59 mcalabre Exp mcalabre $
@


7.8.1.1
log
@WCSLIB 7.8 development branch.
@
text
@d22 1
a22 1
  $Id: prj.c,v 7.8 2022/03/25 06:11:49 mcalabre Exp $
@


7.7
log
@WCSLIB 7.7
@
text
@d2 2
a3 2
  WCSLIB 7.7 - an implementation of the FITS WCS standard.
  Copyright (C) 1995-2021, Mark Calabretta
d22 1
a22 1
  $Id: prj.c,v 7.6.1.1 2021/04/13 13:00:35 mcalabre Exp mcalabre $
@


7.7.1.1
log
@WCSLIB 7.7 development branch.
@
text
@d22 1
a22 1
  $Id: prj.c,v 7.7 2021/07/12 06:36:49 mcalabre Exp $
@


7.7.1.2
log
@Updated date in copyright notice.
@
text
@d3 1
a3 1
  Copyright (C) 1995-2022, Mark Calabretta
d22 1
a22 1
  $Id: prj.c,v 7.7.1.1 2021/07/12 06:38:27 mcalabre Exp mcalabre $
@


7.6
log
@WCSLIB 7.6
@
text
@d2 1
a2 1
  WCSLIB 7.6 - an implementation of the FITS WCS standard.
d22 1
a22 1
  $Id: prj.c,v 7.5.1.2 2021/04/13 09:21:05 mcalabre Exp mcalabre $
@


7.6.1.1
log
@WCSLIB 7.6 development branch.
@
text
@d22 1
a22 1
  $Id: prj.c,v 7.6 2021/04/13 12:57:01 mcalabre Exp $
@


7.5
log
@WCSLIB 7.5
@
text
@d2 1
a2 1
  WCSLIB 7.5 - an implementation of the FITS WCS standard.
d22 1
a22 1
  $Id: prj.c,v 7.4.1.1 2021/01/31 02:26:24 mcalabre Exp mcalabre $
d124 2
d196 25
@


7.5.1.1
log
@WCSLIB 7.5 development branch.
@
text
@d22 1
a22 1
  $Id: prj.c,v 7.5 2021/03/20 05:54:58 mcalabre Exp $
@


7.5.1.2
log
@Added new function prjsize().
@
text
@d22 1
a22 1
  $Id: prj.c,v 7.5.1.1 2021/03/20 05:56:42 mcalabre Exp mcalabre $
a123 2
* prjsize computed the size of a prjprm struct.
*
a193 25
}

//----------------------------------------------------------------------------

int prjsize(const struct prjprm *prj, int sizes[2])

{
  if (prj == 0x0) {
    sizes[0] = sizes[1] = 0;
    return PRJERR_SUCCESS;
  }

  // Base size, in bytes.
  sizes[0] = sizeof(struct prjprm);

  // Total size of allocated memory, in bytes.
  sizes[1] = 0;

  int exsizes[2];

  // prjprm::err.
  wcserr_size(prj->err, exsizes);
  sizes[1] += exsizes[0] + exsizes[1];

  return PRJERR_SUCCESS;
@


7.4
log
@WCSLIB 7.4
@
text
@d2 1
a2 1
  WCSLIB 7.4 - an implementation of the FITS WCS standard.
d22 1
a22 1
  $Id: prj.c,v 7.3.1.4 2021/01/28 12:29:30 mcalabre Exp mcalabre $
@


7.4.1.1
log
@WCSLIB 7.4 development branch.
@
text
@d22 1
a22 1
  $Id: prj.c,v 7.4 2021/01/31 02:24:51 mcalabre Exp $
@


7.3
log
@WCSLIB 7.3
@
text
@d2 2
a3 3

  WCSLIB 7.3 - an implementation of the FITS WCS standard.
  Copyright (C) 1995-2020, Mark Calabretta
a19 2
  Direct correspondence concerning WCSLIB to mark@@calabretta.id.au

d22 1
a22 1
  $Id: prj.c,v 7.2.1.1 2020/03/09 07:34:50 mcalabre Exp mcalabre $
d38 1
a38 1
/* Projection categories. */
d53 1
a53 1
/* Projection codes. */
d90 1
a90 1
/* Map status return value to message. */
d98 1
a98 1
/* Convenience macros for generating common error messages. */
d184 1
a184 1
/*--------------------------------------------------------------------------*/
d196 1
a196 1
/*--------------------------------------------------------------------------*/
d284 1
a284 1
/*--------------------------------------------------------------------------*/
d298 1
a298 1
/*--------------------------------------------------------------------------*/
d319 1
a319 1
      /* Skip values already marked as illegal. */
d359 1
a359 1
/*--------------------------------------------------------------------------*/
d372 1
a372 1
  /* Invoke the relevant initialization routine. */
d431 1
a431 1
    /* Unrecognized projection code. */
d439 1
a439 1
/*--------------------------------------------------------------------------*/
d456 1
a456 1
  /* Initialize. */
d465 1
a465 1
/*--------------------------------------------------------------------------*/
d482 1
a482 1
  /* Initialize. */
d511 1
a511 1
    /* Set both to the projection-specific default if either undefined. */
d607 1
a607 1
/*--------------------------------------------------------------------------*/
d630 1
a630 1
  /* Initialize. */
d648 1
a648 1
  /* Do x dependence. */
d663 1
a663 1
  /* Do y dependence. */
d718 1
a718 1
  /* Do bounds checking on the native coordinates. */
d726 1
a726 1
/*--------------------------------------------------------------------------*/
d748 1
a748 1
  /* Initialize. */
d766 1
a766 1
  /* Do phi dependence. */
d784 1
a784 1
  /* Do theta dependence. */
d805 1
a805 1
        /* Bounds checking. */
d809 1
a809 1
            /* Overlap. */
d814 1
a814 1
            /* Divergence. */
d926 1
a926 1
/*--------------------------------------------------------------------------*/
d949 1
a949 1
  /* Initialize. */
d967 1
a967 1
  /* Do x dependence. */
d982 1
a982 1
  /* Do y dependence. */
d999 1
a999 1
        /* Use small angle formula. */
d1010 1
a1010 1
        /* Check for a solution. */
d1020 1
a1020 1
        /* Choose solution closest to pole. */
d1057 1
a1057 1
  /* Do bounds checking on the native coordinates. */
d1065 1
a1065 1
/*--------------------------------------------------------------------------*/
d1087 1
a1087 1
  /* Initialize. */
d1105 1
a1105 1
  /* Do phi dependence. */
d1123 1
a1123 1
  /* Do theta dependence. */
d1147 1
a1147 1
        /* Bounds checking. */
d1151 1
a1151 1
            /* Divergence. */
d1156 1
a1156 1
            /* Overlap. */
d1230 1
a1230 1
/*--------------------------------------------------------------------------*/
d1252 1
a1252 1
  /* Initialize. */
d1270 1
a1270 1
  /* Do x dependence. */
d1285 1
a1285 1
  /* Do y dependence. */
d1310 1
a1310 1
  /* Do bounds checking on the native coordinates. */
d1318 1
a1318 1
/*--------------------------------------------------------------------------*/
d1340 1
a1340 1
  /* Initialize. */
d1358 1
a1358 1
  /* Do phi dependence. */
d1376 1
a1376 1
  /* Do theta dependence. */
d1394 1
a1394 1
      /* Bounds checking. */
d1465 1
a1465 1
/*--------------------------------------------------------------------------*/
d1487 1
a1487 1
  /* Initialize. */
d1503 1
a1503 1
  /* Do x dependence. */
d1518 1
a1518 1
  /* Do y dependence. */
d1545 1
a1545 1
/*--------------------------------------------------------------------------*/
d1567 1
a1567 1
  /* Initialize. */
d1585 1
a1585 1
  /* Do phi dependence. */
d1603 1
a1603 1
  /* Do theta dependence. */
d1688 1
a1688 1
/*--------------------------------------------------------------------------*/
d1712 1
a1712 1
  /* Initialize. */
d1733 1
a1733 1
  /* Do x dependence. */
d1748 1
a1748 1
  /* Do y dependence. */
d1758 1
a1758 1
      /* Compute intermediaries. */
d1763 1
a1763 1
        /* Orthographic projection. */
d1781 1
a1781 1
        /* "Synthesis" projection. */
d1785 1
a1785 1
          /* Use small angle formula. */
d1795 1
a1795 1
          /* Check for a solution. */
d1805 1
a1805 1
          /* Choose solution closest to pole. */
d1849 1
a1849 1
  /* Do bounds checking on the native coordinates. */
d1857 1
a1857 1
/*--------------------------------------------------------------------------*/
d1879 1
a1879 1
  /* Initialize. */
d1897 1
a1897 1
  /* Do phi dependence. */
d1915 1
a1915 1
  /* Do theta dependence. */
d1936 1
a1936 1
      /* Orthographic projection. */
d1952 1
a1952 1
      /* "Synthesis" projection. */
d2028 1
a2028 1
/*--------------------------------------------------------------------------*/
d2050 1
a2050 1
  /* Initialize. */
d2068 1
a2068 1
  /* Do x dependence. */
d2083 1
a2083 1
  /* Do y dependence. */
d2109 1
a2109 1
  /* Do bounds checking on the native coordinates. */
d2117 1
a2117 1
/*--------------------------------------------------------------------------*/
d2139 1
a2139 1
  /* Initialize. */
d2155 1
a2155 1
  /* Do phi dependence. */
d2173 1
a2173 1
  /* Do theta dependence. */
d2240 1
a2240 1
  /* Find the highest non-zero coefficient. */
d2249 1
a2249 1
    /* No point of inflection. */
d2253 1
a2253 1
    /* Find the point of inflection closest to the pole. */
d2260 1
a2260 1
    /* Find the point where the derivative first goes negative. */
d2274 1
a2274 1
      /* No negative derivative -> no point of inflection. */
d2278 1
a2278 1
      /* Find where the derivative is zero. */
d2313 1
a2313 1
/*--------------------------------------------------------------------------*/
d2336 1
a2336 1
  /* Initialize. */
d2356 1
a2356 1
  /* Do x dependence. */
d2371 1
a2371 1
  /* Do y dependence. */
d2391 1
a2391 1
        /* Constant - no solution. */
d2395 1
a2395 1
        /* Linear. */
d2399 1
a2399 1
        /* Quadratic. */
d2413 1
a2413 1
        /* Choose solution closest to pole. */
d2436 1
a2436 1
        /* Higher order - solve iteratively. */
d2459 1
a2459 1
          /* Dissect the interval. */
d2496 1
a2496 1
  /* Do bounds checking on the native coordinates. */
d2504 1
a2504 1
/*--------------------------------------------------------------------------*/
d2526 1
a2526 1
  /* Initialize. */
d2544 1
a2544 1
  /* Do phi dependence. */
d2562 1
a2562 1
  /* Do theta dependence. */
d2576 1
a2576 1
    /* Bounds checking. */
d2646 1
a2646 1
/*--------------------------------------------------------------------------*/
d2669 1
a2669 1
  /* Initialize. */
d2687 1
a2687 1
  /* Do x dependence. */
d2702 1
a2702 1
  /* Do y dependence. */
d2740 1
a2740 1
  /* Do bounds checking on the native coordinates. */
d2748 1
a2748 1
/*--------------------------------------------------------------------------*/
d2770 1
a2770 1
  /* Initialize. */
d2786 1
a2786 1
  /* Do phi dependence. */
d2804 1
a2804 1
  /* Do theta dependence. */
d2897 1
a2897 1
/*--------------------------------------------------------------------------*/
d2920 1
a2920 1
  /* Initialize. */
d2938 1
a2938 1
  /* Do x dependence. */
d2953 1
a2953 1
  /* Do y dependence. */
d2978 1
a2978 1
        /* Find a solution interval. */
d2998 1
a2998 1
          /* Weighted division of the interval. */
d3036 1
a3036 1
  /* Do bounds checking on the native coordinates. */
d3044 1
a3044 1
/*--------------------------------------------------------------------------*/
d3066 1
a3066 1
  /* Initialize. */
d3084 1
a3084 1
  /* Do phi dependence. */
d3102 1
a3102 1
  /* Do theta dependence. */
d3222 1
a3222 1
/*--------------------------------------------------------------------------*/
d3244 1
a3244 1
  /* Initialize. */
d3262 1
a3262 1
  /* Do x dependence. */
d3277 1
a3277 1
  /* Do y dependence. */
d3292 1
a3292 1
  /* Do bounds checking on the native coordinates. */
d3300 1
a3300 1
/*--------------------------------------------------------------------------*/
d3322 1
a3322 1
  /* Initialize. */
d3340 1
a3340 1
  /* Do phi dependence. */
d3355 1
a3355 1
  /* Do theta dependence. */
d3450 1
a3450 1
/*--------------------------------------------------------------------------*/
d3473 1
a3473 1
  /* Initialize. */
d3491 1
a3491 1
  /* Do x dependence. */
d3506 1
a3506 1
  /* Do y dependence. */
d3533 1
a3533 1
  /* Do bounds checking on the native coordinates. */
d3541 1
a3541 1
/*--------------------------------------------------------------------------*/
d3563 1
a3563 1
  /* Initialize. */
d3579 1
a3579 1
  /* Do phi dependence. */
d3594 1
a3594 1
  /* Do theta dependence. */
d3661 1
a3661 1
/*--------------------------------------------------------------------------*/
d3683 1
a3683 1
  /* Initialize. */
d3701 1
a3701 1
  /* Do x dependence. */
d3716 1
a3716 1
  /* Do y dependence. */
d3730 1
a3730 1
  /* Do bounds checking on the native coordinates. */
d3738 1
a3738 1
/*--------------------------------------------------------------------------*/
d3760 1
a3760 1
  /* Initialize. */
d3776 1
a3776 1
  /* Do phi dependence. */
d3791 1
a3791 1
  /* Do theta dependence. */
d3858 1
a3858 1
/*--------------------------------------------------------------------------*/
d3880 1
a3880 1
  /* Initialize. */
d3898 1
a3898 1
  /* Do x dependence. */
d3913 1
a3913 1
  /* Do y dependence. */
d3927 1
a3927 1
  /* Do bounds checking on the native coordinates. */
d3935 1
a3935 1
/*--------------------------------------------------------------------------*/
d3957 1
a3957 1
  /* Initialize. */
d3975 1
a3975 1
  /* Do phi dependence. */
d3990 1
a3990 1
  /* Do theta dependence. */
d4065 1
a4065 1
/*--------------------------------------------------------------------------*/
d4087 1
a4087 1
  /* Initialize. */
d4105 1
a4105 1
  /* Do x dependence. */
d4120 1
a4120 1
  /* Do y dependence. */
d4147 1
a4147 1
  /* Do bounds checking on the native coordinates. */
d4155 1
a4155 1
/*--------------------------------------------------------------------------*/
d4177 1
a4177 1
  /* Initialize. */
d4193 1
a4193 1
  /* Do phi dependence. */
d4208 1
a4208 1
  /* Do theta dependence. */
d4284 1
a4284 1
/*--------------------------------------------------------------------------*/
d4307 1
a4307 1
  /* Initialize. */
d4325 1
a4325 1
  /* Do x dependence. */
d4345 1
a4345 1
  /* Do y dependence. */
d4363 1
a4363 1
        /* Deferred test. */
d4390 1
a4390 1
  /* Do bounds checking on the native coordinates. */
d4398 1
a4398 1
/*--------------------------------------------------------------------------*/
d4420 1
a4420 1
  /* Initialize. */
d4436 1
a4436 1
  /* Do phi dependence. */
d4451 1
a4451 1
  /* Do theta dependence. */
d4523 1
a4523 1
/*--------------------------------------------------------------------------*/
d4546 1
a4546 1
  /* Initialize. */
d4564 1
a4564 1
  /* Do x dependence. */
d4584 1
a4584 1
  /* Do y dependence. */
d4600 1
a4600 1
        /* OK if fabs(x) < tol whence phi = 0.0. */
d4655 1
a4655 1
  /* Do bounds checking on the native coordinates. */
d4663 1
a4663 1
/*--------------------------------------------------------------------------*/
d4686 1
a4686 1
  /* Initialize. */
d4702 1
a4702 1
  /* Do phi dependence. */
d4717 1
a4717 1
  /* Do theta dependence. */
d4815 1
a4815 1
/*--------------------------------------------------------------------------*/
d4838 1
a4838 1
  /* Initialize. */
d4856 1
a4856 1
  /* Do x dependence. */
d4876 1
a4876 1
  /* Do y dependence. */
d4925 1
a4925 1
  /* Do bounds checking on the native coordinates. */
d4933 1
a4933 1
/*--------------------------------------------------------------------------*/
d4955 1
a4955 1
  /* Initialize. */
d4971 1
a4971 1
  /* Do phi dependence. */
d4990 1
a4990 1
  /* Do theta dependence. */
d5083 1
a5083 1
/*--------------------------------------------------------------------------*/
d5104 1
a5104 1
  /* Initialize. */
d5122 1
a5122 1
  /* Do x dependence. */
d5137 1
a5137 1
  /* Do y dependence. */
d5165 1
a5165 1
  /* Do bounds checking on the native coordinates. */
d5173 1
a5173 1
/*--------------------------------------------------------------------------*/
d5194 1
a5194 1
  /* Initialize. */
d5212 1
a5212 1
  /* Do phi dependence. */
d5231 1
a5231 1
  /* Do theta dependence. */
d5243 1
a5243 1
      /* Latitude of divergence. */
d5249 1
a5249 1
      /* Return an exact value at the poles. */
d5252 1
a5252 1
      /* Bounds checking. */
d5263 1
a5263 1
      /* Bounds checking. */
d5363 1
a5363 1
/*--------------------------------------------------------------------------*/
d5385 1
a5385 1
  /* Initialize. */
d5403 1
a5403 1
  /* Do x dependence. */
d5418 1
a5418 1
  /* Do y dependence. */
d5466 1
a5466 1
  /* Do bounds checking on the native coordinates. */
d5474 1
a5474 1
/*--------------------------------------------------------------------------*/
d5495 1
a5495 1
  /* Initialize. */
d5511 1
a5511 1
  /* Do phi dependence. */
d5530 1
a5530 1
  /* Do theta dependence. */
d5622 1
a5622 1
/*--------------------------------------------------------------------------*/
d5643 1
a5643 1
  /* Initialize. */
d5661 1
a5661 1
  /* Do x dependence. */
d5676 1
a5676 1
  /* Do y dependence. */
d5704 1
a5704 1
  /* Do bounds checking on the native coordinates. */
d5712 1
a5712 1
/*--------------------------------------------------------------------------*/
d5733 1
a5733 1
  /* Initialize. */
d5749 1
a5749 1
  /* Do phi dependence. */
d5768 1
a5768 1
  /* Do theta dependence. */
d5873 1
a5873 1
/*--------------------------------------------------------------------------*/
d5894 1
a5894 1
  /* Initialize. */
d5912 1
a5912 1
  /* Do x dependence. */
d5927 1
a5927 1
  /* Do y dependence. */
d5968 1
a5968 1
  /* Do bounds checking on the native coordinates. */
d5976 1
a5976 1
/*--------------------------------------------------------------------------*/
d5997 1
a5997 1
  /* Initialize. */
d6015 1
a6015 1
  /* Do phi dependence. */
d6034 1
a6034 1
  /* Do theta dependence. */
d6099 1
a6099 1
    /* Sanson-Flamsteed. */
d6126 1
a6126 1
/*--------------------------------------------------------------------------*/
d6148 1
a6148 1
  /* Initialize. */
d6151 1
a6151 1
    /* Sanson-Flamsteed. */
d6171 1
a6171 1
  /* Do x dependence. */
d6186 1
a6186 1
  /* Do y dependence. */
d6222 1
a6222 1
  /* Do bounds checking on the native coordinates. */
d6230 1
a6230 1
/*--------------------------------------------------------------------------*/
d6251 1
a6251 1
  /* Initialize. */
d6254 1
a6254 1
    /* Sanson-Flamsteed. */
d6274 1
a6274 1
  /* Do phi dependence. */
d6289 1
a6289 1
  /* Do theta dependence. */
d6366 1
a6366 1
/*--------------------------------------------------------------------------*/
d6390 1
a6390 1
  /* Initialize. */
d6408 1
a6408 1
  /* Do x dependence. */
d6423 1
a6423 1
  /* Do y dependence. */
d6445 1
a6445 1
          /* To avoid cot(theta) blowing up near theta == 0. */
d6451 1
a6451 1
          /* Iterative solution using weighted division of the interval. */
d6455 1
a6455 1
          /* Setting fneg = -fpos halves the interval in the first iter. */
d6461 1
a6461 1
            /* Weighted division of the interval. */
d6470 1
a6470 1
            /* Compute the residue. */
d6475 1
a6475 1
            /* Check for convergence. */
d6479 1
a6479 1
            /* Redefine the interval. */
d6506 1
a6506 1
  /* Do bounds checking on the native coordinates. */
d6514 1
a6514 1
/*--------------------------------------------------------------------------*/
d6535 1
a6535 1
  /* Initialize. */
d6551 1
a6551 1
  /* Do phi dependence. */
d6564 1
a6564 1
  /* Do theta dependence. */
d6578 1
a6578 1
      /* To avoid cot(theta) blowing up near theta == 0. */
d6653 1
a6653 1
/*--------------------------------------------------------------------------*/
d6675 1
a6675 1
  /* Initialize. */
d6693 1
a6693 1
  /* Do x dependence. */
d6708 1
a6708 1
  /* Do y dependence. */
d6719 1
a6719 1
      /* Bounds checking. */
d6738 1
a6738 1
      /* Map negative faces to the other side. */
d6741 1
a6741 1
      /* Determine the face. */
d6743 1
a6743 1
        /* face = 4 */
d6749 1
a6749 1
        /* face = 3 */
d6755 1
a6755 1
        /* face = 2 */
d6761 1
a6761 1
        /* face = 0 */
d6767 1
a6767 1
        /* face = 5 */
d6773 1
a6773 1
        /* face = 1 */
d6791 1
a6791 1
  /* Do bounds checking on the native coordinates. */
d6799 1
a6799 1
/*--------------------------------------------------------------------------*/
d6821 1
a6821 1
  /* Initialize. */
d6839 1
a6839 1
  /* Do phi dependence. */
d6857 1
a6857 1
  /* Do theta dependence. */
d6925 1
a6925 1
        /* face == 0 */
d7009 1
a7009 1
/*--------------------------------------------------------------------------*/
d7060 1
a7060 1
  /* Initialize. */
d7078 1
a7078 1
  /* Do x dependence. */
d7093 1
a7093 1
  /* Do y dependence. */
d7104 1
a7104 1
      /* Bounds checking. */
d7123 1
a7123 1
      /* Map negative faces to the other side. */
d7126 1
a7126 1
      /* Determine the face. */
d7201 1
a7201 1
        /* face == 0 */
d7220 1
a7220 1
  /* Do bounds checking on the native coordinates. */
d7228 1
a7228 1
/*--------------------------------------------------------------------------*/
d7266 1
a7266 1
  /* Initialize. */
d7284 1
a7284 1
  /* Do phi dependence. */
d7302 1
a7302 1
  /* Do theta dependence. */
d7370 1
a7370 1
        /* face == 0 */
d7386 1
a7386 1
      /* Avoid floating underflows. */
d7475 1
a7475 1
/*--------------------------------------------------------------------------*/
d7498 1
a7498 1
  /* Initialize. */
d7516 1
a7516 1
  /* Do x dependence. */
d7531 1
a7531 1
  /* Do y dependence. */
d7542 1
a7542 1
      /* Bounds checking. */
d7561 1
a7561 1
      /* Map negative faces to the other side. */
d7564 1
a7564 1
      /* Determine the face. */
d7692 1
a7692 1
        /* face == 0 */
d7718 1
a7718 1
  /* Do bounds checking on the native coordinates. */
d7726 1
a7726 1
/*--------------------------------------------------------------------------*/
d7750 1
a7750 1
  /* Initialize. */
d7768 1
a7768 1
  /* Do phi dependence. */
d7786 1
a7786 1
  /* Do theta dependence. */
d7836 1
a7836 1
          /* Small angle formula. */
d7848 1
a7848 1
          /* Small angle formula. */
d7860 1
a7860 1
          /* Small angle formula. */
d7873 1
a7873 1
          /* Small angle formula. */
d7885 1
a7885 1
          /* Small angle formula. */
d7893 1
a7893 1
        /* face == 0 */
d7897 1
a7897 1
          /* Small angle formula. */
d8041 1
a8041 1
/*--------------------------------------------------------------------------*/
d8063 1
a8063 1
  /* Initialize. */
d8084 1
a8084 1
  /* Do x dependence. */
d8090 1
a8090 1
    /* x_c for K odd or theta > 0. */
d8097 1
a8097 1
      /* theta[] is used to hold (x - x_c). */
d8106 1
a8106 1
  /* Do y dependence. */
d8117 1
a8117 1
      /* Equatorial regime. */
d8125 1
a8125 1
      /* Polar regime. */
d8150 1
a8150 1
          /* Offset the southern polar half-facets for even K. */
d8159 1
a8159 1
        /* Recall that theta[] holds (x - x_c). */
d8162 1
a8162 1
        /* Bounds checking. */
d8178 1
a8178 1
      /* Beyond latitude range. */
d8189 1
a8189 1
  /* Do bounds checking on the native coordinates. */
d8197 1
a8197 1
/*--------------------------------------------------------------------------*/
d8219 1
a8219 1
  /* Initialize. */
d8235 1
a8235 1
  /* Do phi dependence. */
d8242 1
a8242 1
    /* phi_c for K odd or theta > 0. */
d8249 1
a8249 1
      /* y[] is used to hold (phi - phi_c). */
d8258 1
a8258 1
  /* Do theta dependence. */
d8268 1
a8268 1
      /* Equatorial regime. */
d8276 1
a8276 1
      /* Polar regime. */
d8288 1
a8288 1
          /* Offset the southern polar half-facets for even K. */
d8297 1
a8297 1
        /* Recall that y[] holds (phi - phi_c). */
d8302 1
a8302 1
        /* Put the phi = 180 meridian in the expected place. */
d8375 1
a8375 1
/*--------------------------------------------------------------------------*/
d8398 1
a8398 1
  /* Initialize. */
d8416 1
a8416 1
  /* Do x dependence. */
d8431 1
a8431 1
  /* Do y dependence. */
d8466 1
a8466 1
          /* Equatorial regime. */
d8471 1
a8471 1
          /* Bounds checking. */
d8482 1
a8482 1
          /* Polar regime. */
d8485 1
a8485 1
          /* Ensure an exact result for points on the boundary. */
d8509 1
a8509 1
          /* Bounds checking. */
d8522 1
a8522 1
        /* Beyond latitude range. */
d8532 1
a8532 1
  /* Do bounds checking on the native coordinates. */
d8540 1
a8540 1
/*--------------------------------------------------------------------------*/
d8562 1
a8562 1
  /* Initialize. */
d8578 1
a8578 1
  /* Do phi dependence. */
d8593 1
a8593 1
    /* phi is also recomputed from chi to avoid rounding problems. */
d8600 1
a8600 1
      /* y[] is used to hold phi (rounded). */
d8609 1
a8609 1
  /* Do theta dependence. */
d8620 1
a8620 1
        /* Equatorial regime. */
d8625 1
a8625 1
        /* Polar regime. */
d8640 1
a8640 1
      /* Recall that y[] holds phi. */
@


7.3.1.1
log
@WCSLIB 7.3 development branch.
@
text
@d25 1
a25 1
  $Id: prj.c,v 7.3 2020/06/03 03:37:02 mcalabre Exp $
@


7.3.1.2
log
@Switched to C99 style commenting (i.e. using //) within the code.
@
text
@d2 1
d25 1
a25 1
  $Id: prj.c,v 7.3.1.1 2020/06/03 03:38:10 mcalabre Exp mcalabre $
d41 1
a41 1
// Projection categories.
d56 1
a56 1
// Projection codes.
d93 1
a93 1
// Map status return value to message.
d101 1
a101 1
// Convenience macros for generating common error messages.
d187 1
a187 1
//----------------------------------------------------------------------------
d199 1
a199 1
//----------------------------------------------------------------------------
d287 1
a287 1
//----------------------------------------------------------------------------
d301 1
a301 1
//----------------------------------------------------------------------------
d322 1
a322 1
      // Skip values already marked as illegal.
d362 1
a362 1
//----------------------------------------------------------------------------
d375 1
a375 1
  // Invoke the relevant initialization routine.
d434 1
a434 1
    // Unrecognized projection code.
d442 1
a442 1
//----------------------------------------------------------------------------
d459 1
a459 1
  // Initialize.
d468 1
a468 1
//----------------------------------------------------------------------------
d485 1
a485 1
  // Initialize.
d514 1
a514 1
    // Set both to the projection-specific default if either undefined.
d610 1
a610 1
//----------------------------------------------------------------------------
d633 1
a633 1
  // Initialize.
d651 1
a651 1
  // Do x dependence.
d666 1
a666 1
  // Do y dependence.
d721 1
a721 1
  // Do bounds checking on the native coordinates.
d729 1
a729 1
//----------------------------------------------------------------------------
d751 1
a751 1
  // Initialize.
d769 1
a769 1
  // Do phi dependence.
d787 1
a787 1
  // Do theta dependence.
d808 1
a808 1
        // Bounds checking.
d812 1
a812 1
            // Overlap.
d817 1
a817 1
            // Divergence.
d929 1
a929 1
//----------------------------------------------------------------------------
d952 1
a952 1
  // Initialize.
d970 1
a970 1
  // Do x dependence.
d985 1
a985 1
  // Do y dependence.
d1002 1
a1002 1
        // Use small angle formula.
d1013 1
a1013 1
        // Check for a solution.
d1023 1
a1023 1
        // Choose solution closest to pole.
d1060 1
a1060 1
  // Do bounds checking on the native coordinates.
d1068 1
a1068 1
//----------------------------------------------------------------------------
d1090 1
a1090 1
  // Initialize.
d1108 1
a1108 1
  // Do phi dependence.
d1126 1
a1126 1
  // Do theta dependence.
d1150 1
a1150 1
        // Bounds checking.
d1154 1
a1154 1
            // Divergence.
d1159 1
a1159 1
            // Overlap.
d1233 1
a1233 1
//----------------------------------------------------------------------------
d1255 1
a1255 1
  // Initialize.
d1273 1
a1273 1
  // Do x dependence.
d1288 1
a1288 1
  // Do y dependence.
d1313 1
a1313 1
  // Do bounds checking on the native coordinates.
d1321 1
a1321 1
//----------------------------------------------------------------------------
d1343 1
a1343 1
  // Initialize.
d1361 1
a1361 1
  // Do phi dependence.
d1379 1
a1379 1
  // Do theta dependence.
d1397 1
a1397 1
      // Bounds checking.
d1468 1
a1468 1
//----------------------------------------------------------------------------
d1490 1
a1490 1
  // Initialize.
d1506 1
a1506 1
  // Do x dependence.
d1521 1
a1521 1
  // Do y dependence.
d1548 1
a1548 1
//----------------------------------------------------------------------------
d1570 1
a1570 1
  // Initialize.
d1588 1
a1588 1
  // Do phi dependence.
d1606 1
a1606 1
  // Do theta dependence.
d1691 1
a1691 1
//----------------------------------------------------------------------------
d1715 1
a1715 1
  // Initialize.
d1736 1
a1736 1
  // Do x dependence.
d1751 1
a1751 1
  // Do y dependence.
d1761 1
a1761 1
      // Compute intermediaries.
d1766 1
a1766 1
        // Orthographic projection.
d1784 1
a1784 1
        // "Synthesis" projection.
d1788 1
a1788 1
          // Use small angle formula.
d1798 1
a1798 1
          // Check for a solution.
d1808 1
a1808 1
          // Choose solution closest to pole.
d1852 1
a1852 1
  // Do bounds checking on the native coordinates.
d1860 1
a1860 1
//----------------------------------------------------------------------------
d1882 1
a1882 1
  // Initialize.
d1900 1
a1900 1
  // Do phi dependence.
d1918 1
a1918 1
  // Do theta dependence.
d1939 1
a1939 1
      // Orthographic projection.
d1955 1
a1955 1
      // "Synthesis" projection.
d2031 1
a2031 1
//----------------------------------------------------------------------------
d2053 1
a2053 1
  // Initialize.
d2071 1
a2071 1
  // Do x dependence.
d2086 1
a2086 1
  // Do y dependence.
d2112 1
a2112 1
  // Do bounds checking on the native coordinates.
d2120 1
a2120 1
//----------------------------------------------------------------------------
d2142 1
a2142 1
  // Initialize.
d2158 1
a2158 1
  // Do phi dependence.
d2176 1
a2176 1
  // Do theta dependence.
d2243 1
a2243 1
  // Find the highest non-zero coefficient.
d2252 1
a2252 1
    // No point of inflection.
d2256 1
a2256 1
    // Find the point of inflection closest to the pole.
d2263 1
a2263 1
    // Find the point where the derivative first goes negative.
d2277 1
a2277 1
      // No negative derivative -> no point of inflection.
d2281 1
a2281 1
      // Find where the derivative is zero.
d2316 1
a2316 1
//----------------------------------------------------------------------------
d2339 1
a2339 1
  // Initialize.
d2359 1
a2359 1
  // Do x dependence.
d2374 1
a2374 1
  // Do y dependence.
d2394 1
a2394 1
        // Constant - no solution.
d2398 1
a2398 1
        // Linear.
d2402 1
a2402 1
        // Quadratic.
d2416 1
a2416 1
        // Choose solution closest to pole.
d2439 1
a2439 1
        // Higher order - solve iteratively.
d2462 1
a2462 1
          // Dissect the interval.
d2499 1
a2499 1
  // Do bounds checking on the native coordinates.
d2507 1
a2507 1
//----------------------------------------------------------------------------
d2529 1
a2529 1
  // Initialize.
d2547 1
a2547 1
  // Do phi dependence.
d2565 1
a2565 1
  // Do theta dependence.
d2579 1
a2579 1
    // Bounds checking.
d2649 1
a2649 1
//----------------------------------------------------------------------------
d2672 1
a2672 1
  // Initialize.
d2690 1
a2690 1
  // Do x dependence.
d2705 1
a2705 1
  // Do y dependence.
d2743 1
a2743 1
  // Do bounds checking on the native coordinates.
d2751 1
a2751 1
//----------------------------------------------------------------------------
d2773 1
a2773 1
  // Initialize.
d2789 1
a2789 1
  // Do phi dependence.
d2807 1
a2807 1
  // Do theta dependence.
d2900 1
a2900 1
//----------------------------------------------------------------------------
d2923 1
a2923 1
  // Initialize.
d2941 1
a2941 1
  // Do x dependence.
d2956 1
a2956 1
  // Do y dependence.
d2981 1
a2981 1
        // Find a solution interval.
d3001 1
a3001 1
          // Weighted division of the interval.
d3039 1
a3039 1
  // Do bounds checking on the native coordinates.
d3047 1
a3047 1
//----------------------------------------------------------------------------
d3069 1
a3069 1
  // Initialize.
d3087 1
a3087 1
  // Do phi dependence.
d3105 1
a3105 1
  // Do theta dependence.
d3225 1
a3225 1
//----------------------------------------------------------------------------
d3247 1
a3247 1
  // Initialize.
d3265 1
a3265 1
  // Do x dependence.
d3280 1
a3280 1
  // Do y dependence.
d3295 1
a3295 1
  // Do bounds checking on the native coordinates.
d3303 1
a3303 1
//----------------------------------------------------------------------------
d3325 1
a3325 1
  // Initialize.
d3343 1
a3343 1
  // Do phi dependence.
d3358 1
a3358 1
  // Do theta dependence.
d3453 1
a3453 1
//----------------------------------------------------------------------------
d3476 1
a3476 1
  // Initialize.
d3494 1
a3494 1
  // Do x dependence.
d3509 1
a3509 1
  // Do y dependence.
d3536 1
a3536 1
  // Do bounds checking on the native coordinates.
d3544 1
a3544 1
//----------------------------------------------------------------------------
d3566 1
a3566 1
  // Initialize.
d3582 1
a3582 1
  // Do phi dependence.
d3597 1
a3597 1
  // Do theta dependence.
d3664 1
a3664 1
//----------------------------------------------------------------------------
d3686 1
a3686 1
  // Initialize.
d3704 1
a3704 1
  // Do x dependence.
d3719 1
a3719 1
  // Do y dependence.
d3733 1
a3733 1
  // Do bounds checking on the native coordinates.
d3741 1
a3741 1
//----------------------------------------------------------------------------
d3763 1
a3763 1
  // Initialize.
d3779 1
a3779 1
  // Do phi dependence.
d3794 1
a3794 1
  // Do theta dependence.
d3861 1
a3861 1
//----------------------------------------------------------------------------
d3883 1
a3883 1
  // Initialize.
d3901 1
a3901 1
  // Do x dependence.
d3916 1
a3916 1
  // Do y dependence.
d3930 1
a3930 1
  // Do bounds checking on the native coordinates.
d3938 1
a3938 1
//----------------------------------------------------------------------------
d3960 1
a3960 1
  // Initialize.
d3978 1
a3978 1
  // Do phi dependence.
d3993 1
a3993 1
  // Do theta dependence.
d4068 1
a4068 1
//----------------------------------------------------------------------------
d4090 1
a4090 1
  // Initialize.
d4108 1
a4108 1
  // Do x dependence.
d4123 1
a4123 1
  // Do y dependence.
d4150 1
a4150 1
  // Do bounds checking on the native coordinates.
d4158 1
a4158 1
//----------------------------------------------------------------------------
d4180 1
a4180 1
  // Initialize.
d4196 1
a4196 1
  // Do phi dependence.
d4211 1
a4211 1
  // Do theta dependence.
d4287 1
a4287 1
//----------------------------------------------------------------------------
d4310 1
a4310 1
  // Initialize.
d4328 1
a4328 1
  // Do x dependence.
d4348 1
a4348 1
  // Do y dependence.
d4366 1
a4366 1
        // Deferred test.
d4393 1
a4393 1
  // Do bounds checking on the native coordinates.
d4401 1
a4401 1
//----------------------------------------------------------------------------
d4423 1
a4423 1
  // Initialize.
d4439 1
a4439 1
  // Do phi dependence.
d4454 1
a4454 1
  // Do theta dependence.
d4526 1
a4526 1
//----------------------------------------------------------------------------
d4549 1
a4549 1
  // Initialize.
d4567 1
a4567 1
  // Do x dependence.
d4587 1
a4587 1
  // Do y dependence.
d4603 1
a4603 1
        // OK if fabs(x) < tol whence phi = 0.0.
d4658 1
a4658 1
  // Do bounds checking on the native coordinates.
d4666 1
a4666 1
//----------------------------------------------------------------------------
d4689 1
a4689 1
  // Initialize.
d4705 1
a4705 1
  // Do phi dependence.
d4720 1
a4720 1
  // Do theta dependence.
d4818 1
a4818 1
//----------------------------------------------------------------------------
d4841 1
a4841 1
  // Initialize.
d4859 1
a4859 1
  // Do x dependence.
d4879 1
a4879 1
  // Do y dependence.
d4928 1
a4928 1
  // Do bounds checking on the native coordinates.
d4936 1
a4936 1
//----------------------------------------------------------------------------
d4958 1
a4958 1
  // Initialize.
d4974 1
a4974 1
  // Do phi dependence.
d4993 1
a4993 1
  // Do theta dependence.
d5086 1
a5086 1
//----------------------------------------------------------------------------
d5107 1
a5107 1
  // Initialize.
d5125 1
a5125 1
  // Do x dependence.
d5140 1
a5140 1
  // Do y dependence.
d5168 1
a5168 1
  // Do bounds checking on the native coordinates.
d5176 1
a5176 1
//----------------------------------------------------------------------------
d5197 1
a5197 1
  // Initialize.
d5215 1
a5215 1
  // Do phi dependence.
d5234 1
a5234 1
  // Do theta dependence.
d5246 1
a5246 1
      // Latitude of divergence.
d5252 1
a5252 1
      // Return an exact value at the poles.
d5255 1
a5255 1
      // Bounds checking.
d5266 1
a5266 1
      // Bounds checking.
d5366 1
a5366 1
//----------------------------------------------------------------------------
d5388 1
a5388 1
  // Initialize.
d5406 1
a5406 1
  // Do x dependence.
d5421 1
a5421 1
  // Do y dependence.
d5469 1
a5469 1
  // Do bounds checking on the native coordinates.
d5477 1
a5477 1
//----------------------------------------------------------------------------
d5498 1
a5498 1
  // Initialize.
d5514 1
a5514 1
  // Do phi dependence.
d5533 1
a5533 1
  // Do theta dependence.
d5625 1
a5625 1
//----------------------------------------------------------------------------
d5646 1
a5646 1
  // Initialize.
d5664 1
a5664 1
  // Do x dependence.
d5679 1
a5679 1
  // Do y dependence.
d5707 1
a5707 1
  // Do bounds checking on the native coordinates.
d5715 1
a5715 1
//----------------------------------------------------------------------------
d5736 1
a5736 1
  // Initialize.
d5752 1
a5752 1
  // Do phi dependence.
d5771 1
a5771 1
  // Do theta dependence.
d5876 1
a5876 1
//----------------------------------------------------------------------------
d5897 1
a5897 1
  // Initialize.
d5915 1
a5915 1
  // Do x dependence.
d5930 1
a5930 1
  // Do y dependence.
d5971 1
a5971 1
  // Do bounds checking on the native coordinates.
d5979 1
a5979 1
//----------------------------------------------------------------------------
d6000 1
a6000 1
  // Initialize.
d6018 1
a6018 1
  // Do phi dependence.
d6037 1
a6037 1
  // Do theta dependence.
d6102 1
a6102 1
    // Sanson-Flamsteed.
d6129 1
a6129 1
//----------------------------------------------------------------------------
d6151 1
a6151 1
  // Initialize.
d6154 1
a6154 1
    // Sanson-Flamsteed.
d6174 1
a6174 1
  // Do x dependence.
d6189 1
a6189 1
  // Do y dependence.
d6225 1
a6225 1
  // Do bounds checking on the native coordinates.
d6233 1
a6233 1
//----------------------------------------------------------------------------
d6254 1
a6254 1
  // Initialize.
d6257 1
a6257 1
    // Sanson-Flamsteed.
d6277 1
a6277 1
  // Do phi dependence.
d6292 1
a6292 1
  // Do theta dependence.
d6369 1
a6369 1
//----------------------------------------------------------------------------
d6393 1
a6393 1
  // Initialize.
d6411 1
a6411 1
  // Do x dependence.
d6426 1
a6426 1
  // Do y dependence.
d6448 1
a6448 1
          // To avoid cot(theta) blowing up near theta == 0.
d6454 1
a6454 1
          // Iterative solution using weighted division of the interval.
d6458 1
a6458 1
          // Setting fneg = -fpos halves the interval in the first iter.
d6464 1
a6464 1
            // Weighted division of the interval.
d6473 1
a6473 1
            // Compute the residue.
d6478 1
a6478 1
            // Check for convergence.
d6482 1
a6482 1
            // Redefine the interval.
d6509 1
a6509 1
  // Do bounds checking on the native coordinates.
d6517 1
a6517 1
//----------------------------------------------------------------------------
d6538 1
a6538 1
  // Initialize.
d6554 1
a6554 1
  // Do phi dependence.
d6567 1
a6567 1
  // Do theta dependence.
d6581 1
a6581 1
      // To avoid cot(theta) blowing up near theta == 0.
d6656 1
a6656 1
//----------------------------------------------------------------------------
d6678 1
a6678 1
  // Initialize.
d6696 1
a6696 1
  // Do x dependence.
d6711 1
a6711 1
  // Do y dependence.
d6722 1
a6722 1
      // Bounds checking.
d6741 1
a6741 1
      // Map negative faces to the other side.
d6744 1
a6744 1
      // Determine the face.
d6746 1
a6746 1
        // face = 4
d6752 1
a6752 1
        // face = 3
d6758 1
a6758 1
        // face = 2
d6764 1
a6764 1
        // face = 0
d6770 1
a6770 1
        // face = 5
d6776 1
a6776 1
        // face = 1
d6794 1
a6794 1
  // Do bounds checking on the native coordinates.
d6802 1
a6802 1
//----------------------------------------------------------------------------
d6824 1
a6824 1
  // Initialize.
d6842 1
a6842 1
  // Do phi dependence.
d6860 1
a6860 1
  // Do theta dependence.
d6928 1
a6928 1
        // face == 0
d7012 1
a7012 1
//----------------------------------------------------------------------------
d7063 1
a7063 1
  // Initialize.
d7081 1
a7081 1
  // Do x dependence.
d7096 1
a7096 1
  // Do y dependence.
d7107 1
a7107 1
      // Bounds checking.
d7126 1
a7126 1
      // Map negative faces to the other side.
d7129 1
a7129 1
      // Determine the face.
d7204 1
a7204 1
        // face == 0
d7223 1
a7223 1
  // Do bounds checking on the native coordinates.
d7231 1
a7231 1
//----------------------------------------------------------------------------
d7269 1
a7269 1
  // Initialize.
d7287 1
a7287 1
  // Do phi dependence.
d7305 1
a7305 1
  // Do theta dependence.
d7373 1
a7373 1
        // face == 0
d7389 1
a7389 1
      // Avoid floating underflows.
d7478 1
a7478 1
//----------------------------------------------------------------------------
d7501 1
a7501 1
  // Initialize.
d7519 1
a7519 1
  // Do x dependence.
d7534 1
a7534 1
  // Do y dependence.
d7545 1
a7545 1
      // Bounds checking.
d7564 1
a7564 1
      // Map negative faces to the other side.
d7567 1
a7567 1
      // Determine the face.
d7695 1
a7695 1
        // face == 0
d7721 1
a7721 1
  // Do bounds checking on the native coordinates.
d7729 1
a7729 1
//----------------------------------------------------------------------------
d7753 1
a7753 1
  // Initialize.
d7771 1
a7771 1
  // Do phi dependence.
d7789 1
a7789 1
  // Do theta dependence.
d7839 1
a7839 1
          // Small angle formula.
d7851 1
a7851 1
          // Small angle formula.
d7863 1
a7863 1
          // Small angle formula.
d7876 1
a7876 1
          // Small angle formula.
d7888 1
a7888 1
          // Small angle formula.
d7896 1
a7896 1
        // face == 0
d7900 1
a7900 1
          // Small angle formula.
d8044 1
a8044 1
//----------------------------------------------------------------------------
d8066 1
a8066 1
  // Initialize.
d8087 1
a8087 1
  // Do x dependence.
d8093 1
a8093 1
    // x_c for K odd or theta > 0.
d8100 1
a8100 1
      // theta[] is used to hold (x - x_c).
d8109 1
a8109 1
  // Do y dependence.
d8120 1
a8120 1
      // Equatorial regime.
d8128 1
a8128 1
      // Polar regime.
d8153 1
a8153 1
          // Offset the southern polar half-facets for even K.
d8162 1
a8162 1
        // Recall that theta[] holds (x - x_c).
d8165 1
a8165 1
        // Bounds checking.
d8181 1
a8181 1
      // Beyond latitude range.
d8192 1
a8192 1
  // Do bounds checking on the native coordinates.
d8200 1
a8200 1
//----------------------------------------------------------------------------
d8222 1
a8222 1
  // Initialize.
d8238 1
a8238 1
  // Do phi dependence.
d8245 1
a8245 1
    // phi_c for K odd or theta > 0.
d8252 1
a8252 1
      // y[] is used to hold (phi - phi_c).
d8261 1
a8261 1
  // Do theta dependence.
d8271 1
a8271 1
      // Equatorial regime.
d8279 1
a8279 1
      // Polar regime.
d8291 1
a8291 1
          // Offset the southern polar half-facets for even K.
d8300 1
a8300 1
        // Recall that y[] holds (phi - phi_c).
d8305 1
a8305 1
        // Put the phi = 180 meridian in the expected place.
d8378 1
a8378 1
//----------------------------------------------------------------------------
d8401 1
a8401 1
  // Initialize.
d8419 1
a8419 1
  // Do x dependence.
d8434 1
a8434 1
  // Do y dependence.
d8469 1
a8469 1
          // Equatorial regime.
d8474 1
a8474 1
          // Bounds checking.
d8485 1
a8485 1
          // Polar regime.
d8488 1
a8488 1
          // Ensure an exact result for points on the boundary.
d8512 1
a8512 1
          // Bounds checking.
d8525 1
a8525 1
        // Beyond latitude range.
d8535 1
a8535 1
  // Do bounds checking on the native coordinates.
d8543 1
a8543 1
//----------------------------------------------------------------------------
d8565 1
a8565 1
  // Initialize.
d8581 1
a8581 1
  // Do phi dependence.
d8596 1
a8596 1
    // phi is also recomputed from chi to avoid rounding problems.
d8603 1
a8603 1
      // y[] is used to hold phi (rounded).
d8612 1
a8612 1
  // Do theta dependence.
d8623 1
a8623 1
        // Equatorial regime.
d8628 1
a8628 1
        // Polar regime.
d8643 1
a8643 1
      // Recall that y[] holds phi.
@


7.3.1.3
log
@Updated date in copyright notice.
@
text
@d3 1
a3 1
  Copyright (C) 1995-2021, Mark Calabretta
d24 1
a24 1
  $Id: prj.c,v 7.3.1.2 2020/08/17 11:19:09 mcalabre Exp mcalabre $
@


7.3.1.4
log
@Removed my email address from the copyright notice.
@
text
@d20 2
d24 1
a24 1
  $Id: prj.c,v 7.3.1.3 2021/01/19 14:09:10 mcalabre Exp mcalabre $
@


7.2
log
@WCSLIB 7.2
@
text
@d3 1
a3 1
  WCSLIB 7.2 - an implementation of the FITS WCS standard.
d25 1
a25 1
  $Id: prj.c,v 7.1.1.1 2019/12/31 13:28:19 mcalabre Exp mcalabre $
@


7.2.1.1
log
@WCSLIB 7.2 development branch.
@
text
@d25 1
a25 1
  $Id: prj.c,v 7.2 2020/03/09 07:31:23 mcalabre Exp $
@


7.1
log
@WCSLIB 7.1
@
text
@d3 1
a3 1
  WCSLIB 7.1 - an implementation of the FITS WCS standard.
d25 1
a25 1
  $Id: prj.c,v 6.4.1.3 2019/12/31 03:28:03 mcalabre Exp mcalabre $
@


7.1.1.1
log
@WCSLIB 7.1 development branch.
@
text
@d25 1
a25 1
  $Id: prj.c,v 7.1 2019/12/31 13:25:19 mcalabre Exp $
@


6.4
log
@WCSLIB 6.4
@
text
@d3 2
a4 2
  WCSLIB 6.4 - an implementation of the FITS WCS standard.
  Copyright (C) 1995-2019, Mark Calabretta
d25 1
a25 1
  $Id: prj.c,v 6.3.1.1 2019/07/12 07:34:37 mcalabre Exp mcalabre $
d7248 1
a7248 1
  const float tol = 1.0e-7;
@


6.4.1.1
log
@WCSLIB 6.4 development branch.
@
text
@d25 1
a25 1
  $Id: prj.c,v 6.4 2019/08/15 09:30:18 mcalabre Exp $
@


6.4.1.2
log
@In cscs2x(), quell a warning from Microsoft Visual C++ (MSVC) about
initialising a float with a double precision constant.
@
text
@d25 1
a25 1
  $Id: prj.c,v 6.4.1.1 2019/08/15 09:31:29 mcalabre Exp mcalabre $
d7248 1
a7248 1
  const double tol = 1.0e-7;
@


6.4.1.3
log
@Updated date in copyright notice.
@
text
@d4 1
a4 1
  Copyright (C) 1995-2020, Mark Calabretta
d25 1
a25 1
  $Id: prj.c,v 6.4.1.2 2019/12/16 04:21:05 mcalabre Exp mcalabre $
@


6.3
log
@WCSLIB 6.3
@
text
@d3 1
a3 1
  WCSLIB 6.3 - an implementation of the FITS WCS standard.
d25 1
a25 1
  $Id: prj.c,v 6.2.1.4 2019/07/08 04:54:14 mcalabre Exp mcalabre $
@


6.3.1.1
log
@WCSLIB 6.3 development branch.
@
text
@d25 1
a25 1
  $Id: prj.c,v 6.3 2019/07/12 07:33:39 mcalabre Exp $
@


6.2
log
@WCSLIB 6.2
@
text
@d3 2
a4 2
  WCSLIB 6.2 - an implementation of the FITS WCS standard.
  Copyright (C) 1995-2018, Mark Calabretta
d25 1
a25 1
  $Id: prj.c,v 6.1.1.1 2018/10/19 08:36:15 mcalabre Exp mcalabre $
d143 1
a143 3
int prjini(prj)

struct prjprm *prj;
d189 1
a189 3
int prjfree(prj)

struct prjprm *prj;
d194 1
a194 4
  if (prj->err) {
    free(prj->err);
    prj->err = 0x0;
  }
d201 1
a201 3
int prjprt(prj)

const struct prjprm *prj;
d303 8
a310 6
int prjbchk(tol, nphi, ntheta, spt, phi, theta, stat)

double tol;
int nphi, ntheta, spt;
double phi[], theta[];
int stat[];
d364 1
a364 3
int prjset(prj)

struct prjprm *prj;
d444 11
a454 7
int prjx2s(prj, nx, ny, sxy, spt, x, y, phi, theta, stat)

struct prjprm *prj;
int nx, ny, sxy, spt;
const double x[], y[];
double phi[], theta[];
int stat[];
d470 11
a480 7
int prjs2x(prj, nphi, ntheta, spt, sxy, phi, theta, x, y, stat)

struct prjprm *prj;
int nphi, ntheta, spt, sxy;
const double phi[], theta[];
double x[], y[];
int stat[];
d499 4
a502 4
int prjoff(prj, phi0, theta0)

struct prjprm *prj;
const double phi0, theta0;
d560 1
a560 3
int azpset(prj)

struct prjprm *prj;
d612 11
a622 7
int azpx2s(prj, nx, ny, sxy, spt, x, y, phi, theta, stat)

struct prjprm *prj;
int nx, ny, sxy, spt;
const double x[], y[];
double phi[], theta[];
int stat[];
d731 11
a741 7
int azps2x(prj, nphi, ntheta, spt, sxy, phi, theta, x, y, stat)

struct prjprm *prj;
int nphi, ntheta, spt, sxy;
const double phi[], theta[];
double x[], y[];
int stat[];
d881 1
a881 3
int szpset(prj)

struct prjprm *prj;
d931 11
a941 7
int szpx2s(prj, nx, ny, sxy, spt, x, y, phi, theta, stat)

struct prjprm *prj;
int nx, ny, sxy, spt;
const double x[], y[];
double phi[], theta[];
int stat[];
d1070 11
a1080 7
int szps2x(prj, nphi, ntheta, spt, sxy, phi, theta, x, y, stat)

struct prjprm *prj;
int nphi, ntheta, spt, sxy;
const double phi[], theta[];
double x[], y[];
int stat[];
d1208 1
a1208 3
int tanset(prj)

struct prjprm *prj;
d1235 11
a1245 7
int tanx2s(prj, nx, ny, sxy, spt, x, y, phi, theta, stat)

struct prjprm *prj;
int nx, ny, sxy, spt;
const double x[], y[];
double phi[], theta[];
int stat[];
d1323 11
a1333 7
int tans2x(prj, nphi, ntheta, spt, sxy, phi, theta, x, y, stat)

struct prjprm *prj;
int nphi, ntheta, spt, sxy;
const double phi[], theta[];
double x[], y[];
int stat[];
d1436 1
a1436 3
int stgset(prj)

struct prjprm *prj;
d1470 11
a1480 7
int stgx2s(prj, nx, ny, sxy, spt, x, y, phi, theta, stat)

struct prjprm *prj;
int nx, ny, sxy, spt;
const double x[], y[];
double phi[], theta[];
int stat[];
d1550 11
a1560 7
int stgs2x(prj, nphi, ntheta, spt, sxy, phi, theta, x, y, stat)

struct prjprm *prj;
int nphi, ntheta, spt, sxy;
const double phi[], theta[];
double x[], y[];
int stat[];
d1659 1
a1659 3
int sinset(prj)

struct prjprm *prj;
d1693 11
a1703 7
int sinx2s(prj, nx, ny, sxy, spt, x, y, phi, theta, stat)

struct prjprm *prj;
int nx, ny, sxy, spt;
const double x[], y[];
double phi[], theta[];
int stat[];
d1862 11
a1872 7
int sins2x(prj, nphi, ntheta, spt, sxy, phi, theta, x, y, stat)

struct prjprm *prj;
int nphi, ntheta, spt, sxy;
const double phi[], theta[];
double x[], y[];
int stat[];
d1999 1
a1999 3
int arcset(prj)

struct prjprm *prj;
d2033 11
a2043 7
int arcx2s(prj, nx, ny, sxy, spt, x, y, phi, theta, stat)

struct prjprm *prj;
int nx, ny, sxy, spt;
const double x[], y[];
double phi[], theta[];
int stat[];
d2122 11
a2132 7
int arcs2x(prj, nphi, ntheta, spt, sxy, phi, theta, x, y, stat)

struct prjprm *prj;
int nphi, ntheta, spt, sxy;
const double phi[], theta[];
double x[], y[];
int stat[];
d2217 1
a2217 3
int zpnset(prj)

struct prjprm *prj;
d2318 11
a2328 7
int zpnx2s(prj, nx, ny, sxy, spt, x, y, phi, theta, stat)

struct prjprm *prj;
int nx, ny, sxy, spt;
const double x[], y[];
double phi[], theta[];
int stat[];
d2509 11
a2519 7
int zpns2x(prj, nphi, ntheta, spt, sxy, phi, theta, x, y, stat)

struct prjprm *prj;
int nphi, ntheta, spt, sxy;
const double phi[], theta[];
double x[], y[];
int stat[];
d2617 1
a2617 3
int zeaset(prj)

struct prjprm *prj;
d2651 11
a2661 7
int zeax2s(prj, nx, ny, sxy, spt, x, y, phi, theta, stat)

struct prjprm *prj;
int nx, ny, sxy, spt;
const double x[], y[];
double phi[], theta[];
int stat[];
d2753 11
a2763 7
int zeas2x(prj, nphi, ntheta, spt, sxy, phi, theta, x, y, stat)

struct prjprm *prj;
int nphi, ntheta, spt, sxy;
const double phi[], theta[];
double x[], y[];
int stat[];
d2854 1
a2854 3
int airset(prj)

struct prjprm *prj;
d2902 11
a2912 7
int airx2s(prj, nx, ny, sxy, spt, x, y, phi, theta, stat)

struct prjprm *prj;
int nx, ny, sxy, spt;
const double x[], y[];
double phi[], theta[];
int stat[];
d3049 11
a3059 7
int airs2x(prj, nphi, ntheta, spt, sxy, phi, theta, x, y, stat)

struct prjprm *prj;
int nphi, ntheta, spt, sxy;
const double phi[], theta[];
double x[], y[];
int stat[];
d3167 1
a3167 3
int cypset(prj)

struct prjprm *prj;
d3227 11
a3237 7
int cypx2s(prj, nx, ny, sxy, spt, x, y, phi, theta, stat)

struct prjprm *prj;
int nx, ny, sxy, spt;
const double x[], y[];
double phi[], theta[];
int stat[];
d3305 11
a3315 7
int cyps2x(prj, nphi, ntheta, spt, sxy, phi, theta, x, y, stat)

struct prjprm *prj;
int nphi, ntheta, spt, sxy;
const double phi[], theta[];
double x[], y[];
int stat[];
d3409 1
a3409 3
int ceaset(prj)

struct prjprm *prj;
d3455 11
a3465 7
int ceax2s(prj, nx, ny, sxy, spt, x, y, phi, theta, stat)

struct prjprm *prj;
int nx, ny, sxy, spt;
const double x[], y[];
double phi[], theta[];
int stat[];
d3546 11
a3556 7
int ceas2x(prj, nphi, ntheta, spt, sxy, phi, theta, x, y, stat)

struct prjprm *prj;
int nphi, ntheta, spt, sxy;
const double phi[], theta[];
double x[], y[];
int stat[];
d3632 1
a3632 3
int carset(prj)

struct prjprm *prj;
d3666 11
a3676 7
int carx2s(prj, nx, ny, sxy, spt, x, y, phi, theta, stat)

struct prjprm *prj;
int nx, ny, sxy, spt;
const double x[], y[];
double phi[], theta[];
int stat[];
d3743 11
a3753 7
int cars2x(prj, nphi, ntheta, spt, sxy, phi, theta, x, y, stat)

struct prjprm *prj;
int nphi, ntheta, spt, sxy;
const double phi[], theta[];
double x[], y[];
int stat[];
d3829 1
a3829 3
int merset(prj)

struct prjprm *prj;
d3863 11
a3873 7
int merx2s(prj, nx, ny, sxy, spt, x, y, phi, theta, stat)

struct prjprm *prj;
int nx, ny, sxy, spt;
const double x[], y[];
double phi[], theta[];
int stat[];
d3940 11
a3950 7
int mers2x(prj, nphi, ntheta, spt, sxy, phi, theta, x, y, stat)

struct prjprm *prj;
int nphi, ntheta, spt, sxy;
const double phi[], theta[];
double x[], y[];
int stat[];
d4036 1
a4036 3
int sflset(prj)

struct prjprm *prj;
d4070 11
a4080 7
int sflx2s(prj, nx, ny, sxy, spt, x, y, phi, theta, stat)

struct prjprm *prj;
int nx, ny, sxy, spt;
const double x[], y[];
double phi[], theta[];
int stat[];
d4160 11
a4170 7
int sfls2x(prj, nphi, ntheta, spt, sxy, phi, theta, x, y, stat)

struct prjprm *prj;
int nphi, ntheta, spt, sxy;
const double phi[], theta[];
double x[], y[];
int stat[];
d4251 1
a4251 3
int parset(prj)

struct prjprm *prj;
d4289 11
a4299 7
int parx2s(prj, nx, ny, sxy, spt, x, y, phi, theta, stat)

struct prjprm *prj;
int nx, ny, sxy, spt;
const double x[], y[];
double phi[], theta[];
int stat[];
d4403 11
a4413 7
int pars2x(prj, nphi, ntheta, spt, sxy, phi, theta, x, y, stat)

struct prjprm *prj;
int nphi, ntheta, spt, sxy;
const double phi[], theta[];
double x[], y[];
int stat[];
d4495 1
a4495 3
int molset(prj)

struct prjprm *prj;
d4528 11
a4538 7
int molx2s(prj, nx, ny, sxy, spt, x, y, phi, theta, stat)

struct prjprm *prj;
int nx, ny, sxy, spt;
const double x[], y[];
double phi[], theta[];
int stat[];
d4668 11
a4678 7
int mols2x(prj, nphi, ntheta, spt, sxy, phi, theta, x, y, stat)

struct prjprm *prj;
int nphi, ntheta, spt, sxy;
const double phi[], theta[];
double x[], y[];
int stat[];
d4788 1
a4788 3
int aitset(prj)

struct prjprm *prj;
d4820 11
a4830 7
int aitx2s(prj, nx, ny, sxy, spt, x, y, phi, theta, stat)

struct prjprm *prj;
int nx, ny, sxy, spt;
const double x[], y[];
double phi[], theta[];
int stat[];
d4938 11
a4948 7
int aits2x(prj, nphi, ntheta, spt, sxy, phi, theta, x, y, stat)

struct prjprm *prj;
int nphi, ntheta, spt, sxy;
const double phi[], theta[];
double x[], y[];
int stat[];
d5040 1
a5040 3
int copset(prj)

struct prjprm *prj;
d5088 11
a5098 7
int copx2s(prj, nx, ny, sxy, spt, x, y, phi, theta, stat)

struct prjprm *prj;
int nx, ny, sxy, spt;
const double x[], y[];
double phi[], theta[];
int stat[];
d5178 11
a5188 7
int cops2x(prj, nphi, ntheta, spt, sxy, phi, theta, x, y, stat)

struct prjprm *prj;
int nphi, ntheta, spt, sxy;
const double phi[], theta[];
double x[], y[];
int stat[];
d5316 1
a5316 3
int coeset(prj)

struct prjprm *prj;
d5368 11
a5378 7
int coex2s(prj, nx, ny, sxy, spt, x, y, phi, theta, stat)

struct prjprm *prj;
int nx, ny, sxy, spt;
const double x[], y[];
double phi[], theta[];
int stat[];
d5479 11
a5489 7
int coes2x(prj, nphi, ntheta, spt, sxy, phi, theta, x, y, stat)

struct prjprm *prj;
int nphi, ntheta, spt, sxy;
const double phi[], theta[];
double x[], y[];
int stat[];
d5582 1
a5582 3
int codset(prj)

struct prjprm *prj;
d5627 11
a5637 7
int codx2s(prj, nx, ny, sxy, spt, x, y, phi, theta, stat)

struct prjprm *prj;
int nx, ny, sxy, spt;
const double x[], y[];
double phi[], theta[];
int stat[];
d5717 11
a5727 7
int cods2x(prj, nphi, ntheta, spt, sxy, phi, theta, x, y, stat)

struct prjprm *prj;
int nphi, ntheta, spt, sxy;
const double phi[], theta[];
double x[], y[];
int stat[];
d5819 1
a5819 3
int cooset(prj)

struct prjprm *prj;
d5878 11
a5888 7
int coox2s(prj, nx, ny, sxy, spt, x, y, phi, theta, stat)

struct prjprm *prj;
int nx, ny, sxy, spt;
const double x[], y[];
double phi[], theta[];
int stat[];
d5981 11
a5991 7
int coos2x(prj, nphi, ntheta, spt, sxy, phi, theta, x, y, stat)

struct prjprm *prj;
int nphi, ntheta, spt, sxy;
const double phi[], theta[];
double x[], y[];
int stat[];
d6088 1
a6088 3
int bonset(prj)

struct prjprm *prj;
d6131 11
a6141 7
int bonx2s(prj, nx, ny, sxy, spt, x, y, phi, theta, stat)

struct prjprm *prj;
int nx, ny, sxy, spt;
const double x[], y[];
double phi[], theta[];
int stat[];
d6235 11
a6245 7
int bons2x(prj, nphi, ntheta, spt, sxy, phi, theta, x, y, stat)

struct prjprm *prj;
int nphi, ntheta, spt, sxy;
const double phi[], theta[];
double x[], y[];
int stat[];
d6334 1
a6334 3
int pcoset(prj)

struct prjprm *prj;
d6371 11
a6381 7
int pcox2s(prj, nx, ny, sxy, spt, x, y, phi, theta, stat)

struct prjprm *prj;
int nx, ny, sxy, spt;
const double x[], y[];
double phi[], theta[];
int stat[];
d6519 11
a6529 7
int pcos2x(prj, nphi, ntheta, spt, sxy, phi, theta, x, y, stat)

struct prjprm *prj;
int nphi, ntheta, spt, sxy;
const double phi[], theta[];
double x[], y[];
int stat[];
d6624 1
a6624 3
int tscset(prj)

struct prjprm *prj;
d6658 11
a6668 7
int tscx2s(prj, nx, ny, sxy, spt, x, y, phi, theta, stat)

struct prjprm *prj;
int nx, ny, sxy, spt;
const double x[], y[];
double phi[], theta[];
int stat[];
d6804 11
a6814 7
int tscs2x(prj, nphi, ntheta, spt, sxy, phi, theta, x, y, stat)

struct prjprm *prj;
int nphi, ntheta, spt, sxy;
const double phi[], theta[];
double x[], y[];
int stat[];
d6980 1
a6980 3
int cscset(prj)

struct prjprm *prj;
d7014 11
a7024 7
int cscx2s(prj, nx, ny, sxy, spt, x, y, phi, theta, stat)

struct prjprm *prj;
int nx, ny, sxy, spt;
const double x[], y[];
double phi[], theta[];
int stat[];
d7233 11
a7243 7
int cscs2x(prj, nphi, ntheta, spt, sxy, phi, theta, x, y, stat)

struct prjprm *prj;
int nphi, ntheta, spt, sxy;
const double phi[], theta[];
double x[], y[];
int stat[];
d7446 1
a7446 3
int qscset(prj)

struct prjprm *prj;
d7480 11
a7490 7
int qscx2s(prj, nx, ny, sxy, spt, x, y, phi, theta, stat)

struct prjprm *prj;
int nx, ny, sxy, spt;
const double x[], y[];
double phi[], theta[];
int stat[];
d7731 11
a7741 7
int qscs2x(prj, nphi, ntheta, spt, sxy, phi, theta, x, y, stat)

struct prjprm *prj;
int nphi, ntheta, spt, sxy;
const double phi[], theta[];
double x[], y[];
int stat[];
d7993 1
a7993 3
int hpxset(prj)

struct prjprm *prj;
d8046 11
a8056 7
int hpxx2s(prj, nx, ny, sxy, spt, x, y, phi, theta, stat)

struct prjprm *prj;
int nx, ny, sxy, spt;
const double x[], y[];
double phi[], theta[];
int stat[];
d8202 11
a8212 7
int hpxs2x(prj, nphi, ntheta, spt, sxy, phi, theta, x, y, stat)

struct prjprm *prj;
int nphi, ntheta, spt, sxy;
const double phi[], theta[];
double x[], y[];
int stat[];
d8338 1
a8338 3
int xphset(prj)

struct prjprm *prj;
d8380 11
a8390 7
int xphx2s(prj, nx, ny, sxy, spt, x, y, phi, theta, stat)

struct prjprm *prj;
int nx, ny, sxy, spt;
const double x[], y[];
double phi[], theta[];
int stat[];
d8545 11
a8555 7
int xphs2x(prj, nphi, ntheta, spt, sxy, phi, theta, x, y, stat)

struct prjprm *prj;
int nphi, ntheta, spt, sxy;
const double phi[], theta[];
double x[], y[];
int stat[];
@


6.2.1.1
log
@WCSLIB 6.2 development branch.
@
text
@d25 1
a25 1
  $Id: prj.c,v 6.2 2018/10/20 10:03:13 mcalabre Exp $
@


6.2.1.2
log
@Updated date in copyright notice.
@
text
@d4 1
a4 1
  Copyright (C) 1995-2019, Mark Calabretta
d25 1
a25 1
  $Id: prj.c,v 6.2.1.1 2018/10/20 10:04:15 mcalabre Exp mcalabre $
@


6.2.1.3
log
@In prjfree(), use wcserr_clear() to free the wcserr struct, including any
memory that may have been allocated to store a message.
@
text
@d25 1
a25 1
  $Id: prj.c,v 6.2.1.2 2019/05/10 01:56:50 mcalabre Exp mcalabre $
d198 4
a201 1
  wcserr_clear(&(prj->err));
@


6.2.1.4
log
@Switched to ANSI style argument lists in function definitions.
@
text
@d25 1
a25 1
  $Id: prj.c,v 6.2.1.3 2019/07/08 03:29:49 mcalabre Exp mcalabre $
d143 3
a145 1
int prjini(struct prjprm *prj)
d191 3
a193 1
int prjfree(struct prjprm *prj)
d205 3
a207 1
int prjprt(const struct prjprm *prj)
d309 6
a314 8
int prjbchk(
  double tol,
  int nphi,
  int ntheta,
  int spt,
  double phi[],
  double theta[],
  int stat[])
d368 3
a370 1
int prjset(struct prjprm *prj)
d450 7
a456 11
int prjx2s(
  struct prjprm *prj,
  int nx,
  int ny,
  int sxy,
  int spt,
  const double x[],
  const double y[],
  double phi[],
  double theta[],
  int stat[])
d472 7
a478 11
int prjs2x(
  struct prjprm *prj,
  int nphi,
  int ntheta,
  int spt,
  int sxy,
  const double phi[],
  const double theta[],
  double x[],
  double y[],
  int stat[])
d497 4
a500 4
int prjoff(
  struct prjprm *prj,
  const double phi0,
  const double theta0)
d558 3
a560 1
int azpset(struct prjprm *prj)
d612 7
a618 11
int azpx2s(
  struct prjprm *prj,
  int nx,
  int ny,
  int sxy,
  int spt,
  const double x[],
  const double y[],
  double phi[],
  double theta[],
  int stat[])
d727 7
a733 11
int azps2x(
  struct prjprm *prj,
  int nphi,
  int ntheta,
  int spt,
  int sxy,
  const double phi[],
  const double theta[],
  double x[],
  double y[],
  int stat[])
d873 3
a875 1
int szpset(struct prjprm *prj)
d925 7
a931 11
int szpx2s(
  struct prjprm *prj,
  int nx,
  int ny,
  int sxy,
  int spt,
  const double x[],
  const double y[],
  double phi[],
  double theta[],
  int stat[])
d1060 7
a1066 11
int szps2x(
  struct prjprm *prj,
  int nphi,
  int ntheta,
  int spt,
  int sxy,
  const double phi[],
  const double theta[],
  double x[],
  double y[],
  int stat[])
d1194 3
a1196 1
int tanset(struct prjprm *prj)
d1223 7
a1229 11
int tanx2s(
  struct prjprm *prj,
  int nx,
  int ny,
  int sxy,
  int spt,
  const double x[],
  const double y[],
  double phi[],
  double theta[],
  int stat[])
d1307 7
a1313 11
int tans2x(
  struct prjprm *prj,
  int nphi,
  int ntheta,
  int spt,
  int sxy,
  const double phi[],
  const double theta[],
  double x[],
  double y[],
  int stat[])
d1416 3
a1418 1
int stgset(struct prjprm *prj)
d1452 7
a1458 11
int stgx2s(
  struct prjprm *prj,
  int nx,
  int ny,
  int sxy,
  int spt,
  const double x[],
  const double y[],
  double phi[],
  double theta[],
  int stat[])
d1528 7
a1534 11
int stgs2x(
  struct prjprm *prj,
  int nphi,
  int ntheta,
  int spt,
  int sxy,
  const double phi[],
  const double theta[],
  double x[],
  double y[],
  int stat[])
d1633 3
a1635 1
int sinset(struct prjprm *prj)
d1669 7
a1675 11
int sinx2s(
  struct prjprm *prj,
  int nx,
  int ny,
  int sxy,
  int spt,
  const double x[],
  const double y[],
  double phi[],
  double theta[],
  int stat[])
d1834 7
a1840 11
int sins2x(
  struct prjprm *prj,
  int nphi,
  int ntheta,
  int spt,
  int sxy,
  const double phi[],
  const double theta[],
  double x[],
  double y[],
  int stat[])
d1967 3
a1969 1
int arcset(struct prjprm *prj)
d2003 7
a2009 11
int arcx2s(
  struct prjprm *prj,
  int nx,
  int ny,
  int sxy,
  int spt,
  const double x[],
  const double y[],
  double phi[],
  double theta[],
  int stat[])
d2088 7
a2094 11
int arcs2x(
  struct prjprm *prj,
  int nphi,
  int ntheta,
  int spt,
  int sxy,
  const double phi[],
  const double theta[],
  double x[],
  double y[],
  int stat[])
d2179 3
a2181 1
int zpnset(struct prjprm *prj)
d2282 7
a2288 11
int zpnx2s(
  struct prjprm *prj,
  int nx,
  int ny,
  int sxy,
  int spt,
  const double x[],
  const double y[],
  double phi[],
  double theta[],
  int stat[])
d2469 7
a2475 11
int zpns2x(
  struct prjprm *prj,
  int nphi,
  int ntheta,
  int spt,
  int sxy,
  const double phi[],
  const double theta[],
  double x[],
  double y[],
  int stat[])
d2573 3
a2575 1
int zeaset(struct prjprm *prj)
d2609 7
a2615 11
int zeax2s(
  struct prjprm *prj,
  int nx,
  int ny,
  int sxy,
  int spt,
  const double x[],
  const double y[],
  double phi[],
  double theta[],
  int stat[])
d2707 7
a2713 11
int zeas2x(
  struct prjprm *prj,
  int nphi,
  int ntheta,
  int spt,
  int sxy,
  const double phi[],
  const double theta[],
  double x[],
  double y[],
  int stat[])
d2804 3
a2806 1
int airset(struct prjprm *prj)
d2854 7
a2860 11
int airx2s(
  struct prjprm *prj,
  int nx,
  int ny,
  int sxy,
  int spt,
  const double x[],
  const double y[],
  double phi[],
  double theta[],
  int stat[])
d2997 7
a3003 11
int airs2x(
  struct prjprm *prj,
  int nphi,
  int ntheta,
  int spt,
  int sxy,
  const double phi[],
  const double theta[],
  double x[],
  double y[],
  int stat[])
d3111 3
a3113 1
int cypset(struct prjprm *prj)
d3173 7
a3179 11
int cypx2s(
  struct prjprm *prj,
  int nx,
  int ny,
  int sxy,
  int spt,
  const double x[],
  const double y[],
  double phi[],
  double theta[],
  int stat[])
d3247 7
a3253 11
int cyps2x(
  struct prjprm *prj,
  int nphi,
  int ntheta,
  int spt,
  int sxy,
  const double phi[],
  const double theta[],
  double x[],
  double y[],
  int stat[])
d3347 3
a3349 1
int ceaset(struct prjprm *prj)
d3395 7
a3401 11
int ceax2s(
  struct prjprm *prj,
  int nx,
  int ny,
  int sxy,
  int spt,
  const double x[],
  const double y[],
  double phi[],
  double theta[],
  int stat[])
d3482 7
a3488 11
int ceas2x(
  struct prjprm *prj,
  int nphi,
  int ntheta,
  int spt,
  int sxy,
  const double phi[],
  const double theta[],
  double x[],
  double y[],
  int stat[])
d3564 3
a3566 1
int carset(struct prjprm *prj)
d3600 7
a3606 11
int carx2s(
  struct prjprm *prj,
  int nx,
  int ny,
  int sxy,
  int spt,
  const double x[],
  const double y[],
  double phi[],
  double theta[],
  int stat[])
d3673 7
a3679 11
int cars2x(
  struct prjprm *prj,
  int nphi,
  int ntheta,
  int spt,
  int sxy,
  const double phi[],
  const double theta[],
  double x[],
  double y[],
  int stat[])
d3755 3
a3757 1
int merset(struct prjprm *prj)
d3791 7
a3797 11
int merx2s(
  struct prjprm *prj,
  int nx,
  int ny,
  int sxy,
  int spt,
  const double x[],
  const double y[],
  double phi[],
  double theta[],
  int stat[])
d3864 7
a3870 11
int mers2x(
  struct prjprm *prj,
  int nphi,
  int ntheta,
  int spt,
  int sxy,
  const double phi[],
  const double theta[],
  double x[],
  double y[],
  int stat[])
d3956 3
a3958 1
int sflset(struct prjprm *prj)
d3992 7
a3998 11
int sflx2s(
  struct prjprm *prj,
  int nx,
  int ny,
  int sxy,
  int spt,
  const double x[],
  const double y[],
  double phi[],
  double theta[],
  int stat[])
d4078 7
a4084 11
int sfls2x(
  struct prjprm *prj,
  int nphi,
  int ntheta,
  int spt,
  int sxy,
  const double phi[],
  const double theta[],
  double x[],
  double y[],
  int stat[])
d4165 3
a4167 1
int parset(struct prjprm *prj)
d4205 7
a4211 11
int parx2s(
  struct prjprm *prj,
  int nx,
  int ny,
  int sxy,
  int spt,
  const double x[],
  const double y[],
  double phi[],
  double theta[],
  int stat[])
d4315 7
a4321 11
int pars2x(
  struct prjprm *prj,
  int nphi,
  int ntheta,
  int spt,
  int sxy,
  const double phi[],
  const double theta[],
  double x[],
  double y[],
  int stat[])
d4403 3
a4405 1
int molset(struct prjprm *prj)
d4438 7
a4444 11
int molx2s(
  struct prjprm *prj,
  int nx,
  int ny,
  int sxy,
  int spt,
  const double x[],
  const double y[],
  double phi[],
  double theta[],
  int stat[])
d4574 7
a4580 11
int mols2x(
  struct prjprm *prj,
  int nphi,
  int ntheta,
  int spt,
  int sxy,
  const double phi[],
  const double theta[],
  double x[],
  double y[],
  int stat[])
d4690 3
a4692 1
int aitset(struct prjprm *prj)
d4724 7
a4730 11
int aitx2s(
  struct prjprm *prj,
  int nx,
  int ny,
  int sxy,
  int spt,
  const double x[],
  const double y[],
  double phi[],
  double theta[],
  int stat[])
d4838 7
a4844 11
int aits2x(
  struct prjprm *prj,
  int nphi,
  int ntheta,
  int spt,
  int sxy,
  const double phi[],
  const double theta[],
  double x[],
  double y[],
  int stat[])
d4936 3
a4938 1
int copset(struct prjprm *prj)
d4986 7
a4992 11
int copx2s(
  struct prjprm *prj,
  int nx,
  int ny,
  int sxy,
  int spt,
  const double x[],
  const double y[],
  double phi[],
  double theta[],
  int stat[])
d5072 7
a5078 11
int cops2x(
  struct prjprm *prj,
  int nphi,
  int ntheta,
  int spt,
  int sxy,
  const double phi[],
  const double theta[],
  double x[],
  double y[],
  int stat[])
d5206 3
a5208 1
int coeset(struct prjprm *prj)
d5260 7
a5266 11
int coex2s(
  struct prjprm *prj,
  int nx,
  int ny,
  int sxy,
  int spt,
  const double x[],
  const double y[],
  double phi[],
  double theta[],
  int stat[])
d5367 7
a5373 11
int coes2x(
  struct prjprm *prj,
  int nphi,
  int ntheta,
  int spt,
  int sxy,
  const double phi[],
  const double theta[],
  double x[],
  double y[],
  int stat[])
d5466 3
a5468 1
int codset(struct prjprm *prj)
d5513 7
a5519 11
int codx2s(
  struct prjprm *prj,
  int nx,
  int ny,
  int sxy,
  int spt,
  const double x[],
  const double y[],
  double phi[],
  double theta[],
  int stat[])
d5599 7
a5605 11
int cods2x(
  struct prjprm *prj,
  int nphi,
  int ntheta,
  int spt,
  int sxy,
  const double phi[],
  const double theta[],
  double x[],
  double y[],
  int stat[])
d5697 3
a5699 1
int cooset(struct prjprm *prj)
d5758 7
a5764 11
int coox2s(
  struct prjprm *prj,
  int nx,
  int ny,
  int sxy,
  int spt,
  const double x[],
  const double y[],
  double phi[],
  double theta[],
  int stat[])
d5857 7
a5863 11
int coos2x(
  struct prjprm *prj,
  int nphi,
  int ntheta,
  int spt,
  int sxy,
  const double phi[],
  const double theta[],
  double x[],
  double y[],
  int stat[])
d5960 3
a5962 1
int bonset(struct prjprm *prj)
d6005 7
a6011 11
int bonx2s(
  struct prjprm *prj,
  int nx,
  int ny,
  int sxy,
  int spt,
  const double x[],
  const double y[],
  double phi[],
  double theta[],
  int stat[])
d6105 7
a6111 11
int bons2x(
  struct prjprm *prj,
  int nphi,
  int ntheta,
  int spt,
  int sxy,
  const double phi[],
  const double theta[],
  double x[],
  double y[],
  int stat[])
d6200 3
a6202 1
int pcoset(struct prjprm *prj)
d6239 7
a6245 11
int pcox2s(
  struct prjprm *prj,
  int nx,
  int ny,
  int sxy,
  int spt,
  const double x[],
  const double y[],
  double phi[],
  double theta[],
  int stat[])
d6383 7
a6389 11
int pcos2x(
  struct prjprm *prj,
  int nphi,
  int ntheta,
  int spt,
  int sxy,
  const double phi[],
  const double theta[],
  double x[],
  double y[],
  int stat[])
d6484 3
a6486 1
int tscset(struct prjprm *prj)
d6520 7
a6526 11
int tscx2s(
  struct prjprm *prj,
  int nx,
  int ny,
  int sxy,
  int spt,
  const double x[],
  const double y[],
  double phi[],
  double theta[],
  int stat[])
d6662 7
a6668 11
int tscs2x(
  struct prjprm *prj,
  int nphi,
  int ntheta,
  int spt,
  int sxy,
  const double phi[],
  const double theta[],
  double x[],
  double y[],
  int stat[])
d6834 3
a6836 1
int cscset(struct prjprm *prj)
d6870 7
a6876 11
int cscx2s(
  struct prjprm *prj,
  int nx,
  int ny,
  int sxy,
  int spt,
  const double x[],
  const double y[],
  double phi[],
  double theta[],
  int stat[])
d7085 7
a7091 11
int cscs2x(
  struct prjprm *prj,
  int nphi,
  int ntheta,
  int spt,
  int sxy,
  const double phi[],
  const double theta[],
  double x[],
  double y[],
  int stat[])
d7294 3
a7296 1
int qscset(struct prjprm *prj)
d7330 7
a7336 11
int qscx2s(
  struct prjprm *prj,
  int nx,
  int ny,
  int sxy,
  int spt,
  const double x[],
  const double y[],
  double phi[],
  double theta[],
  int stat[])
d7577 7
a7583 11
int qscs2x(
  struct prjprm *prj,
  int nphi,
  int ntheta,
  int spt,
  int sxy,
  const double phi[],
  const double theta[],
  double x[],
  double y[],
  int stat[])
d7835 3
a7837 1
int hpxset(struct prjprm *prj)
d7890 7
a7896 11
int hpxx2s(
  struct prjprm *prj,
  int nx,
  int ny,
  int sxy,
  int spt,
  const double x[],
  const double y[],
  double phi[],
  double theta[],
  int stat[])
d8042 7
a8048 11
int hpxs2x(
  struct prjprm *prj,
  int nphi,
  int ntheta,
  int spt,
  int sxy,
  const double phi[],
  const double theta[],
  double x[],
  double y[],
  int stat[])
d8174 3
a8176 1
int xphset(struct prjprm *prj)
d8218 7
a8224 11
int xphx2s(
  struct prjprm *prj,
  int nx,
  int ny,
  int sxy,
  int spt,
  const double x[],
  const double y[],
  double phi[],
  double theta[],
  int stat[])
d8379 7
a8385 11
int xphs2x(
  struct prjprm *prj,
  int nphi,
  int ntheta,
  int spt,
  int sxy,
  const double phi[],
  const double theta[],
  double x[],
  double y[],
  int stat[])
@


6.1
log
@WCSLIB 6.1
@
text
@d3 1
a3 1
  WCSLIB 6.1 - an implementation of the FITS WCS standard.
d25 1
a25 1
  $Id: prj.c,v 5.20.1.1 2018/10/05 05:33:33 mcalabre Exp mcalabre $
@


6.1.1.1
log
@WCSLIB 6.1 development branch.
@
text
@d25 1
a25 1
  $Id: prj.c,v 6.1 2018/10/19 08:35:17 mcalabre Exp $
@


5.20
log
@WCSLIB 5.20
@
text
@d3 1
a3 1
  WCSLIB 5.20 - an implementation of the FITS WCS standard.
d25 1
a25 1
  $Id: prj.c,v 5.19.1.1 2018/07/26 15:41:40 mcalabre Exp mcalabre $
@


5.20.1.1
log
@WCSLIB 5.20 development branch.
@
text
@d25 1
a25 1
  $Id: prj.c,v 5.20 2018/10/05 05:32:41 mcalabre Exp $
@


5.19
log
@WCSLIB 5.19
@
text
@d3 1
a3 1
  WCSLIB 5.19 - an implementation of the FITS WCS standard.
d25 1
a25 1
  $Id: prj.c,v 5.18.1.2 2018/07/25 00:22:45 mcalabre Exp mcalabre $
@


5.19.1.1
log
@WCSLIB 5.19 development branch.
@
text
@d25 1
a25 1
  $Id: prj.c,v 5.19 2018/07/26 15:37:04 mcalabre Exp $
@


5.18
log
@WCSLIB 5.18
@
text
@d3 1
a3 1
  WCSLIB 5.18 - an implementation of the FITS WCS standard.
d25 1
a25 1
  $Id: prj.c,v 5.17.1.2 2018/01/10 08:25:34 mcalabre Exp mcalabre $
d289 1
a289 1
    wcsutil_fptr2str((int (*)(void))prj->prjx2s, hext));
d291 1
a291 1
    wcsutil_fptr2str((int (*)(void))prj->prjs2x, hext));
@


5.18.1.1
log
@WCSLIB 5.18 development branch.
@
text
@d25 1
a25 1
  $Id: prj.c,v 5.18 2018/01/10 08:32:14 mcalabre Exp $
@


5.18.1.2
log
@Changed function prototype of wcsutil_fptr2str() to avert
-Wcast-function-type warnings from gcc 8.1.0.
@
text
@d25 1
a25 1
  $Id: prj.c,v 5.18.1.1 2018/01/10 08:33:04 mcalabre Exp mcalabre $
d289 1
a289 1
    wcsutil_fptr2str((void (*)(void))prj->prjx2s, hext));
d291 1
a291 1
    wcsutil_fptr2str((void (*)(void))prj->prjs2x, hext));
@


5.17
log
@WCSLIB 5.17
@
text
@d3 2
a4 2
  WCSLIB 5.17 - an implementation of the FITS WCS standard.
  Copyright (C) 1995-2017, Mark Calabretta
d25 1
a25 1
  $Id: prj.c,v 5.16.1.1 2017/01/15 04:28:59 mcalabre Exp mcalabre $
@


5.17.1.1
log
@WCSLIB 5.17 development branch.
@
text
@d25 1
a25 1
  $Id: prj.c,v 5.17 2017/09/18 08:44:23 mcalabre Exp $
@


5.17.1.2
log
@Updated date in copyright notice.
@
text
@d4 1
a4 1
  Copyright (C) 1995-2018, Mark Calabretta
d25 1
a25 1
  $Id: prj.c,v 5.17.1.1 2017/09/18 08:45:59 mcalabre Exp mcalabre $
@


5.16
log
@WCSLIB 5.16
@
text
@d3 1
a3 1
  WCSLIB 5.16 - an implementation of the FITS WCS standard.
d25 1
a25 1
  $Id: prj.c,v 5.15.1.2 2017/01/15 04:13:33 mcalabre Exp mcalabre $
@


5.16.1.1
log
@WCSLIB 5.16 development branch.
@
text
@d25 1
a25 1
  $Id: prj.c,v 5.16 2017/01/15 04:25:01 mcalabre Exp $
@


5.15
log
@WCSLIB 5.15
@
text
@d3 2
a4 2
  WCSLIB 5.15 - an implementation of the FITS WCS standard.
  Copyright (C) 1995-2016, Mark Calabretta
d25 1
a25 1
  $Id: prj.c,v 5.14.1.1 2016/02/07 10:52:44 mcalabre Exp mcalabre $
@


5.15.1.1
log
@WCSLIB 5.15 development branch.
@
text
@d25 1
a25 1
  $Id: prj.c,v 5.15 2016/04/05 12:55:10 mcalabre Exp $
@


5.15.1.2
log
@Updated date in copyright notice.
@
text
@d4 1
a4 1
  Copyright (C) 1995-2017, Mark Calabretta
d25 1
a25 1
  $Id: prj.c,v 5.15.1.1 2016/04/05 12:58:35 mcalabre Exp mcalabre $
@


5.14
log
@WCSLIB 5.14
@
text
@d3 1
a3 1
  WCSLIB 5.14 - an implementation of the FITS WCS standard.
d25 1
a25 1
  $Id: prj.c,v 5.13.1.1 2016/01/26 08:54:32 mcalabre Exp mcalabre $
@


5.14.1.1
log
@WCSLIB 5.14 development branch.
@
text
@d25 1
a25 1
  $Id: prj.c,v 5.14 2016/02/07 10:49:31 mcalabre Exp $
@


5.13
log
@WCSLIB 5.13
@
text
@d3 1
a3 1
  WCSLIB 5.13 - an implementation of the FITS WCS standard.
d25 1
a25 1
  $Id: prj.c,v 5.12.1.2 2016/01/25 05:17:04 mcalabre Exp mcalabre $
@


5.13.1.1
log
@WCSLIB 5.13 development branch.
@
text
@d25 1
a25 1
  $Id: prj.c,v 5.13 2016/01/26 08:51:13 mcalabre Exp $
@


5.12
log
@WCSLIB 5.12
@
text
@d3 2
a4 2
  WCSLIB 5.12 - an implementation of the FITS WCS standard.
  Copyright (C) 1995-2015, Mark Calabretta
d25 1
a25 1
  $Id: prj.c,v 5.11.1.1 2015/10/18 09:16:27 mcalabre Exp mcalabre $
@


5.12.1.1
log
@WCSLIB 5.12 development branch.
@
text
@d25 1
a25 1
  $Id: prj.c,v 5.12 2015/11/15 02:13:00 mcalabre Exp $
@


5.12.1.2
log
@Updated date in copyright notice.
@
text
@d4 1
a4 1
  Copyright (C) 1995-2016, Mark Calabretta
d25 1
a25 1
  $Id: prj.c,v 5.12.1.1 2015/11/15 02:16:14 mcalabre Exp mcalabre $
@


5.11
log
@WCSLIB 5.11
@
text
@d3 1
a3 1
  WCSLIB 5.11 - an implementation of the FITS WCS standard.
d25 1
a25 1
  $Id: prj.c,v 5.10.1.1 2015/10/09 08:22:35 mcalabre Exp mcalabre $
@


5.11.1.1
log
@WCSLIB 5.11 development branch.
@
text
@d25 1
a25 1
  $Id: prj.c,v 5.11 2015/10/18 09:13:05 mcalabre Exp $
@


5.10
log
@WCSLIB 5.10
@
text
@d3 1
a3 1
  WCSLIB 5.10 - an implementation of the FITS WCS standard.
d25 1
a25 1
  $Id: prj.c,v 5.9.1.1 2015/07/21 09:28:07 mcalabre Exp mcalabre $
@


5.10.1.1
log
@WCSLIB 5.10 development branch.
@
text
@d25 1
a25 1
  $Id: prj.c,v 5.10 2015/10/09 08:19:15 mcalabre Exp $
@


5.9
log
@WCSLIB 5.9
@
text
@d3 1
a3 1
  WCSLIB 5.9 - an implementation of the FITS WCS standard.
d25 1
a25 1
  $Id: prj.c,v 5.8.1.1 2015/07/08 11:07:18 mcalabre Exp mcalabre $
@


5.9.1.1
log
@WCSLIB 5.9 development branch.
@
text
@d25 1
a25 1
  $Id: prj.c,v 5.9 2015/07/21 09:20:01 mcalabre Exp $
@


5.8
log
@WCSLIB 5.8
@
text
@d3 1
a3 1
  WCSLIB 5.8 - an implementation of the FITS WCS standard.
d25 1
a25 1
  $Id: prj.c,v 5.7.1.2 2015/07/08 07:12:41 mcalabre Exp mcalabre $
@


5.8.1.1
log
@WCSLIB 5.8 development branch.
@
text
@d25 1
a25 1
  $Id: prj.c,v 5.8 2015/07/08 11:03:59 mcalabre Exp $
@


5.7
log
@WCSLIB 5.7
@
text
@d3 1
a3 1
  WCSLIB 5.7 - an implementation of the FITS WCS standard.
d25 1
a25 1
  $Id: prj.c,v 5.6.1.2 2015/06/18 08:12:20 mcalabre Exp mcalabre $
d228 1
a228 1
      wcsprintf("  %#- 11.5g", prj->pv[0]);
@


5.7.1.1
log
@WCSLIB 5.7 development branch.
@
text
@d25 1
a25 1
  $Id: prj.c,v 5.7 2015/06/29 02:44:16 mcalabre Exp $
@


5.7.1.2
log
@Output formatting tweak for PVi_0a in prjprt().
@
text
@d25 1
a25 1
  $Id: prj.c,v 5.7.1.1 2015/06/29 02:47:24 mcalabre Exp mcalabre $
d228 1
a228 1
      wcsprintf(" %#- 11.5g", prj->pv[0]);
@


5.6
log
@WCSLIB 5.6
@
text
@d3 1
a3 1
  WCSLIB 5.6 - an implementation of the FITS WCS standard.
d25 1
a25 1
  $Id: prj.c,v 5.5.1.1 2015/05/05 13:21:00 mcalabre Exp mcalabre $
d292 14
@


5.6.1.1
log
@WCSLIB 5.6 development branch.
@
text
@d25 1
a25 1
  $Id: prj.c,v 5.6 2015/06/14 07:11:24 mcalabre Exp $
@


5.6.1.2
log
@Added prjperr().
@
text
@d25 1
a25 1
  $Id: prj.c,v 5.6.1.1 2015/06/14 07:14:44 mcalabre Exp mcalabre $
a291 14

  return 0;
}

/*--------------------------------------------------------------------------*/

int prjperr(const struct prjprm *prj, const char *prefix)

{
  if (prj == 0x0) return PRJERR_NULL_POINTER;

  if (prj->err) {
    wcserr_prt(prj->err, prefix);
  }
@


5.5
log
@WCSLIB 5.5
@
text
@d3 1
a3 1
  WCSLIB 5.5 - an implementation of the FITS WCS standard.
d25 1
a25 1
  $Id: prj.c,v 5.4.1.1 2015/04/21 14:44:28 mcalabre Exp mcalabre $
@


5.5.1.1
log
@WCSLIB 5.5 development branch.
@
text
@d25 1
a25 1
  $Id: prj.c,v 5.5 2015/05/05 13:16:31 mcalabre Exp $
@


5.4
log
@WCSLIB 5.4
@
text
@d3 1
a3 1
  WCSLIB 5.4 - an implementation of the FITS WCS standard.
d25 1
a25 1
  $Id: prj.c,v 5.3.1.1 2015/04/21 02:54:02 mcalabre Exp mcalabre $
@


5.4.1.1
log
@WCSLIB 5.4 development branch.
@
text
@d25 1
a25 1
  $Id: prj.c,v 5.4 2015/04/21 14:41:05 mcalabre Exp $
@


5.3
log
@WCSLIB 5.3
@
text
@d3 1
a3 1
  WCSLIB 5.3 - an implementation of the FITS WCS standard.
d25 1
a25 1
  $Id: prj.c,v 5.2.1.1 2015/04/15 12:39:14 mcalabre Exp mcalabre $
@


5.3.1.1
log
@WCSLIB 5.3 development branch.
@
text
@d25 1
a25 1
  $Id: prj.c,v 5.3 2015/04/21 02:50:51 mcalabre Exp $
@


5.2
log
@WCSLIB 5.2
@
text
@d3 1
a3 1
  WCSLIB 5.2 - an implementation of the FITS WCS standard.
d25 1
a25 1
  $Id: prj.c,v 5.1.1.1 2015/04/07 11:01:10 mcalabre Exp mcalabre $
@


5.2.1.1
log
@WCSLIB 5.2 development branch.
@
text
@d25 1
a25 1
  $Id: prj.c,v 5.2 2015/04/15 12:35:07 mcalabre Exp $
@


5.1
log
@WCSLIB 5.1
@
text
@d3 1
a3 1
  WCSLIB 5.1 - an implementation of the FITS WCS standard.
d25 1
a25 1
  $Id: prj.c,v 5.0.1.1 2015/04/05 12:28:00 mcalabre Exp mcalabre $
@


5.1.1.1
log
@WCSLIB 5.1 development branch.
@
text
@d25 1
a25 1
  $Id: prj.c,v 5.1 2015/04/07 10:56:36 mcalabre Exp $
@


5.0
log
@WCSLIB 5.0
@
text
@d3 1
a3 1
  WCSLIB 5.0 - an implementation of the FITS WCS standard.
d25 1
a25 1
  $Id: prj.c,v 4.25.1.4 2015/04/03 01:51:43 mcalabre Exp mcalabre $
@


5.0.1.1
log
@WCSLIB 5.0 development branch.
@
text
@d25 1
a25 1
  $Id: prj.c,v 5.0 2015/04/05 12:24:59 mcalabre Exp $
@


4.25
log
@WCSLIB 4.25
@
text
@d3 2
a4 2
  WCSLIB 4.25 - an implementation of the FITS WCS standard.
  Copyright (C) 1995-2014, Mark Calabretta
d25 1
a25 1
  $Id: prj.c,v 4.24.1.1 2014/09/18 15:28:09 mcalabre Exp mcalabre $
d228 1
a228 1
      wcsprintf(" %- 11.5g", prj->pv[0]);
d240 1
a240 1
        wcsprintf("  %- 11.5g", prj->pv[i]);
d279 1
a279 1
    wcsprintf("  %- 11.5g", prj->w[i]);
d283 1
a283 1
    wcsprintf("  %- 11.5g", prj->w[i]);
d315 16
a330 13
      if (*phip < -180.0) {
        if (*phip < -180.0-tol) {
          *statp = 1;
          status = 1;
        } else {
          *phip = -180.0;
        }
      } else if (180.0 < *phip) {
        if (180.0+tol < *phip) {
          *statp = 1;
          status = 1;
        } else {
          *phip = 180.0;
a331 1
      }
d333 14
a346 13
      if (*thetap < -90.0) {
        if (*thetap < -90.0-tol) {
          *statp = 1;
          status = 1;
        } else {
          *thetap = -90.0;
        }
      } else if (90.0 < *thetap) {
        if (90.0+tol < *thetap) {
          *statp = 1;
          status = 1;
        } else {
          *thetap = 90.0;
d2411 1
a2411 1
          /* Disect the interval. */
@


4.25.1.1
log
@WCSLIB 4.25 development branch.
@
text
@d25 1
a25 1
  $Id: prj.c,v 4.25 2014/12/14 14:29:36 mcalabre Exp $
@


4.25.1.2
log
@Updated date in copyright notice.
@
text
@d4 1
a4 1
  Copyright (C) 1995-2015, Mark Calabretta
d25 1
a25 1
  $Id: prj.c,v 4.25.1.1 2014/12/14 14:32:45 mcalabre Exp mcalabre $
@


4.25.1.3
log
@In prjbchk(), skip (phi,theta) already flagged as invalid in the stat
vector, as they will not have been initialized (uncovered by valgrind,
reported by Ger van Diepen).
@
text
@d25 1
a25 1
  $Id: prj.c,v 4.25.1.2 2015/01/06 01:01:06 mcalabre Exp mcalabre $
d315 6
a320 16
      /* Skip values already marked as illegal. */
      if (*statp == 0) {
        if (*phip < -180.0) {
          if (*phip < -180.0-tol) {
            *statp = 1;
            status = 1;
          } else {
            *phip = -180.0;
          }
        } else if (180.0 < *phip) {
          if (180.0+tol < *phip) {
            *statp = 1;
            status = 1;
          } else {
            *phip = 180.0;
          }
d322 8
d331 13
a343 14
        if (*thetap < -90.0) {
          if (*thetap < -90.0-tol) {
            *statp = 1;
            status = 1;
          } else {
            *thetap = -90.0;
          }
        } else if (90.0 < *thetap) {
          if (90.0+tol < *thetap) {
            *statp = 1;
            status = 1;
          } else {
            *thetap = 90.0;
          }
@


4.25.1.4
log
@Tweaked output formatting in prjprt().
@
text
@d25 1
a25 1
  $Id: prj.c,v 4.25.1.3 2015/03/05 14:39:08 mcalabre Exp mcalabre $
d228 1
a228 1
      wcsprintf("  %#- 11.5g", prj->pv[0]);
d240 1
a240 1
        wcsprintf("  %#- 11.5g", prj->pv[i]);
d279 1
a279 1
    wcsprintf("  %#- 11.5g", prj->w[i]);
d283 1
a283 1
    wcsprintf("  %#- 11.5g", prj->w[i]);
d2411 1
a2411 1
          /* Dissect the interval. */
@


4.24
log
@WCSLIB 4.24
@
text
@d3 1
a3 1
  WCSLIB 4.24 - an implementation of the FITS WCS standard.
d25 1
a25 1
  $Id: prj.c,v 4.23.1.1 2014/05/13 05:53:49 mcalabre Exp mcalabre $
@


4.24.1.1
log
@WCSLIB 4.24 development branch.
@
text
@d25 1
a25 1
  $Id: prj.c,v 4.24 2014/09/18 15:25:00 mcalabre Exp $
@


4.23
log
@WCSLIB 4.23
@
text
@d3 1
a3 1
  WCSLIB 4.23 - an implementation of the FITS WCS standard.
d25 1
a25 1
  $Id: prj.c,v 4.22.1.1 2014/04/12 15:06:32 mcalabre Exp mcalabre $
@


4.23.1.1
log
@WCSLIB 4.23 development branch.
@
text
@d25 1
a25 1
  $Id: prj.c,v 4.23 2014/05/13 05:50:51 mcalabre Exp $
@


4.22
log
@WCSLIB 4.22
@
text
@d3 1
a3 1
  WCSLIB 4.22 - an implementation of the FITS WCS standard.
d25 1
a25 1
  $Id: prj.c,v 4.21.1.2 2014/04/12 14:39:52 mcalabre Exp mcalabre $
@


4.22.1.1
log
@WCSLIB 4.22 development branch.
@
text
@d25 1
a25 1
  $Id: prj.c,v 4.22 2014/04/12 15:03:52 mcalabre Exp $
@


4.21
log
@WCSLIB 4.21
@
text
@d3 1
a3 1
  WCSLIB 4.21 - an implementation of the FITS WCS standard.
d25 1
a25 1
  $Id: prj.c,v 4.20.1.4 2014/03/24 03:13:46 mcalabre Exp mcalabre $
d4055 1
a4055 1
  if (prj->bounds&4 && prjbchk(1.0e-13, nx, my, spt, phi, theta, stat)) {
d5122 1
d5127 12
d6179 1
a6179 1
*      prj->w[1]    1/r0
d6181 1
d6215 1
d6297 6
a6302 3
        /* Iterative solution using weighted division of the interval. */
        if (yj > 0.0) {
          thepos =  90.0;
d6304 8
a6311 3
          thepos = -90.0;
        }
        theneg = 0.0;
d6313 1
a6313 10
        xx = xj*xj;
        ymthe = yj - prj->w[0]*thepos;
        fpos = xx + ymthe*ymthe;
        fneg = -999.0;

        for (k = 0; k < 64; k++) {
          if (fneg < -100.0) {
            /* Equal division of the interval. */
            the = (thepos+theneg)/2.0;
          } else {
a6321 1
          }
d6323 17
a6339 16
          /* Compute the residue. */
          ymthe = yj - prj->w[0]*(the);
          tanthe = tand(the);
          f = xx + ymthe*(ymthe - prj->w[2]/tanthe);

          /* Check for convergence. */
          if (fabs(f) < tol) break;
          if (fabs(thepos-theneg) < tol) break;

          /* Redefine the interval. */
          if (f > 0.0) {
            thepos = the;
            fpos = f;
          } else {
            theneg = the;
            fneg = f;
d6379 1
a6379 1
  double alpha, costhe, cotthe, sinthe, therad;
d6419 2
a6420 5
    therad = (*thetap)*D2R;
    sincosd(*thetap, &sinthe, &costhe);

    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
      if (sinthe == 0.0) {
d6423 17
a6439 2
      } else {
        alpha  = (*xp)*sinthe;
d6441 3
a6443 2
        *xp = prj->r0*cotthe*sind(alpha) - prj->x0;
        *yp = prj->r0*(cotthe*(1.0 - cosd(alpha)) + therad) - prj->y0;
a6444 2

      *(statp++) = 0;
@


4.21.1.1
log
@WCSLIB 4.21 development branch.
@
text
@d25 1
a25 1
  $Id: prj.c,v 4.21 2014/03/24 05:12:27 mcalabre Exp $
@


4.21.1.2
log
@In pcox2s() and pcos2x(), use alternative projection equations for
greater numerical precision near theta == 0.  In cops2x(), return
an exact result for theta at the poles.  Relaxed the tolerance for
bounds checking a little in sflx2s().
@
text
@d4055 1
a4055 1
  if (prj->bounds&4 && prjbchk(1.0e-12, nx, my, spt, phi, theta, stat)) {
a5121 1
      /* Latitude of divergence. */
a5125 12
    } else if (fabs(*thetap) == 90.0) {
      /* Return an exact value at the poles. */
      r = 0.0;

      /* Bounds checking. */
      if (prj->bounds&1) {
        if ((*thetap < 0.0) != (prj->pv[1] < 0.0)) {
          istat = 1;
          if (!status) status = PRJERR_BAD_WORLD_SET("cops2x");
        }
      }

d6166 1
a6166 1
*      prj->w[1]    (180/pi)/r0
a6167 1
*      prj->w[3]    (pi/180)/(2*r0)
a6200 1
  prj->w[3] = D2R/prj->w[2];
d6282 3
a6284 6
        if (w < 1.0e-4) {
          /* To avoid cot(theta) blowing up near theta == 0. */
          the    = yj / (prj->w[0] + prj->w[3]*xj*xj);
          ymthe  = yj - prj->w[0]*the;
          tanthe = tand(the);

d6286 3
a6288 8
          /* Iterative solution using weighted division of the interval. */
          thepos = yj / prj->w[0];
          theneg = 0.0;

          /* Setting fneg = -fpos halves the interval in the first iter. */
          xx = xj*xj;
          fpos  =  xx;
          fneg  = -xx;
d6290 10
a6299 1
          for (k = 0; k < 64; k++) {
d6308 1
d6310 16
a6325 17
            /* Compute the residue. */
            ymthe  = yj - prj->w[0]*the;
            tanthe = tand(the);
            f = xx + ymthe*(ymthe - prj->w[2]/tanthe);

            /* Check for convergence. */
            if (fabs(f) < tol) break;
            if (fabs(thepos-theneg) < tol) break;

            /* Redefine the interval. */
            if (f > 0.0) {
              thepos = the;
              fpos = f;
            } else {
              theneg = the;
              fneg = f;
            }
d6365 1
a6365 1
  double cospsi, costhe, cotthe, sinpsi, sinthe, therad;
d6405 5
a6409 2
    if (*thetap == 0.0) {
      for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
d6412 5
a6416 1
        *(statp++) = 0;
d6419 1
a6419 19
    } else if (fabs(*thetap) < 1.0e-4) {
      /* To avoid cot(theta) blowing up near theta == 0. */
      for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
        *xp = prj->w[0]*(*xp)*cosd(*thetap) - prj->x0;
        *yp = (prj->w[0] + prj->w[3]*(*xp)*(*xp))*(*thetap) - prj->y0;
        *(statp++) = 0;
      }

    } else {
      therad = (*thetap)*D2R;
      sincosd(*thetap, &sinthe, &costhe);

      for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
        sincosd((*xp)*sinthe, &sinpsi, &cospsi);
        cotthe = costhe/sinthe;
        *xp = prj->r0*cotthe*sinpsi - prj->x0;
        *yp = prj->r0*(cotthe*(1.0 - cospsi) + therad) - prj->y0;
        *(statp++) = 0;
      }
@


4.20
log
@WCSLIB 4.20
@
text
@d3 2
a4 2
  WCSLIB 4.20 - an implementation of the FITS WCS standard.
  Copyright (C) 1995-2013, Mark Calabretta
d25 1
a25 1
  $Id: prj.c,v 4.19.1.2 2013/10/06 04:01:53 mcalabre Exp mcalabre $
d120 1
a120 1
* Generic routines.
d124 3
d129 3
d163 1
a163 1
  prj->bounds = 3;
d298 56
d479 2
a480 2
* Internal helper routine used by the *set() routines that forces
* (x,y) = (0,0) at (phi0,theta0).
d702 6
d1035 6
d1240 2
d1282 7
a1288 1
  return 0;
d1809 6
d2020 2
d2063 7
a2069 1
  return 0;
d2342 1
d2346 1
d2444 6
d2682 6
d2972 6
d3051 1
a3051 1
        tanxi = sqrt(1.0-cosxi*cosxi)/cosxi;
d3190 2
d3222 7
a3228 1
  return 0;
d3457 6
d3617 2
d3648 7
a3654 1
  return 0;
d3808 2
d3839 7
a3845 1
  return 0;
d4053 6
d4281 2
d4290 6
d4540 2
d4549 6
d4617 1
d4621 1
d4813 6
d5002 2
d5047 7
a5053 1
  return 0;
d5329 6
d5516 2
d5561 7
a5567 1
  return 0;
d5819 6
d6014 2
d6067 7
a6073 1
  return 0;
d6243 2
d6344 7
a6350 1
  return 0;
d6612 6
d7035 6
d7527 6
d7861 1
a7861 1
  double absy, s, sigma, slim, t, ylim, yr;
d7964 1
a7964 4
        s *= *thetap;
        if (s != 0.0) s -= *thetap;
        *phip += s;
        *thetap = t;
d7968 1
a7968 1
          if (slim <= fabs(s)) {
d7974 4
d7992 6
d8221 1
a8221 1
    phip   = phi + rowoff;
d8292 1
a8292 1
              *phip = 270.0;
d8327 6
@


4.20.1.1
log
@WCSLIB 4.20 development branch.
@
text
@d25 1
a25 1
  $Id: prj.c,v 4.20 2013/12/18 05:42:49 mcalabre Exp $
@


4.20.1.2
log
@Updated date in copyright notice.
@
text
@d4 1
a4 1
  Copyright (C) 1995-2014, Mark Calabretta
d25 1
a25 1
  $Id: prj.c,v 4.20.1.1 2013/12/18 05:46:55 mcalabre Exp mcalabre $
@


4.20.1.3
log
@New function prjbchk() performs bounds checking on native spherical
coordinates.  It is invoked automatically by the deprojection (x2s)
routines if prjprm::bounds&4 is set.

Bug fixes: in hpxx2s() relating to bounds checking, introduced at 4.20,
reported by Michael Droettboom; in parx2s() and molx2s() relating to
setting the stat vector; in hpxx2s() relating to implementation of the
vector API; and in xphx2s() relating to setting an out-of-bounds value
of phi.
@
text
@d25 1
a25 1
  $Id: prj.c,v 4.20.1.2 2014/03/21 06:32:19 mcalabre Exp mcalabre $
d120 1
a120 1
* Generic routines:
a123 3
* prjfree frees any memory that may have been allocated to store an error
*        message in the prjprm struct.
*
a125 3
* prjbchk performs bounds checking on the native coordinates returned by the
*        *x2s() routines.
*
d157 1
a157 1
  prj->bounds = 7;
a291 56
int prjbchk(tol, nphi, ntheta, spt, phi, theta, stat)

double tol;
int nphi, ntheta, spt;
double phi[], theta[];
int stat[];

{
  int status = 0;
  register int iphi, itheta, *statp;
  register double *phip, *thetap;

  phip   = phi;
  thetap = theta;
  statp  = stat;
  for (itheta = 0; itheta < ntheta; itheta++) {
    for (iphi = 0; iphi < nphi; iphi++, phip += spt, thetap += spt, statp++) {
      if (*phip < -180.0) {
        if (*phip < -180.0-tol) {
          *statp = 1;
          status = 1;
        } else {
          *phip = -180.0;
        }
      } else if (180.0 < *phip) {
        if (180.0+tol < *phip) {
          *statp = 1;
          status = 1;
        } else {
          *phip = 180.0;
        }
      }

      if (*thetap < -90.0) {
        if (*thetap < -90.0-tol) {
          *statp = 1;
          status = 1;
        } else {
          *thetap = -90.0;
        }
      } else if (90.0 < *thetap) {
        if (90.0+tol < *thetap) {
          *statp = 1;
          status = 1;
        } else {
          *thetap = 90.0;
        }
      }
    }
  }

  return status;
}

/*--------------------------------------------------------------------------*/

d417 2
a418 2
* Internal helper routine used by the *set() routines - not intended for
* outside use.  It forces (x,y) = (0,0) at (phi0,theta0).
a639 6

  /* Do bounds checking on the native coordinates. */
  if (prj->bounds&4 && prjbchk(1.0e-13, nx, my, spt, phi, theta, stat)) {
    if (!status) status = PRJERR_BAD_PIX_SET("azpx2s");
  }

a966 6

  /* Do bounds checking on the native coordinates. */
  if (prj->bounds&4 && prjbchk(1.0e-13, nx, my, spt, phi, theta, stat)) {
    if (!status) status = PRJERR_BAD_PIX_SET("szpx2s");
  }

a1205 6

  /* Do bounds checking on the native coordinates. */
  if (prj->bounds&4 && prjbchk(1.0e-13, nx, my, spt, phi, theta, stat)) {
    if (!status) status = PRJERR_BAD_PIX_SET("tanx2s");
  }

a1726 6

  /* Do bounds checking on the native coordinates. */
  if (prj->bounds&4 && prjbchk(1.0e-13, nx, my, spt, phi, theta, stat)) {
    if (!status) status = PRJERR_BAD_PIX_SET("sinx2s");
  }

a1972 6

  /* Do bounds checking on the native coordinates. */
  if (prj->bounds&4 && prjbchk(1.0e-13, nx, my, spt, phi, theta, stat)) {
    if (!status) status = PRJERR_BAD_PIX_SET("arcx2s");
  }

a2245 1

a2248 1

a2345 6

  /* Do bounds checking on the native coordinates. */
  if (prj->bounds&4 && prjbchk(1.0e-13, nx, my, spt, phi, theta, stat)) {
    if (!status) status = PRJERR_BAD_PIX_SET("zpnx2s");
  }

a2577 6

  /* Do bounds checking on the native coordinates. */
  if (prj->bounds&4 && prjbchk(1.0e-13, nx, my, spt, phi, theta, stat)) {
    if (!status) status = PRJERR_BAD_PIX_SET("zeax2s");
  }

a2861 6

  /* Do bounds checking on the native coordinates. */
  if (prj->bounds&4 && prjbchk(1.0e-13, nx, my, spt, phi, theta, stat)) {
    if (!status) status = PRJERR_BAD_PIX_SET("airx2s");
  }

d2935 1
a2935 1
        tanxi = sqrt(1.0 - cosxi*cosxi)/cosxi;
a3103 6

  /* Do bounds checking on the native coordinates. */
  if (prj->bounds&4 && prjbchk(1.0e-13, nx, my, spt, phi, theta, stat)) {
    if (!status) status = PRJERR_BAD_PIX_SET("cypx2s");
  }

a3332 6

  /* Do bounds checking on the native coordinates. */
  if (prj->bounds&4 && prjbchk(1.0e-13, nx, my, spt, phi, theta, stat)) {
    if (!status) status = PRJERR_BAD_PIX_SET("ceax2s");
  }

a3515 6

  /* Do bounds checking on the native coordinates. */
  if (prj->bounds&4 && prjbchk(1.0e-13, nx, my, spt, phi, theta, stat)) {
    if (!status) status = PRJERR_BAD_PIX_SET("carx2s");
  }

a3698 6

  /* Do bounds checking on the native coordinates. */
  if (prj->bounds&4 && prjbchk(1.0e-13, nx, my, spt, phi, theta, stat)) {
    if (!status) status = PRJERR_BAD_PIX_SET("merx2s");
  }

a3906 6

  /* Do bounds checking on the native coordinates. */
  if (prj->bounds&4 && prjbchk(1.0e-13, nx, my, spt, phi, theta, stat)) {
    if (!status) status = PRJERR_BAD_PIX_SET("sflx2s");
  }

a4128 2
      } else {
        *(statp++) = istat;
a4135 6

  /* Do bounds checking on the native coordinates. */
  if (prj->bounds&4 && prjbchk(1.0e-12, nx, my, spt, phi, theta, stat)) {
    if (!status) status = PRJERR_BAD_PIX_SET("parx2s");
  }

a4379 2
      } else {
        *(statp++) = istat;
a4386 6

  /* Do bounds checking on the native coordinates. */
  if (prj->bounds&4 && prjbchk(1.0e-11, nx, my, spt, phi, theta, stat)) {
    if (!status) status = PRJERR_BAD_PIX_SET("molx2s");
  }

a4448 1

a4451 1

a4642 6

  /* Do bounds checking on the native coordinates. */
  if (prj->bounds&4 && prjbchk(1.0e-13, nx, my, spt, phi, theta, stat)) {
    if (!status) status = PRJERR_BAD_PIX_SET("aitx2s");
  }

a4868 6

  /* Do bounds checking on the native coordinates. */
  if (prj->bounds&4 && prjbchk(1.0e-13, nx, my, spt, phi, theta, stat)) {
    if (!status) status = PRJERR_BAD_PIX_SET("copx2s");
  }

a5144 6

  /* Do bounds checking on the native coordinates. */
  if (prj->bounds&4 && prjbchk(1.0e-13, nx, my, spt, phi, theta, stat)) {
    if (!status) status = PRJERR_BAD_PIX_SET("coex2s");
  }

a5368 6

  /* Do bounds checking on the native coordinates. */
  if (prj->bounds&4 && prjbchk(1.0e-13, nx, my, spt, phi, theta, stat)) {
    if (!status) status = PRJERR_BAD_PIX_SET("codx2s");
  }

a5620 6

  /* Do bounds checking on the native coordinates. */
  if (prj->bounds&4 && prjbchk(1.0e-13, nx, my, spt, phi, theta, stat)) {
    if (!status) status = PRJERR_BAD_PIX_SET("coox2s");
  }

a5860 6

  /* Do bounds checking on the native coordinates. */
  if (prj->bounds&4 && prjbchk(1.0e-11, nx, my, spt, phi, theta, stat)) {
    if (!status) status = PRJERR_BAD_PIX_SET("bonx2s");
  }

a6129 6

  /* Do bounds checking on the native coordinates. */
  if (prj->bounds&4 && prjbchk(1.0e-12, nx, my, spt, phi, theta, stat)) {
    if (!status) status = PRJERR_BAD_PIX_SET("pcox2s");
  }

a6391 6

  /* Do bounds checking on the native coordinates. */
  if (prj->bounds&4 && prjbchk(1.0e-13, nx, my, spt, phi, theta, stat)) {
    if (!status) status = PRJERR_BAD_PIX_SET("tscx2s");
  }

a6808 6

  /* Do bounds checking on the native coordinates. */
  if (prj->bounds&4 && prjbchk(1.0e-13, nx, my, spt, phi, theta, stat)) {
    if (!status) status = PRJERR_BAD_PIX_SET("cscx2s");
  }

a7294 6

  /* Do bounds checking on the native coordinates. */
  if (prj->bounds&4 && prjbchk(1.0e-13, nx, my, spt, phi, theta, stat)) {
    if (!status) status = PRJERR_BAD_PIX_SET("qscx2s");
  }

d7623 1
a7623 1
  double absy, r, s, sigma, slim, t, ylim, yr;
d7726 4
a7729 1
        r = s * *thetap;
d7733 1
a7733 1
          if (slim <= fabs(r)) {
a7738 4
        if (r != 0.0) r -= *thetap;
        *phip  += r;
        *thetap = t;

a7752 6

  /* Do bounds checking on the native coordinates. */
  if (prj->bounds&4 && prjbchk(1.0e-12, nx, my, spt, phi, theta, stat)) {
    if (!status) status = PRJERR_BAD_PIX_SET("hpxx2s");
  }

d7976 1
a7976 1
    phip = phi + rowoff;
d8047 1
a8047 1
              *phip = -90.0;
a8081 6
  }


  /* Do bounds checking on the native coordinates. */
  if (prj->bounds&4 && prjbchk(1.0e-12, nx, my, spt, phi, theta, stat)) {
    if (!status) status = PRJERR_BAD_PIX_SET("xphx2s");
@


4.20.1.4
log
@Fixed handling of status return for bounds checking in tanx2s(), arcx2s(),
cypx2s(), carx2s(), merx2s(), copx2s(), codx2s(), bonx2s(), and pcox2s().
@
text
@d25 1
a25 1
  $Id: prj.c,v 4.20.1.3 2014/03/22 05:37:04 mcalabre Exp mcalabre $
a1239 2
  status = 0;

d1286 1
a1286 1
  return status;
a2017 2
  status = 0;

d2065 1
a2065 1
  return status;
a3185 2
  status = 0;

d3222 1
a3222 1
  return status;
a3610 2
  status = 0;

d3646 1
a3646 1
  return status;
a3799 2
  status = 0;

d3835 1
a3835 1
  return status;
a4991 2
  status = 0;

d5041 1
a5041 1
  return status;
a5503 2
  status = 0;

d5553 1
a5553 1
  return status;
a5999 2
  status = 0;

d6057 1
a6057 1
  return status;
a6226 2
  status = 0;

d6332 1
a6332 1
  return status;
@


4.19
log
@WCSLIB 4.19
@
text
@d3 1
a3 1
  WCSLIB 4.19 - an implementation of the FITS WCS standard.
d25 1
a25 1
  $Id: prj.c,v 4.18.1.2 2013/09/29 08:52:42 mcalabre Exp mcalabre $
d157 1
a157 1
  prj->bounds = 1;
d720 1
a720 1
        if (prj->bounds) {
d1050 1
a1050 1
        if (prj->bounds) {
d1281 1
d1283 5
a1287 3
      if (prj->bounds && s < 0.0) {
        istat = 1;
        if (!status) status = PRJERR_BAD_WORLD_SET("tans2x");
d1807 5
a1811 3
      if (prj->bounds && *thetap < 0.0) {
        istat = 1;
        if (!status) status = PRJERR_BAD_WORLD_SET("sins2x");
d1828 1
a1828 1
        if (prj->bounds) {
d2417 1
d2419 5
a2423 3
    if (prj->bounds && s > prj->w[0]) {
      istat = 1;
      if (!status) status = PRJERR_BAD_WORLD_SET("zpns2x");
d4945 6
a4950 3
      if (prj->bounds && r*prj->w[0] < 0.0) {
        istat = 1;
        if (!status) status = PRJERR_BAD_WORLD_SET("cops2x");
d6321 1
a6321 1
      /* Check bounds. */
d6694 1
a6694 1
      /* Check bounds. */
d7120 1
a7120 1
      /* Check bounds. */
d7727 10
a7736 11
        if (fabs(s) < slim) {
          if (s != 0.0) s -= *thetap;
          *phip += s;
          *thetap = t;
          *(statp++) = istat;
        } else {
          /* Out-of-bounds. */
          *phip   = 0.0;
          *thetap = 0.0;
          *(statp++) = 1;
          if (!status) status = PRJERR_BAD_PIX_SET("hpxx2s");
d7738 2
d7944 3
a7946 2
  double abseta, eta, sigma, xi, xr, yr;
  register int ix, iy, *statp;
d7996 2
a7997 2
        xi  = -xr - yr;
        eta =  xr - yr;
d8000 2
a8001 2
        xi  =  xr - yr;
        eta =  xr + yr;
d8004 2
a8005 2
        xi  =  xr + yr;
        eta = -xr + yr;
d8008 2
a8009 2
        xi  = -xr + yr;
        eta = -xr - yr;
d8013 2
a8014 2
      xi  += 45.0;
      eta += 90.0;
d8022 11
a8032 1
          *(statp++) = 0;
d8052 1
a8052 1
            *phip += 45.0 + (xi - 45.0)/sigma;
d8061 11
a8071 1
          *(statp++) = 0;
@


4.19.1.1
log
@WCSLIB 4.19 development branch.
@
text
@d25 1
a25 1
  $Id: prj.c,v 4.19 2013/09/29 14:17:51 mcalabre Exp $
@


4.19.1.2
log
@Extended the interpretation of prjprm::bounds to allow bounds checking to
be disabled in hpxp2s() and xphp2s() (enabled by default by prjini()).
@
text
@d25 1
a25 1
  $Id: prj.c,v 4.19.1.1 2013/09/29 14:20:38 mcalabre Exp mcalabre $
d157 1
a157 1
  prj->bounds = 3;
d720 1
a720 1
        if (prj->bounds&1) {
d1050 1
a1050 1
        if (prj->bounds&1) {
a1280 1
      /* Bounds checking. */
d1282 3
a1284 5
      if (prj->bounds&1) {
        if (s < 0.0) {
          istat = 1;
          if (!status) status = PRJERR_BAD_WORLD_SET("tans2x");
        }
d1804 3
a1806 5
      if (prj->bounds&1) {
        if (*thetap < 0.0) {
          istat = 1;
          if (!status) status = PRJERR_BAD_WORLD_SET("sins2x");
        }
d1823 1
a1823 1
        if (prj->bounds&1) {
a2411 1
    /* Bounds checking. */
d2413 3
a2415 5
    if (prj->bounds&1) {
      if (s > prj->w[0]) {
        istat = 1;
        if (!status) status = PRJERR_BAD_WORLD_SET("zpns2x");
      }
d4937 3
a4939 6
      /* Bounds checking. */
      if (prj->bounds&1) {
        if (r*prj->w[0] < 0.0) {
          istat = 1;
          if (!status) status = PRJERR_BAD_WORLD_SET("cops2x");
        }
d6310 1
a6310 1
      /* Bounds checking. */
d6683 1
a6683 1
      /* Bounds checking. */
d7109 1
a7109 1
      /* Bounds checking. */
d7716 11
a7726 10
        if (s != 0.0) s -= *thetap;
        *phip += s;
        *thetap = t;

        /* Bounds checking. */
        if (prj->bounds&2) {
          if (slim <= fabs(s)) {
            istat = 1;
            if (!status) status = PRJERR_BAD_PIX_SET("hpxx2s");
          }
a7727 2

        *(statp++) = istat;
d7932 2
a7933 3
  double abseta, eta, eta1, sigma, xi, xi1, xr, yr;
  const double tol = 1.0e-12;
  register int istat, ix, iy, *statp;
d7983 2
a7984 2
        xi1  = -xr - yr;
        eta1 =  xr - yr;
d7987 2
a7988 2
        xi1  =  xr - yr;
        eta1 =  xr + yr;
d7991 2
a7992 2
        xi1  =  xr + yr;
        eta1 = -xr + yr;
d7995 2
a7996 2
        xi1  = -xr + yr;
        eta1 = -xr - yr;
d8000 2
a8001 2
      xi  = xi1  + 45.0;
      eta = eta1 + 90.0;
d8009 1
a8009 11
          istat = 0;

          /* Bounds checking. */
          if (prj->bounds&2) {
            if (45.0+tol < fabs(xi1)) {
              istat = 1;
              if (!status) status = PRJERR_BAD_PIX_SET("xphx2s");
            }
          }

          *(statp++) = istat;
d8029 1
a8029 1
            *phip += 45.0 + xi1/sigma;
d8038 1
a8038 11

          /* Bounds checking. */
          istat = 0;
          if (prj->bounds&2) {
            if (eta < -45.0 && eta+90.0+tol < fabs(xi1)) {
              istat = 1;
              if (!status) status = PRJERR_BAD_PIX_SET("xphx2s");
            }
          }

          *(statp++) = istat;
@


4.18
log
@WCSLIB 4.18
@
text
@d3 1
a3 1
  WCSLIB 4.18 - an implementation of the FITS WCS standard.
d25 1
a25 1
  $Id: prj.c,v 4.17.1.2 2013/07/12 04:05:47 mcalabre Exp mcalabre $
d7612 1
a7612 3
  double absy, s, sigma, t, yr;
  const double slim = prj->w[6] + 1e-12;
  const double ylim = prj->w[9] * prj->w[4];
d7623 3
@


4.18.1.1
log
@WCSLIB 4.18 development branch.
@
text
@d25 1
a25 1
  $Id: prj.c,v 4.18 2013/07/13 10:00:04 mcalabre Exp $
@


4.18.1.2
log
@In hpxx2s(), don't attempt to dereference prj (in const variable
initialization) until it tests non-zero (reported by cppcheck).
@
text
@d25 1
a25 1
  $Id: prj.c,v 4.18.1.1 2013/07/13 10:02:37 mcalabre Exp mcalabre $
d7612 3
a7614 1
  double absy, s, sigma, slim, t, ylim, yr;
a7624 3

  slim = prj->w[6] + 1e-12;
  ylim = prj->w[9] * prj->w[4];
@


4.17
log
@WCSLIB 4.17
@
text
@d3 1
a3 1
  WCSLIB 4.17 - an implementation of the FITS WCS standard.
d25 1
a25 1
  $Id: prj.c,v 4.16.1.2 2013/01/29 05:09:44 cal103 Exp cal103 $
d57 2
a58 2
const int  prj_ncode = 27;
const char prj_codes[27][4] =
d61 1
a61 1
   "AIT", "BON", "PCO", "TSC", "CSC", "QSC", "HPX"};
d90 1
d361 2
d7847 321
@


4.17.1.1
log
@WCSLIB 4.17 development branch.
@
text
@d25 1
a25 1
  $Id: prj.c,v 4.17 2013/01/29 05:29:20 cal103 Exp $
@


4.17.1.2
log
@Added the XPH projection.
@
text
@d25 1
a25 1
  $Id: prj.c,v 4.17.1.1 2013/01/29 05:32:32 cal103 Exp cal103 $
d57 2
a58 2
const int  prj_ncode = 28;
const char prj_codes[28][4] =
d61 1
a61 1
   "AIT", "BON", "PCO", "TSC", "CSC", "QSC", "HPX", "XPH"};
a89 1
const int XPH = 802;
a359 2
  } else if (strcmp(prj->code, "XPH") == 0) {
    status = xphset(prj);
a7843 321
    }
  }

  return 0;
}

/*============================================================================
*   XPH: HEALPix polar, aka "butterfly" projection.
*
*   Given and/or returned:
*      prj->r0      Reset to 180/pi if 0.
*      prj->phi0    Reset to 0.0 if undefined.
*      prj->theta0  Reset to 0.0 if undefined.
*
*   Returned:
*      prj->flag     XPH
*      prj->code    "XPH"
*      prj->x0      Fiducial offset in x.
*      prj->y0      Fiducial offset in y.
*      prj->w[0]    r0*(pi/180)/sqrt(2)
*      prj->w[1]    (180/pi)/r0/sqrt(2)
*      prj->w[2]    2/3
*      prj->w[3]    tol (= 1e-4)
*      prj->w[4]    sqrt(2/3)*(180/pi)
*      prj->w[5]    90 - tol*sqrt(2/3)*(180/pi)
*      prj->w[6]    sqrt(3/2)*(pi/180)
*      prj->prjx2s  Pointer to xphx2s().
*      prj->prjs2x  Pointer to xphs2x().
*===========================================================================*/

int xphset(prj)

struct prjprm *prj;

{
  if (prj == 0x0) return PRJERR_NULL_POINTER;

  prj->flag = XPH;
  strcpy(prj->code, "XPH");

  strcpy(prj->name, "butterfly");
  prj->category  = HEALPIX;
  prj->pvrange   = 0;
  prj->simplezen = 0;
  prj->equiareal = 1;
  prj->conformal = 0;
  prj->global    = 1;
  prj->divergent = 0;

  if (prj->r0 == 0.0) {
    prj->r0 = R2D;
    prj->w[0] = 1.0;
    prj->w[1] = 1.0;
  } else {
    prj->w[0] = prj->r0*D2R;
    prj->w[1] = R2D/prj->r0;
  }

  prj->w[0] /= sqrt(2.0);
  prj->w[1] /= sqrt(2.0);
  prj->w[2]  = 2.0/3.0;
  prj->w[3]  = 1e-4;
  prj->w[4]  = sqrt(prj->w[2])*R2D;
  prj->w[5]  = 90.0 - prj->w[3]*prj->w[4];
  prj->w[6]  = sqrt(1.5)*D2R;

  prj->prjx2s = xphx2s;
  prj->prjs2x = xphs2x;

  return prjoff(prj, 0.0, 90.0);
}

/*--------------------------------------------------------------------------*/

int xphx2s(prj, nx, ny, sxy, spt, x, y, phi, theta, stat)

struct prjprm *prj;
int nx, ny, sxy, spt;
const double x[], y[];
double phi[], theta[];
int stat[];

{
  int mx, my, rowlen, rowoff, status;
  double abseta, eta, sigma, xi, xr, yr;
  register int ix, iy, *statp;
  register const double *xp, *yp;
  register double *phip, *thetap;


  /* Initialize. */
  if (prj == 0x0) return PRJERR_NULL_POINTER;
  if (prj->flag != XPH) {
    if ((status = xphset(prj))) return status;
  }

  if (ny > 0) {
    mx = nx;
    my = ny;
  } else {
    mx = 1;
    my = 1;
    ny = nx;
  }

  status = 0;


  /* Do x dependence. */
  xp = x;
  rowoff = 0;
  rowlen = nx*spt;
  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    xr = (*xp + prj->x0)*prj->w[1];

    phip   = phi + rowoff;
    for (iy = 0; iy < my; iy++) {
      *phip = xr;
      phip  += rowlen;
    }
  }


  /* Do y dependence. */
  yp = y;
  phip   = phi;
  thetap = theta;
  statp  = stat;
  for (iy = 0; iy < ny; iy++, yp += sxy) {
    yr = (*yp + prj->y0)*prj->w[1];

    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
      xr = *phip;

      if (xr <= 0.0 && 0.0 < yr) {
        xi  = -xr - yr;
        eta =  xr - yr;
        *phip = -180.0;
      } else if (xr < 0.0 && yr <= 0.0) {
        xi  =  xr - yr;
        eta =  xr + yr;
        *phip = -90.0;
      } else if (0.0 <= xr && yr < 0.0) {
        xi  =  xr + yr;
        eta = -xr + yr;
        *phip = 0.0;
      } else {
        xi  = -xr + yr;
        eta = -xr - yr;
        *phip = 90.0;
      }

      xi  += 45.0;
      eta += 90.0;
      abseta = fabs(eta);

      if (abseta <= 90.0) {
        if (abseta <= 45.0) {
          /* Equatorial regime. */
          *phip  += xi;
          *thetap = asind(eta/67.5);
          *(statp++) = 0;

        } else {
          /* Polar regime. */
          sigma = (90.0 - abseta) / 45.0;

          /* Ensure an exact result for points on the boundary. */
          if (xr == 0.0) {
            if (yr <= 0.0) {
              *phip = 0.0;
            } else {
              *phip = 180.0;
            }
          } else if (yr == 0.0) {
            if (xr < 0.0) {
              *phip = 270.0;
            } else {
              *phip =  90.0;
            }
          } else {
            *phip += 45.0 + (xi - 45.0)/sigma;
          }

          if (sigma < prj->w[3]) {
            *thetap = 90.0 - sigma*prj->w[4];
          } else {
            *thetap = asind(1.0 - sigma*sigma/3.0);
          }
          if (eta < 0.0) *thetap = -(*thetap);
          *(statp++) = 0;
        }

      } else {
        /* Beyond latitude range. */
        *phip   = 0.0;
        *thetap = 0.0;
        *(statp++) = 1;
        if (!status) status = PRJERR_BAD_PIX_SET("xphx2s");
      }
    }
  }

  return status;
}

/*--------------------------------------------------------------------------*/

int xphs2x(prj, nphi, ntheta, spt, sxy, phi, theta, x, y, stat)

struct prjprm *prj;
int nphi, ntheta, spt, sxy;
const double phi[], theta[];
double x[], y[];
int stat[];

{
  int mphi, mtheta, rowlen, rowoff, status;
  double abssin, chi, eta, psi, sigma, sinthe, xi;
  register int iphi, itheta, *statp;
  register const double *phip, *thetap;
  register double *xp, *yp;


  /* Initialize. */
  if (prj == 0x0) return PRJERR_NULL_POINTER;
  if (prj->flag != XPH) {
    if ((status = xphset(prj))) return status;
  }

  if (ntheta > 0) {
    mphi   = nphi;
    mtheta = ntheta;
  } else {
    mphi   = 1;
    mtheta = 1;
    ntheta = nphi;
  }


  /* Do phi dependence. */
  phip = phi;
  rowoff = 0;
  rowlen = nphi*sxy;
  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    chi = *phip;
    if (180.0 <= fabs(chi)) {
      chi = fmod(chi, 360.0);
      if (chi < -180.0) {
        chi += 360.0;
      } else if (180.0 <= chi) {
        chi -= 360.0;
      }
    }

    /* phi is also recomputed from chi to avoid rounding problems. */
    chi += 180.0;
    psi = fmod(chi, 90.0);

    xp = x + rowoff;
    yp = y + rowoff;
    for (itheta = 0; itheta < mtheta; itheta++) {
      /* y[] is used to hold phi (rounded). */
      *xp = psi;
      *yp = chi - 180.0;
      xp += rowlen;
      yp += rowlen;
    }
  }


  /* Do theta dependence. */
  thetap = theta;
  xp = x;
  yp = y;
  statp = stat;
  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    sinthe = sind(*thetap);
    abssin = fabs(sinthe);

    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
      if (abssin <= prj->w[2]) {
        /* Equatorial regime. */
        xi  = *xp;
        eta = 67.5 * sinthe;

      } else {
        /* Polar regime. */
        if (*thetap < prj->w[5]) {
          sigma = sqrt(3.0*(1.0 - abssin));
        } else {
          sigma = (90.0 - *thetap)*prj->w[6];
        }

        xi  = 45.0 + (*xp - 45.0)*sigma;
        eta = 45.0 * (2.0 - sigma);
        if (*thetap < 0.0) eta = -eta;
      }

      xi  -= 45.0;
      eta -= 90.0;

      /* Recall that y[] holds phi. */
      if (*yp < -90.0) {
        *xp = prj->w[0]*(-xi + eta) - prj->x0;
        *yp = prj->w[0]*(-xi - eta) - prj->y0;

      } else if (*yp <  0.0) {
        *xp = prj->w[0]*(+xi + eta) - prj->x0;
        *yp = prj->w[0]*(-xi + eta) - prj->y0;

      } else if (*yp < 90.0) {
        *xp = prj->w[0]*( xi - eta) - prj->x0;
        *yp = prj->w[0]*( xi + eta) - prj->y0;

      } else {
        *xp = prj->w[0]*(-xi - eta) - prj->x0;
        *yp = prj->w[0]*( xi - eta) - prj->y0;
      }

      *(statp++) = 0;
@


4.16
log
@WCSLIB 4.16
@
text
@d3 2
a4 2
  WCSLIB 4.16 - an implementation of the FITS WCS standard.
  Copyright (C) 1995-2012, Mark Calabretta
d25 1
a25 1
  $Id: prj.c,v 4.15.1.1 2012/09/26 14:27:51 cal103 Exp cal103 $
@


4.16.1.1
log
@WCSLIB 4.16 development branch.
@
text
@d25 1
a25 1
  $Id: prj.c,v 4.16 2012/11/07 04:42:44 cal103 Exp $
@


4.16.1.2
log
@Updated date in copyright notice.
@
text
@d4 1
a4 1
  Copyright (C) 1995-2013, Mark Calabretta
d25 1
a25 1
  $Id: prj.c,v 4.16.1.1 2012/11/07 04:45:56 cal103 Exp cal103 $
@


4.15
log
@WCSLIB 4.15
@
text
@d3 1
a3 1
  WCSLIB 4.15 - an implementation of the FITS WCS standard.
d25 1
a25 1
  $Id: prj.c,v 4.14.1.1 2012/07/13 10:04:44 cal103 Exp cal103 $
@


4.15.1.1
log
@WCSLIB 4.15 development branch.
@
text
@d25 1
a25 1
  $Id: prj.c,v 4.15 2012/09/26 14:26:05 cal103 Exp $
@


4.14
log
@WCSLIB 4.14
@
text
@d3 1
a3 1
  WCSLIB 4.14 - an implementation of the FITS WCS standard.
d25 1
a25 1
  $Id: prj.c,v 4.13.1.3 2012/07/13 03:34:20 cal103 Exp cal103 $
@


4.14.1.1
log
@WCSLIB 4.14 development branch.
@
text
@d25 1
a25 1
  $Id: prj.c,v 4.14 2012/07/13 10:02:27 cal103 Exp $
@


4.13
log
@WCSLIB 4.13
@
text
@d3 1
a3 1
  WCSLIB 4.13 - an implementation of the FITS WCS standard.
d19 1
a19 1
  along with WCSLIB.  If not, see <http://www.gnu.org/licenses/>.
d21 5
a25 11
  Correspondence concerning WCSLIB may be directed to:
    Internet email: mcalabre@@atnf.csiro.au
    Postal address: Dr. Mark Calabretta
                    Australia Telescope National Facility, CSIRO
                    PO Box 76
                    Epping NSW 1710
                    AUSTRALIA

  Author: Mark Calabretta, Australia Telescope National Facility
  http://www.atnf.csiro.au/~mcalabre/index.html
  $Id: prj.c,v 4.12.1.2 2012/03/14 06:38:34 cal103 Exp cal103 $
d282 1
a282 1
    wcsutil_fptr2str((int (*)())prj->prjx2s, hext));
d284 1
a284 1
    wcsutil_fptr2str((int (*)())prj->prjs2x, hext));
d720 1
a720 1
            istat  = 1;
d737 1
a737 1
                istat  = 1;
d1050 1
a1050 1
            istat  = 1;
d1068 1
a1068 1
                istat  = 1;
d1280 1
a1280 1
        istat  = 1;
d1802 1
a1802 1
        istat  = 1;
d1823 1
a1823 1
            istat  = 1;
d2411 1
a2411 1
      istat  = 1;
d2929 1
a2929 1
      istat  = 1;
d3156 1
a3156 1
      istat  = 1;
d3307 1
a3307 1
        istat  = 1;
d3751 1
a3751 1
      istat  = 1;
d3881 1
a3881 1
      istat  = 1;
d3892 1
a3892 1
      *(statp++) = 0;
d4095 1
a4095 1
      istat  = 1;
d4321 1
a4321 1
        istat  = 1;
d4340 1
a4340 1
        istat  = 1;
d4352 1
a4352 1
        istat  = 1;
d4599 1
a4599 1
          istat  = 1;
d4618 1
a4618 1
          istat  = 1;
d4928 1
a4928 1
      istat  = 1;
d4935 1
a4935 1
        istat  = 1;
d5117 1
a5117 1
            istat  = 1;
d5594 1
a5594 1
          istat  = 1;
d5676 1
a5676 1
        istat  = 1;
d6514 1
a6514 1
          istat  = 1;
d6521 1
a6521 1
          istat  = 1;
d6601 1
a6601 1
  double l, m, n;
d6606 29
a6634 29
  float     chi, psi, xf, xx, yf, yy, z0, z1, z2, z3, z4, z5, z6;
  const float p00 = -0.27292696;
  const float p10 = -0.07629969;
  const float p20 = -0.22797056;
  const float p30 =  0.54852384;
  const float p40 = -0.62930065;
  const float p50 =  0.25795794;
  const float p60 =  0.02584375;
  const float p01 = -0.02819452;
  const float p11 = -0.01471565;
  const float p21 =  0.48051509;
  const float p31 = -1.74114454;
  const float p41 =  1.71547508;
  const float p51 = -0.53022337;
  const float p02 =  0.27058160;
  const float p12 = -0.56800938;
  const float p22 =  0.30803317;
  const float p32 =  0.98938102;
  const float p42 = -0.83180469;
  const float p03 = -0.60441560;
  const float p13 =  1.50880086;
  const float p23 = -0.93678576;
  const float p33 =  0.08693841;
  const float p04 =  0.93412077;
  const float p14 = -1.41601920;
  const float p24 =  0.33887446;
  const float p05 = -0.63915306;
  const float p15 =  0.52032238;
  const float p06 =  0.14381585;
d6659 1
a6659 1
    xf = (*xp + prj->x0)*prj->w[1];
d6675 1
a6675 1
    yf = (*yp + prj->y0)*prj->w[1];
d6678 1
a6678 1
      xf = *phip;
d6681 2
a6682 2
      if (fabs(xf) <= 1.0) {
        if (fabs(yf) > 3.0) {
d6690 1
a6690 1
        if (fabs(xf) > 7.0 || fabs(yf) > 1.0) {
d6700 1
a6700 1
      if (xf < -1.0) xf += 8.0;
d6703 1
a6703 1
      if (xf > 5.0) {
d6705 2
a6706 2
        xf = xf - 6.0;
      } else if (xf > 3.0) {
d6708 2
a6709 2
        xf = xf - 4.0;
      } else if (xf > 1.0) {
d6711 2
a6712 2
        xf = xf - 2.0;
      } else if (yf > 1.0) {
d6714 2
a6715 2
        yf = yf - 2.0;
      } else if (yf < -1.0) {
d6717 1
a6717 1
        yf = yf + 2.0;
d6735 1
a6735 1
      chi = xf + xf*(1.0 - xx)*chi;
d6747 1
a6747 1
      psi = yf + yf*(1.0 - yy)*psi;
d6749 1
d6752 1
a6752 1
        l =  1.0/sqrt(chi*chi + psi*psi + 1.0);
d6757 1
a6757 1
        m =  1.0/sqrt(chi*chi + psi*psi + 1.0);
d6762 1
a6762 1
        l = -1.0/sqrt(chi*chi + psi*psi + 1.0);
d6767 1
a6767 1
        m = -1.0/sqrt(chi*chi + psi*psi + 1.0);
d6772 1
a6772 1
        n = -1.0/sqrt(chi*chi + psi*psi + 1.0);
d6778 1
a6778 1
        n =  1.0/sqrt(chi*chi + psi*psi + 1.0);
d6818 12
a6829 12
  const float gstar  =  1.37484847732;
  const float mm     =  0.004869491981;
  const float gamma  = -0.13161671474;
  const float omega1 = -0.159596235474;
  const float d0  =  0.0759196200467;
  const float d1  = -0.0217762490699;
  const float c00 =  0.141189631152;
  const float c10 =  0.0809701286525;
  const float c01 = -0.281528535557;
  const float c11 =  0.15384112876;
  const float c20 = -0.178251207466;
  const float c02 =  0.106959469314;
d6944 2
a6945 2
      chi =  xi/zeta;
      psi = eta/zeta;
d6949 2
a6950 2
      chi2co = 1.0 - chi2;
      psi2co = 1.0 - psi2;
d6953 4
a6956 4
      chipsi = fabs(chi*psi);
      chi4   = (chi2 > 1.0e-16) ? chi2*chi2 : 0.0;
      psi4   = (psi2 > 1.0e-16) ? psi2*psi2 : 0.0;
      chi2psi2 = (chipsi > 1.0e-16) ? chi2*psi2 : 0.0;
d6961 1
a6961 1
       yf = psi*(psi2 + psi2co*(gstar + chi2*(gamma*psi2co + mm*psi2 +
d6966 3
a6968 3
      if (fabs(xf) > 1.0) {
        if (fabs(xf) > 1.0+tol) {
          istat  = 1;
d6971 1
a6971 1
        xf = copysign(1.0, xf);
d6973 3
a6975 3
      if (fabs(yf) > 1.0) {
        if (fabs(yf) > 1.0+tol) {
          istat  = 1;
d6978 1
a6978 1
        yf = copysign(1.0, yf);
d7489 1
a7489 1
          istat  = 1;
d7496 1
a7496 1
          istat  = 1;
d7690 1
a7690 1
          istat  = 1;
@


4.13.1.1
log
@WCSLIB 4.13 development branch.
@
text
@d31 1
a31 1
  $Id: prj.c,v 4.13 2012/03/14 07:39:30 cal103 Exp $
@


4.13.1.2
log
@Bug fix in sflx2s() to return an error status in the stat[] vector.
Changed prototype to wcsutil_fptr2str() to fix a compiler warning.
Make conversions between float and double explicit in cscx2s() and
cscs2x().  Patches provided by Michael Droettboom.
@
text
@d31 1
a31 1
  $Id: prj.c,v 4.13.1.1 2012/03/14 07:40:37 cal103 Exp cal103 $
d288 1
a288 1
    wcsutil_fptr2str((int (*)(void))prj->prjx2s, hext));
d290 1
a290 1
    wcsutil_fptr2str((int (*)(void))prj->prjs2x, hext));
d726 1
a726 1
            istat = 1;
d743 1
a743 1
                istat = 1;
d1056 1
a1056 1
            istat = 1;
d1074 1
a1074 1
                istat = 1;
d1286 1
a1286 1
        istat = 1;
d1808 1
a1808 1
        istat = 1;
d1829 1
a1829 1
            istat = 1;
d2417 1
a2417 1
      istat = 1;
d2935 1
a2935 1
      istat = 1;
d3162 1
a3162 1
      istat = 1;
d3313 1
a3313 1
        istat = 1;
d3757 1
a3757 1
      istat = 1;
d3887 1
a3887 1
      istat = 1;
d3898 1
a3898 1
      *(statp++) = istat;
d4101 1
a4101 1
      istat = 1;
d4327 1
a4327 1
        istat = 1;
d4346 1
a4346 1
        istat = 1;
d4358 1
a4358 1
        istat = 1;
d4605 1
a4605 1
          istat = 1;
d4624 1
a4624 1
          istat = 1;
d4934 1
a4934 1
      istat = 1;
d4941 1
a4941 1
        istat = 1;
d5123 1
a5123 1
            istat = 1;
d5600 1
a5600 1
          istat = 1;
d5682 1
a5682 1
        istat = 1;
d6520 1
a6520 1
          istat = 1;
d6527 1
a6527 1
          istat = 1;
d6607 1
a6607 1
  double l, m, n, t;
d6612 29
a6640 29
  float chi, psi, xf, xx, yf, yy, z0, z1, z2, z3, z4, z5, z6;
  const float p00 = -0.27292696f;
  const float p10 = -0.07629969f;
  const float p20 = -0.22797056f;
  const float p30 =  0.54852384f;
  const float p40 = -0.62930065f;
  const float p50 =  0.25795794f;
  const float p60 =  0.02584375f;
  const float p01 = -0.02819452f;
  const float p11 = -0.01471565f;
  const float p21 =  0.48051509f;
  const float p31 = -1.74114454f;
  const float p41 =  1.71547508f;
  const float p51 = -0.53022337f;
  const float p02 =  0.27058160f;
  const float p12 = -0.56800938f;
  const float p22 =  0.30803317f;
  const float p32 =  0.98938102f;
  const float p42 = -0.83180469f;
  const float p03 = -0.60441560f;
  const float p13 =  1.50880086f;
  const float p23 = -0.93678576f;
  const float p33 =  0.08693841f;
  const float p04 =  0.93412077f;
  const float p14 = -1.41601920f;
  const float p24 =  0.33887446f;
  const float p05 = -0.63915306f;
  const float p15 =  0.52032238f;
  const float p06 =  0.14381585f;
d6665 1
a6665 1
    xf = (float)((*xp + prj->x0)*prj->w[1]);
d6681 1
a6681 1
    yf = (float)((*yp + prj->y0)*prj->w[1]);
d6684 1
a6684 1
      xf = (float)(*phip);
d6687 2
a6688 2
      if (fabs((double)xf) <= 1.0) {
        if (fabs((double)yf) > 3.0) {
d6696 1
a6696 1
        if (fabs((double)xf) > 7.0 || fabs((double)yf) > 1.0) {
d6706 1
a6706 1
      if (xf < -1.0f) xf += 8.0f;
d6709 1
a6709 1
      if (xf > 5.0f) {
d6711 2
a6712 2
        xf = xf - 6.0f;
      } else if (xf > 3.0f) {
d6714 2
a6715 2
        xf = xf - 4.0f;
      } else if (xf > 1.0f) {
d6717 2
a6718 2
        xf = xf - 2.0f;
      } else if (yf > 1.0f) {
d6720 2
a6721 2
        yf = yf - 2.0f;
      } else if (yf < -1.0f) {
d6723 1
a6723 1
        yf = yf + 2.0f;
d6741 1
a6741 1
      chi = xf + xf*(1.0f - xx)*chi;
d6753 1
a6753 1
      psi = yf + yf*(1.0f - yy)*psi;
a6754 1
      t = 1.0/sqrt((double)(chi*chi + psi*psi) + 1.0);
d6757 1
a6757 1
        l =  t;
d6762 1
a6762 1
        m =  t;
d6767 1
a6767 1
        l = -t;
d6772 1
a6772 1
        m = -t;
d6777 1
a6777 1
        n = -t;
d6783 1
a6783 1
        n =  t;
d6823 12
a6834 12
  const float gstar  =  1.37484847732f;
  const float mm     =  0.004869491981f;
  const float gamma  = -0.13161671474f;
  const float omega1 = -0.159596235474f;
  const float d0  =  0.0759196200467f;
  const float d1  = -0.0217762490699f;
  const float c00 =  0.141189631152f;
  const float c10 =  0.0809701286525f;
  const float c01 = -0.281528535557f;
  const float c11 =  0.15384112876f;
  const float c20 = -0.178251207466f;
  const float c02 =  0.106959469314f;
d6949 2
a6950 2
      chi = (float)( xi/zeta);
      psi = (float)(eta/zeta);
d6954 2
a6955 2
      chi2co = 1.0f - chi2;
      psi2co = 1.0f - psi2;
d6958 4
a6961 4
      chipsi = (float)fabs((double)(chi*psi));
      chi4   = (chi2 > 1.0e-16f) ? chi2*chi2 : 0.0f;
      psi4   = (psi2 > 1.0e-16f) ? psi2*psi2 : 0.0f;
      chi2psi2 = (chipsi > 1.0e-16f) ? chi2*psi2 : 0.0f;
d6966 1
a6966 1
      yf = psi*(psi2 + psi2co*(gstar + chi2*(gamma*psi2co + mm*psi2 +
d6971 3
a6973 3
      if (fabs((double)xf) > 1.0) {
        if (fabs((double)xf) > 1.0+tol) {
          istat = 1;
d6976 1
a6976 1
        xf = (float)copysign(1.0, (double)xf);
d6978 3
a6980 3
      if (fabs((double)yf) > 1.0) {
        if (fabs((double)yf) > 1.0+tol) {
          istat = 1;
d6983 1
a6983 1
        yf = (float)copysign(1.0, (double)yf);
d7494 1
a7494 1
          istat = 1;
d7501 1
a7501 1
          istat = 1;
d7695 1
a7695 1
          istat = 1;
@


4.13.1.3
log
@Changed contact details.
@
text
@d19 1
a19 1
  along with WCSLIB.  If not, see http://www.gnu.org/licenses.
d21 11
a31 5
  Direct correspondence concerning WCSLIB to mark@@calabretta.id.au

  Author: Mark Calabretta, Australia Telescope National Facility, CSIRO.
  http://www.atnf.csiro.au/people/Mark.Calabretta
  $Id: prj.c,v 4.13.1.2 2012/07/12 15:31:21 cal103 Exp cal103 $
@


4.12
log
@WCSLIB 4.12
@
text
@d3 1
a3 1
  WCSLIB 4.12 - an implementation of the FITS WCS standard.
d31 1
a31 1
  $Id: prj.c,v 4.11.1.1 2012/02/20 23:31:13 cal103 Exp cal103 $
d175 4
d182 2
a183 2

  prj->err = 0x0;
d197 4
a200 2
  if (prj->err) free(prj->err);
  prj->err = 0x0;
@


4.12.1.1
log
@WCSLIB 4.12 development branch.
@
text
@d31 1
a31 1
  $Id: prj.c,v 4.12 2012/02/29 07:57:56 cal103 Exp $
@


4.12.1.2
log
@In prjini(), also initialize prjprm::padding, prjprm::prjx2s, and
prjprm::prjs2x so that they don't display rubbish in the debugger.
@
text
@d31 1
a31 1
  $Id: prj.c,v 4.12.1.1 2012/02/29 07:59:10 cal103 Exp cal103 $
a174 4

  prj->err = 0x0;

  prj->padding = 0x0;
d178 2
a179 2
  prj->prjx2s = 0x0;
  prj->prjs2x = 0x0;
d193 2
a194 4
  if (prj->err) {
    free(prj->err);
    prj->err = 0x0;
  }
@


4.11
log
@WCSLIB 4.11
@
text
@d3 1
a3 1
  WCSLIB 4.11 - an implementation of the FITS WCS standard.
d31 1
a31 1
  $Id: prj.c,v 4.10.1.1 2012/02/05 23:42:46 cal103 Exp cal103 $
@


4.11.1.1
log
@WCSLIB 4.11 development branch.
@
text
@d31 1
a31 1
  $Id: prj.c,v 4.11 2012/02/20 23:30:02 cal103 Exp $
@


4.10
log
@WCSLIB 4.10
@
text
@d3 1
a3 1
  WCSLIB 4.10 - an implementation of the FITS WCS standard.
d31 1
a31 1
  $Id: prj.c,v 4.9.1.1 2012/01/24 05:41:45 cal103 Exp cal103 $
@


4.10.1.1
log
@WCSLIB 4.10 development branch.
@
text
@d31 1
a31 1
  $Id: prj.c,v 4.10 2012/02/05 23:41:44 cal103 Exp $
@


4.9
log
@WCSLIB 4.9
@
text
@d3 1
a3 1
  WCSLIB 4.9 - an implementation of the FITS WCS standard.
d31 1
a31 1
  $Id: prj.c,v 4.8.1.3 2012/01/24 05:23:06 cal103 Exp cal103 $
@


4.9.1.1
log
@WCSLIB 4.9 development branch.
@
text
@d31 1
a31 1
  $Id: prj.c,v 4.9 2012/01/24 05:40:29 cal103 Exp $
@


4.8
log
@WCSLIB 4.8
@
text
@d3 2
a4 2
  WCSLIB 4.8 - an implementation of the FITS WCS standard.
  Copyright (C) 1995-2011, Mark Calabretta
d31 1
a31 1
  $Id: prj.c,v 4.7.1.5 2011/08/12 05:42:29 cal103 Exp cal103 $
d267 1
a267 1
    wcserr_prt(prj->err, "");
@


4.8.1.1
log
@WCSLIB 4.8 development branch.
@
text
@d31 1
a31 1
  $Id: prj.c,v 4.8 2011/08/15 08:05:53 cal103 Exp $
@


4.8.1.2
log
@Minor refinement in prjprt() for printing prjprm::err.
@
text
@d31 1
a31 1
  $Id: prj.c,v 4.8.1.1 2011/08/15 08:07:06 cal103 Exp cal103 $
d267 1
a267 1
    wcserr_prt(prj->err, "             ");
@


4.8.1.3
log
@Updated date in copyright notice.
@
text
@d4 1
a4 1
  Copyright (C) 1995-2012, Mark Calabretta
d31 1
a31 1
  $Id: prj.c,v 4.8.1.2 2011/11/17 03:08:29 cal103 Exp cal103 $
@


4.7
log
@WCSLIB 4.7
@
text
@d3 1
a3 1
  WCSLIB 4.7 - an implementation of the FITS WCS standard.
d31 1
a31 1
  $Id: prj.c,v 4.6.1.5 2011/01/25 00:35:11 cal103 Exp cal103 $
d36 1
d39 1
d43 1
d106 14
d149 1
a149 1
  if (prj == 0x0) return 1;
d179 17
d206 2
a207 1
  int i, n;
d209 1
a209 1
  if (prj == 0x0) return 1;
d264 6
d281 4
a284 2
  wcsprintf("     prjx2s: %p\n", (void *)prj->prjx2s);
  wcsprintf("     prjs2x: %p\n", (void *)prj->prjs2x);
d296 2
d299 1
d301 2
a302 1
  if (prj == 0x0) return 1;
d362 2
a363 1
    status = 2;
d380 2
d383 1
a383 1
  if (prj == 0x0) return 1;
d385 1
a385 1
    if (prjset(prj)) return 2;
d402 2
d405 1
a405 1
  if (prj == 0x0) return 1;
d407 1
a407 1
    if (prjset(prj)) return 2;
d427 1
a427 1
  if (prj == 0x0) return 1;
d440 1
a440 1
      return 2;
d484 1
a484 1
  if (prj == 0x0) return 1;
d504 1
a504 1
    return 2;
d509 1
a509 1
    return 2;
d551 1
a551 1
  if (prj == 0x0) return 1;
d553 1
a553 1
    if (azpset(prj)) return 2;
d617 1
a617 1
            status = 3;
d659 1
a659 1
  if (prj == 0x0) return 1;
d661 1
a661 1
    if (azpset(prj)) return 2;
d710 1
a710 1
        status = 4;
d721 1
a721 1
            status = 4;
d738 1
a738 1
                status = 4;
d793 1
a793 1
  if (prj == 0x0) return 1;
d816 1
a816 1
    return 2;
d858 1
a858 1
  if (prj == 0x0) return 1;
d860 1
a860 1
    if (szpset(prj)) return 2;
d923 1
a923 1
          status = 3;
d950 1
a950 1
          status = 3;
d986 1
a986 1
  if (prj == 0x0) return 1;
d988 1
a988 1
    if (szpset(prj)) return 2;
d1037 1
a1037 1
      status = 4;
d1051 1
a1051 1
            status = 4;
d1069 1
a1069 1
                status = 4;
d1108 1
a1108 1
  if (prj == 0x0) return 1;
d1141 1
a1141 1
  int mx, my, rowlen, rowoff;
d1149 1
a1149 1
  if (prj == 0x0) return 1;
d1151 1
a1151 1
    if (tanset(prj)) return 2;
d1225 1
a1225 1
  if (prj == 0x0) return 1;
d1227 1
a1227 1
    if (tanset(prj)) return 2;
d1273 1
a1273 1
      status = 4;
d1281 1
a1281 1
        status = 4;
d1319 1
a1319 1
  if (prj == 0x0) return 1;
d1359 1
a1359 1
  int mx, my, rowlen, rowoff;
d1367 1
a1367 1
  if (prj == 0x0) return 1;
d1369 1
a1369 1
    if (stgset(prj)) return 2;
d1443 1
a1443 1
  if (prj == 0x0) return 1;
d1445 1
a1445 1
    if (stgset(prj)) return 2;
d1491 1
a1491 1
      status = 4;
d1536 1
a1536 1
  if (prj == 0x0) return 1;
d1586 1
a1586 1
  if (prj == 0x0) return 1;
d1588 1
a1588 1
    if (sinset(prj)) return 2;
d1649 1
a1649 1
          status = 3;
d1658 3
a1660 3
           /* Use small angle formula. */
           z = r2/2.0;
           *thetap = 90.0 - R2D*sqrt(r2/(1.0 + xy));
d1663 40
a1702 40
           a = prj->w[2];
           b = xy - prj->w[1];
           c = r2 - xy - xy + prj->w[3];
           d = b*b - a*c;

           /* Check for a solution. */
           if (d < 0.0) {
             *phip = 0.0;
             *thetap = 0.0;
             *(statp++) = 1;
             status = 3;
             continue;
           }
           d = sqrt(d);

           /* Choose solution closest to pole. */
           sinth1 = (-b + d)/a;
           sinth2 = (-b - d)/a;
           sinthe = (sinth1 > sinth2) ? sinth1 : sinth2;
           if (sinthe > 1.0) {
             if (sinthe-1.0 < tol) {
               sinthe = 1.0;
             } else {
               sinthe = (sinth1 < sinth2) ? sinth1 : sinth2;
             }
           }

           if (sinthe < -1.0) {
             if (sinthe+1.0 > -tol) {
               sinthe = -1.0;
             }
           }

           if (sinthe > 1.0 || sinthe < -1.0) {
             *phip = 0.0;
             *thetap = 0.0;
             *(statp++) = 1;
             status = 3;
             continue;
           }
d1704 2
a1705 2
           *thetap = asind(sinthe);
           z = 1.0 - sinthe;
d1743 1
a1743 1
  if (prj == 0x0) return 1;
d1745 1
a1745 1
    if (sinset(prj)) return 2;
d1803 1
a1803 1
        status = 4;
d1824 1
a1824 1
            status = 4;
d1862 1
a1862 1
  if (prj == 0x0) return 1;
d1902 1
a1902 1
  int mx, my, rowlen, rowoff;
d1910 1
a1910 1
  if (prj == 0x0) return 1;
d1912 1
a1912 1
    if (arcset(prj)) return 2;
d1979 1
a1979 1
  int mphi, mtheta, rowlen, rowoff;
d1987 1
a1987 1
  if (prj == 0x0) return 1;
d1989 1
a1989 1
    if (arcset(prj)) return 2;
d2070 1
a2070 1
  if (prj == 0x0) return 1;
d2091 3
a2093 1
  if (k < 0) return 2;
d2106 1
a2106 1
      return 2;
d2182 1
a2182 1
  if (prj == 0x0) return 1;
d2184 1
a2184 1
    if (zpnset(prj)) return 2;
d2237 1
a2237 1
        return 2;
d2251 1
a2251 1
          status = 3;
d2265 1
a2265 1
            status = 3;
d2273 1
a2273 1
            status = 3;
d2289 1
a2289 1
            status = 3;
d2297 1
a2297 1
            status = 3;
d2360 1
a2360 1
  if (prj == 0x0) return 1;
d2362 1
a2362 1
    if (zpnset(prj)) return 2;
d2412 1
a2412 1
      status = 4;
d2449 1
a2449 1
  if (prj == 0x0) return 1;
d2498 1
a2498 1
  if (prj == 0x0) return 1;
d2500 1
a2500 1
    if (zeaset(prj)) return 2;
d2556 1
a2556 1
          status = 3;
d2581 1
a2581 1
  int mphi, mtheta, rowlen, rowoff;
d2589 1
a2589 1
  if (prj == 0x0) return 1;
d2591 1
a2591 1
    if (zeaset(prj)) return 2;
d2677 1
a2677 1
  if (prj == 0x0) return 1;
d2703 1
a2703 1
    return 2;
d2737 1
a2737 1
  if (prj == 0x0) return 1;
d2739 1
a2739 1
    if (airset(prj)) return 2;
d2809 1
a2809 1
          status = 3;
d2839 1
a2839 1
          status = 3;
d2873 1
a2873 1
  if (prj == 0x0) return 1;
d2875 1
a2875 1
    if (airset(prj)) return 2;
d2930 1
a2930 1
      status = 4;
d2975 1
a2975 1
  if (prj == 0x0) return 1;
d2997 1
a2997 1
      return 2;
d3004 1
a3004 1
      return 2;
d3011 1
a3011 1
      return 2;
d3018 1
a3018 1
      return 2;
d3041 1
a3041 1
  int mx, my, rowlen, rowoff;
d3049 1
a3049 1
  if (prj == 0x0) return 1;
d3051 1
a3051 1
    if (cypset(prj)) return 2;
d3115 1
a3115 1
  if (prj == 0x0) return 1;
d3117 1
a3117 1
    if (cypset(prj)) return 2;
d3157 1
a3157 1
      status = 4;
d3203 1
a3203 1
  if (prj == 0x0) return 1;
d3224 1
a3224 1
      return 2;
d3232 1
a3232 1
      return 2;
d3264 1
a3264 1
  if (prj == 0x0) return 1;
d3266 1
a3266 1
    if (ceaset(prj)) return 2;
d3308 1
a3308 1
        status = 3;
d3336 1
a3336 1
  int mphi, mtheta, rowlen, rowoff;
d3344 1
a3344 1
  if (prj == 0x0) return 1;
d3346 1
a3346 1
    if (ceaset(prj)) return 2;
d3414 1
a3414 1
  if (prj == 0x0) return 1;
d3454 1
a3454 1
  int mx, my, rowlen, rowoff;
d3462 1
a3462 1
  if (prj == 0x0) return 1;
d3464 1
a3464 1
    if (carset(prj)) return 2;
d3519 1
a3519 1
  int mphi, mtheta, rowlen, rowoff;
d3527 1
a3527 1
  if (prj == 0x0) return 1;
d3529 1
a3529 1
    if (carset(prj)) return 2;
d3597 1
a3597 1
  if (prj == 0x0) return 1;
d3637 1
a3637 1
  int mx, my, rowlen, rowoff;
d3645 1
a3645 1
  if (prj == 0x0) return 1;
d3647 1
a3647 1
    if (merset(prj)) return 2;
d3710 1
a3710 1
  if (prj == 0x0) return 1;
d3712 1
a3712 1
    if (merset(prj)) return 2;
d3752 1
a3752 1
      status = 4;
d3790 1
a3790 1
  if (prj == 0x0) return 1;
d3838 1
a3838 1
  if (prj == 0x0) return 1;
d3840 1
a3840 1
    if (sflset(prj)) return 2;
d3852 2
d3882 1
a3882 1
      status = 3;
d3896 1
a3896 1
  return 0;
d3910 1
a3910 1
  int mphi, mtheta, rowlen, rowoff;
d3918 1
a3918 1
  if (prj == 0x0) return 1;
d3920 1
a3920 1
    if (sflset(prj)) return 2;
d3993 1
a3993 1
  if (prj == 0x0) return 1;
d4046 1
a4046 1
  if (prj == 0x0) return 1;
d4048 1
a4048 1
    if (parset(prj)) return 2;
d4096 1
a4096 1
      status = 3;
d4116 1
a4116 1
          status = 3;
d4139 1
a4139 1
  int mphi, mtheta, rowlen, rowoff;
d4147 1
a4147 1
  if (prj == 0x0) return 1;
d4149 1
a4149 1
    if (parset(prj)) return 2;
d4223 1
a4223 1
  if (prj == 0x0) return 1;
d4271 1
a4271 1
  if (prj == 0x0) return 1;
d4273 1
a4273 1
    if (molset(prj)) return 2;
d4322 1
a4322 1
        status = 3;
d4341 1
a4341 1
        status = 3;
d4353 1
a4353 1
        status = 3;
d4367 1
a4367 1
          status = 3;
d4390 1
a4390 1
  int k, mphi, mtheta, rowlen, rowoff;
d4399 1
a4399 1
  if (prj == 0x0) return 1;
d4401 1
a4401 1
    if (molset(prj)) return 2;
d4500 1
a4500 1
  if (prj == 0x0) return 1;
d4547 1
a4547 1
  if (prj == 0x0) return 1;
d4549 1
a4549 1
    if (aitset(prj)) return 2;
d4600 1
a4600 1
          status = 3;
d4619 1
a4619 1
          status = 3;
d4646 1
a4646 1
  int mphi, mtheta, rowlen, rowoff;
d4654 1
a4654 1
  if (prj == 0x0) return 1;
d4656 1
a4656 1
    if (aitset(prj)) return 2;
d4740 1
a4740 1
  if (prj == 0x0) return 1;
d4744 1
d4747 1
a4747 1
    return 2;
a4751 1
  strcpy(prj->name, "conic perspective");
d4762 1
a4762 1
    return 2;
d4769 1
a4769 1
    return 2;
d4794 1
a4794 1
  int mx, my, rowlen, rowoff;
d4801 1
a4801 1
  if (prj == 0x0) return 1;
d4803 1
a4803 1
    if (copset(prj)) return 2;
d4879 1
a4879 1
  if (prj == 0x0) return 1;
d4881 1
a4881 1
    if (copset(prj)) return 2;
d4929 1
a4929 1
      status = 4;
d4936 1
a4936 1
        status = 4;
d4988 1
a4988 1
  if (prj == 0x0) return 1;
d4992 1
d4995 1
a4995 1
    return 2;
a4999 1
  strcpy(prj->name, "conic equal area");
d5013 1
a5013 1
    return 2;
d5052 1
a5052 1
  if (prj == 0x0) return 1;
d5054 1
a5054 1
    if (coeset(prj)) return 2;
d5118 1
a5118 1
            status = 3;
d5145 1
a5145 1
  int mphi, mtheta, rowlen, rowoff;
d5152 1
a5152 1
  if (prj == 0x0) return 1;
d5154 1
a5154 1
    if (coeset(prj)) return 2;
d5240 1
a5240 1
  if (prj == 0x0) return 1;
d5244 1
d5247 1
a5247 1
    return 2;
a5251 1
  strcpy(prj->name, "conic equidistant");
d5267 1
a5267 1
    return 2;
d5291 1
a5291 1
  int mx, my, rowlen, rowoff;
d5298 1
a5298 1
  if (prj == 0x0) return 1;
d5300 1
a5300 1
    if (codset(prj)) return 2;
d5369 1
a5369 1
  int mphi, mtheta, rowlen, rowoff;
d5376 1
a5376 1
  if (prj == 0x0) return 1;
d5378 1
a5378 1
    if (codset(prj)) return 2;
d5465 1
a5465 1
  if (prj == 0x0) return 1;
d5469 1
d5472 1
a5472 1
    return 2;
a5476 1
  strcpy(prj->name, "conic orthomorphic");
d5499 1
a5499 1
    return 2;
d5506 1
a5506 1
    return 2;
d5535 1
a5535 1
  if (prj == 0x0) return 1;
d5537 1
a5537 1
    if (cooset(prj)) return 2;
d5595 1
a5595 1
          status = 3;
d5628 1
a5628 1
  if (prj == 0x0) return 1;
d5630 1
a5630 1
    if (cooset(prj)) return 2;
d5677 1
a5677 1
        status = 4;
d5720 1
a5720 1
  if (prj == 0x0) return 1;
d5724 1
d5727 1
a5727 1
    return 2;
a5734 1
  strcpy(prj->name, "Bonne's");
d5769 1
a5769 1
  int mx, my, rowlen, rowoff;
d5777 1
a5777 1
  if (prj == 0x0) return 1;
d5784 1
a5784 1
    if (bonset(prj)) return 2;
d5861 1
a5861 1
  int mphi, mtheta, rowlen, rowoff;
d5868 1
a5868 1
  if (prj == 0x0) return 1;
d5875 1
a5875 1
    if (bonset(prj)) return 2;
d5951 1
a5951 1
  if (prj == 0x0) return 1;
d5993 1
a5993 1
  int mx, my, rowlen, rowoff;
d6003 1
a6003 1
  if (prj == 0x0) return 1;
d6005 1
a6005 1
    if (pcoset(prj)) return 2;
d6130 1
a6130 1
  int mphi, mtheta, rowlen, rowoff;
d6137 1
a6137 1
  if (prj == 0x0) return 1;
d6139 1
a6139 1
    if (pcoset(prj)) return 2;
d6216 1
a6216 1
  if (prj == 0x0) return 1;
d6264 1
a6264 1
  if (prj == 0x0) return 1;
d6266 1
a6266 1
    if (tscset(prj)) return 2;
d6313 1
a6313 1
          status = 3;
d6321 1
a6321 1
          status = 3;
d6400 1
a6400 1
  if (prj == 0x0) return 1;
d6402 1
a6402 1
    if (tscset(prj)) return 2;
d6515 1
a6515 1
          status = 4;
d6522 1
a6522 1
          status = 4;
d6560 1
a6560 1
  if (prj == 0x0) return 1;
d6637 1
a6637 1
  if (prj == 0x0) return 1;
d6639 1
a6639 1
    if (cscset(prj)) return 2;
d6686 1
a6686 1
          status = 3;
d6694 1
a6694 1
          status = 3;
d6832 1
a6832 1
  if (prj == 0x0) return 1;
d6834 1
a6834 1
    if (cscset(prj)) return 2;
d6968 1
a6968 1
          status = 4;
d6975 1
a6975 1
          status = 4;
d7013 1
a7013 1
  if (prj == 0x0) return 1;
d7062 1
a7062 1
  if (prj == 0x0) return 1;
d7064 1
a7064 1
    if (qscset(prj)) return 2;
d7111 1
a7111 1
          status = 3;
d7119 1
a7119 1
          status = 3;
d7182 1
a7182 1
          status = 3;
d7304 1
a7304 1
  if (prj == 0x0) return 1;
d7306 1
a7306 1
    if (qscset(prj)) return 2;
d7489 1
a7489 1
          status = 4;
d7496 1
a7496 1
          status = 4;
d7548 1
a7548 1
  if (prj == 0x0) return 1;
d7566 1
a7566 1
    return 2;
d7617 1
a7617 1
  if (prj == 0x0) return 1;
d7619 1
a7619 1
    if (hpxset(prj)) return 2;
d7640 1
a7640 1
    /* x_c for K odd or theta > 0. */ 
d7690 1
a7690 1
          status = 3;
d7721 1
a7721 1
          status = 3;
d7732 1
a7732 1
      status = 3;
d7750 1
a7750 1
  int h, mphi, mtheta, offset, rowlen, rowoff;
d7758 1
a7758 1
  if (prj == 0x0) return 1;
d7760 1
a7760 1
    if (hpxset(prj)) return 2;
d7780 1
a7780 1
    /* phi_c for K odd or theta > 0. */ 
@


4.7.1.1
log
@WCSLIB 4.7 development branch.
@
text
@d31 1
a31 1
  $Id: prj.c,v 4.7 2011/02/07 07:03:42 cal103 Exp $
@


4.7.1.2
log
@Added error messaging based on wcserr.  Changes supplied by Michael
Droettboom (STScI) with respect to the released WCSLIB 4.7 sources.
@
text
@a102 14
/* Some convenience macros for creating common projection errors */
#define PRJERR_BAD_PARAM_SET(prj)                             \
  WCSERR_SET(&(prj)->err, PRJERR_BAD_PARAM,                   \
             "Invalid parameters for %s projection", (prj)->name);

#define PRJERR_BAD_PIX_SET(prj)                               \
  WCSERR_SET(&(prj)->err, PRJERR_BAD_PIX,                     \
             "One or more of the (x, y) coordinates were invalid for %s projection", \
             (prj)->name);

#define PRJERR_BAD_WORLD_SET(prj)                             \
  WCSERR_SET(&(prj)->err, PRJERR_BAD_WORLD,                   \
             "One or more of the (lat, lng) coordinates were invalid for %s projection", \
             (prj)->name);
d132 1
a132 3
  if (prj == 0x0) return PRJERR_NULL_POINTER;

  wcserr_ini(&prj->err);
d174 1
a174 1
  if (prj == 0x0) return PRJERR_NULL_POINTER;
d255 1
a255 1
  if (prj == 0x0) return PRJERR_NULL_POINTER;
d315 1
a315 3
    status = WCSERR_SET(
      &prj->err, PRJERR_BAD_PARAM,
      "Unrecognized projection code '%s'", prj->code);
a331 2
  int status;
  
d333 1
a333 1
  if (prj == 0x0) return PRJERR_NULL_POINTER;
d335 1
a335 1
    if (status = prjset(prj)) return status;
a351 2
  int status;
  
d353 1
a353 1
  if (prj == 0x0) return PRJERR_NULL_POINTER;
d355 1
a355 1
    if (status = prjset(prj)) return status;
d375 1
a375 1
  if (prj == 0x0) return PRJERR_NULL_POINTER;
d388 1
a388 1
      return PRJERR_BAD_PARAM_SET(prj);
d432 1
a432 1
  if (prj == 0x0) return PRJERR_NULL_POINTER;
d452 1
a452 1
    return PRJERR_BAD_PARAM_SET(prj);
d457 1
a457 1
    return PRJERR_BAD_PARAM_SET(prj);
d496 1
a496 1
  
d499 1
a499 1
  if (prj == 0x0) return PRJERR_NULL_POINTER;
d501 1
a501 1
    if (status = azpset(prj)) return status;
d565 1
a565 1
            status = PRJERR_BAD_PIX;
a584 4
  if (status == PRJERR_BAD_PIX) {
    PRJERR_BAD_PIX_SET(prj);
  }
  
d607 1
a607 1
  if (prj == 0x0) return PRJERR_NULL_POINTER;
d609 1
a609 1
    if (status = azpset(prj)) return status;
d658 1
a658 1
        status = PRJERR_BAD_WORLD;
d669 1
a669 1
            status = PRJERR_BAD_WORLD;
d686 1
a686 1
                status = PRJERR_BAD_WORLD;
a698 4
  if (status == PRJERR_BAD_WORLD) {
    PRJERR_BAD_WORLD_SET(prj);
  }

d741 1
a741 1
  if (prj == 0x0) return PRJERR_NULL_POINTER;
d764 1
a764 1
    return PRJERR_BAD_PARAM_SET(prj);
d806 1
a806 1
  if (prj == 0x0) return PRJERR_NULL_POINTER;
d808 1
a808 1
    if (status = szpset(prj)) return status;
d871 1
a871 1
          status = PRJERR_BAD_PIX;
d898 1
a898 1
          status = PRJERR_BAD_PIX;
a911 4
  if (status == PRJERR_BAD_PIX) {
    PRJERR_BAD_PIX_SET(prj);
  }
  
d934 1
a934 1
  if (prj == 0x0) return PRJERR_NULL_POINTER;
d936 1
a936 1
    if (status = szpset(prj)) return status;
d985 1
a985 1
      status = PRJERR_BAD_WORLD;
d999 1
a999 1
            status = PRJERR_BAD_WORLD;
d1017 1
a1017 1
                status = PRJERR_BAD_WORLD;
a1029 4
  if (status == PRJERR_BAD_WORLD) {
    PRJERR_BAD_WORLD_SET(prj);
  }
  
d1056 1
a1056 1
  if (prj == 0x0) return PRJERR_NULL_POINTER;
d1089 1
a1089 1
  int mx, my, rowlen, rowoff, status;
d1097 1
a1097 1
  if (prj == 0x0) return PRJERR_NULL_POINTER;
d1099 1
a1099 1
    if (status = tanset(prj)) return status;
d1173 1
a1173 1
  if (prj == 0x0) return PRJERR_NULL_POINTER;
d1175 1
a1175 1
    if (status = tanset(prj)) return status;
d1221 1
a1221 1
      status = PRJERR_BAD_WORLD;
d1229 1
a1229 1
        status = PRJERR_BAD_WORLD;
a1239 3
  if (status == PRJERR_BAD_WORLD) {
    PRJERR_BAD_WORLD_SET(prj);
  }
d1267 1
a1267 1
  if (prj == 0x0) return PRJERR_NULL_POINTER;
d1307 1
a1307 1
  int mx, my, rowlen, rowoff, status;
d1315 1
a1315 1
  if (prj == 0x0) return PRJERR_NULL_POINTER;
d1317 1
a1317 1
    if (status = stgset(prj)) return status;
d1391 1
a1391 1
  if (prj == 0x0) return PRJERR_NULL_POINTER;
d1393 1
a1393 1
    if (status = stgset(prj)) return status;
d1439 1
a1439 1
      status = PRJERR_BAD_WORLD;
a1451 3
  if (status == PRJERR_BAD_WORLD) {
    PRJERR_BAD_WORLD_SET(prj);
  }
d1484 1
a1484 1
  if (prj == 0x0) return PRJERR_NULL_POINTER;
d1534 1
a1534 1
  if (prj == 0x0) return PRJERR_NULL_POINTER;
d1536 1
a1536 1
    if (status = sinset(prj)) return status;
d1597 1
a1597 1
          status = PRJERR_BAD_PIX;
d1621 1
a1621 1
             status = PRJERR_BAD_PIX;
d1648 1
a1648 1
             status = PRJERR_BAD_PIX;
a1668 3
  if (status == PRJERR_BAD_PIX) {
    PRJERR_BAD_PIX_SET(prj);
  }
d1691 1
a1691 1
  if (prj == 0x0) return PRJERR_NULL_POINTER;
d1693 1
a1693 1
    if (status = sinset(prj)) return status;
d1751 1
a1751 1
        status = PRJERR_BAD_WORLD;
d1772 1
a1772 1
            status = PRJERR_BAD_WORLD;
a1782 3
  if (status == PRJERR_BAD_WORLD) {
    PRJERR_BAD_WORLD_SET(prj);
  }
d1810 1
a1810 1
  if (prj == 0x0) return PRJERR_NULL_POINTER;
d1850 1
a1850 1
  int mx, my, rowlen, rowoff, status;
d1858 1
a1858 1
  if (prj == 0x0) return PRJERR_NULL_POINTER;
d1860 1
a1860 1
    if (status = arcset(prj)) return status;
d1927 1
a1927 1
  int mphi, mtheta, rowlen, rowoff, status;
d1935 1
a1935 1
  if (prj == 0x0) return PRJERR_NULL_POINTER;
d1937 1
a1937 1
    if (status = arcset(prj)) return status;
d2018 1
a2018 1
  if (prj == 0x0) return PRJERR_NULL_POINTER;
d2039 1
a2039 3
  if (k < 0) {
    return PRJERR_BAD_PARAM_SET(prj);
  }
d2052 1
a2052 1
      return PRJERR_BAD_PARAM_SET(prj);
d2128 1
a2128 1
  if (prj == 0x0) return PRJERR_NULL_POINTER;
d2130 1
a2130 1
    if (status = zpnset(prj)) return status;
d2183 1
a2183 1
        return PRJERR_BAD_PARAM_SET(prj);
d2197 1
a2197 1
          status = PRJERR_BAD_PIX;
d2211 1
a2211 1
            status = PRJERR_BAD_PIX;
d2219 1
a2219 1
            status = PRJERR_BAD_PIX;
d2235 1
a2235 1
            status = PRJERR_BAD_PIX;
d2243 1
a2243 1
            status = PRJERR_BAD_PIX;
a2283 3
  if (status == PRJERR_BAD_PIX) {
    PRJERR_BAD_PIX_SET(prj);
  }
d2306 1
a2306 1
  if (prj == 0x0) return PRJERR_NULL_POINTER;
d2308 1
a2308 1
    if (status = zpnset(prj)) return status;
d2358 1
a2358 1
      status = PRJERR_BAD_WORLD;
a2367 3
  if (status == PRJERR_BAD_WORLD) {
    PRJERR_BAD_WORLD_SET(prj);
  }
d2395 1
a2395 1
  if (prj == 0x0) return PRJERR_NULL_POINTER;
d2444 1
a2444 1
  if (prj == 0x0) return PRJERR_NULL_POINTER;
d2446 1
a2446 1
    if (status = zeaset(prj)) return status;
d2502 1
a2502 1
          status = PRJERR_BAD_PIX;
a2512 3
  if (status == PRJERR_BAD_PIX) {
    PRJERR_BAD_PIX_SET(prj);
  }
d2527 1
a2527 1
  int mphi, mtheta, rowlen, rowoff, status;
d2535 1
a2535 1
  if (prj == 0x0) return PRJERR_NULL_POINTER;
d2537 1
a2537 1
    if (status = zeaset(prj)) return status;
d2623 1
a2623 1
  if (prj == 0x0) return PRJERR_NULL_POINTER;
d2649 1
a2649 1
    return PRJERR_BAD_PARAM_SET(prj);
d2683 1
a2683 1
  if (prj == 0x0) return PRJERR_NULL_POINTER;
d2685 1
a2685 1
    if (status = airset(prj)) return status;
d2755 1
a2755 1
          status = PRJERR_BAD_PIX;
d2785 1
a2785 1
          status = PRJERR_BAD_PIX;
a2796 3
  if (status == PRJERR_BAD_PIX) {
    PRJERR_BAD_PIX_SET(prj);
  }
d2819 1
a2819 1
  if (prj == 0x0) return PRJERR_NULL_POINTER;
d2821 1
a2821 1
    if (status = airset(prj)) return status;
d2876 1
a2876 1
      status = PRJERR_BAD_WORLD;
a2885 3
  if (status == PRJERR_BAD_WORLD) {
    PRJERR_BAD_WORLD_SET(prj);
  }
d2921 1
a2921 1
  if (prj == 0x0) return PRJERR_NULL_POINTER;
d2943 1
a2943 1
      return PRJERR_BAD_PARAM_SET(prj);
d2950 1
a2950 1
      return PRJERR_BAD_PARAM_SET(prj);
d2957 1
a2957 1
      return PRJERR_BAD_PARAM_SET(prj);
d2964 1
a2964 1
      return PRJERR_BAD_PARAM_SET(prj);
d2987 1
a2987 1
  int mx, my, rowlen, rowoff, status;
d2995 1
a2995 1
  if (prj == 0x0) return PRJERR_NULL_POINTER;
d2997 1
a2997 1
    if (status = cypset(prj)) return status;
d3061 1
a3061 1
  if (prj == 0x0) return PRJERR_NULL_POINTER;
d3063 1
a3063 1
    if (status = cypset(prj)) return status;
d3103 1
a3103 1
      status = PRJERR_BAD_WORLD;
a3115 3
  if (status == PRJERR_BAD_WORLD) {
    PRJERR_BAD_WORLD_SET(prj);
  }
d3149 1
a3149 1
  if (prj == 0x0) return PRJERR_NULL_POINTER;
d3170 1
a3170 1
      return PRJERR_BAD_PARAM_SET(prj);
d3178 1
a3178 1
      return PRJERR_BAD_PARAM_SET(prj);
d3210 1
a3210 1
  if (prj == 0x0) return PRJERR_NULL_POINTER;
d3212 1
a3212 1
    if (status = ceaset(prj)) return status;
d3254 1
a3254 1
        status = PRJERR_BAD_PIX;
a3267 3
  if (status == PRJERR_BAD_PIX) {
    PRJERR_BAD_PIX_SET(prj);
  }
d3282 1
a3282 1
  int mphi, mtheta, rowlen, rowoff, status;
d3290 1
a3290 1
  if (prj == 0x0) return PRJERR_NULL_POINTER;
d3292 1
a3292 1
    if (status = ceaset(prj)) return status;
d3360 1
a3360 1
  if (prj == 0x0) return PRJERR_NULL_POINTER;
d3400 1
a3400 1
  int mx, my, rowlen, rowoff, status;
d3408 1
a3408 1
  if (prj == 0x0) return PRJERR_NULL_POINTER;
d3410 1
a3410 1
    if (status = carset(prj)) return status;
d3465 1
a3465 1
  int mphi, mtheta, rowlen, rowoff, status;
d3473 1
a3473 1
  if (prj == 0x0) return PRJERR_NULL_POINTER;
d3475 1
a3475 1
    if (status = carset(prj)) return status;
d3543 1
a3543 1
  if (prj == 0x0) return PRJERR_NULL_POINTER;
d3583 1
a3583 1
  int mx, my, rowlen, rowoff, status;
d3591 1
a3591 1
  if (prj == 0x0) return PRJERR_NULL_POINTER;
d3593 1
a3593 1
    if (status = merset(prj)) return status;
d3656 1
a3656 1
  if (prj == 0x0) return PRJERR_NULL_POINTER;
d3658 1
a3658 1
    if (status = merset(prj)) return status;
d3698 1
a3698 1
      status = PRJERR_BAD_WORLD;
a3708 3
  if (status == PRJERR_BAD_WORLD) {
    PRJERR_BAD_WORLD_SET(prj);
  }
d3736 1
a3736 1
  if (prj == 0x0) return PRJERR_NULL_POINTER;
d3784 1
a3784 1
  if (prj == 0x0) return PRJERR_NULL_POINTER;
d3786 1
a3786 1
    if (status = sflset(prj)) return status;
d3826 1
a3826 1
      status = PRJERR_BAD_PIX;
d3840 1
a3840 4
  if (status == PRJERR_BAD_PIX) {
    PRJERR_BAD_PIX_SET(prj);
  }
  return status;
d3854 1
a3854 1
  int mphi, mtheta, rowlen, rowoff, status;
d3862 1
a3862 1
  if (prj == 0x0) return PRJERR_NULL_POINTER;
d3864 1
a3864 1
    if (status = sflset(prj)) return status;
d3937 1
a3937 1
  if (prj == 0x0) return PRJERR_NULL_POINTER;
d3990 1
a3990 1
  if (prj == 0x0) return PRJERR_NULL_POINTER;
d3992 1
a3992 1
    if (status = parset(prj)) return status;
d4040 1
a4040 1
      status = PRJERR_BAD_PIX;
d4060 1
a4060 1
          status = PRJERR_BAD_PIX;
a4068 3
  if (status == PRJERR_BAD_PIX) {
    PRJERR_BAD_PIX_SET(prj);
  }
d4083 1
a4083 1
  int mphi, mtheta, rowlen, rowoff, status;
d4091 1
a4091 1
  if (prj == 0x0) return PRJERR_NULL_POINTER;
d4093 1
a4093 1
    if (status = parset(prj)) return status;
d4167 1
a4167 1
  if (prj == 0x0) return PRJERR_NULL_POINTER;
d4215 1
a4215 1
  if (prj == 0x0) return PRJERR_NULL_POINTER;
d4217 1
a4217 1
    if (status = molset(prj)) return status;
d4266 1
a4266 1
        status = PRJERR_BAD_PIX;
d4285 1
a4285 1
        status = PRJERR_BAD_PIX;
d4297 1
a4297 1
        status = PRJERR_BAD_PIX;
d4311 1
a4311 1
          status = PRJERR_BAD_PIX;
a4319 3
  if (status == PRJERR_BAD_PIX) {
    PRJERR_BAD_PIX_SET(prj);
  }
d4334 1
a4334 1
  int k, mphi, mtheta, rowlen, rowoff, status;
d4343 1
a4343 1
  if (prj == 0x0) return PRJERR_NULL_POINTER;
d4345 1
a4345 1
    if (status = molset(prj)) return status;
d4444 1
a4444 1
  if (prj == 0x0) return PRJERR_NULL_POINTER;
d4491 1
a4491 1
  if (prj == 0x0) return PRJERR_NULL_POINTER;
d4493 1
a4493 1
    if (status = aitset(prj)) return status;
d4544 1
a4544 1
          status = PRJERR_BAD_PIX;
d4563 1
a4563 1
          status = PRJERR_BAD_PIX;
a4575 3
  if (status == PRJERR_BAD_PIX) {
    PRJERR_BAD_PIX_SET(prj);
  }
d4590 1
a4590 1
  int mphi, mtheta, rowlen, rowoff, status;
d4598 1
a4598 1
  if (prj == 0x0) return PRJERR_NULL_POINTER;
d4600 1
a4600 1
    if (status = aitset(prj)) return status;
d4684 1
a4684 1
  if (prj == 0x0) return PRJERR_NULL_POINTER;
a4687 1
  strcpy(prj->name, "conic perspective");
d4690 1
a4690 1
    return PRJERR_BAD_PARAM_SET(prj);
d4695 1
d4706 1
a4706 1
    return PRJERR_BAD_PARAM_SET(prj);
d4713 1
a4713 1
    return PRJERR_BAD_PARAM_SET(prj);
d4738 1
a4738 1
  int mx, my, rowlen, rowoff, status;
d4745 1
a4745 1
  if (prj == 0x0) return PRJERR_NULL_POINTER;
d4747 1
a4747 1
    if (status = copset(prj)) return status;
d4823 1
a4823 1
  if (prj == 0x0) return PRJERR_NULL_POINTER;
d4825 1
a4825 1
    if (status = copset(prj)) return status;
d4873 1
a4873 1
      status = PRJERR_BAD_WORLD;
d4880 1
a4880 1
        status = PRJERR_BAD_WORLD;
a4890 3
  if (status == PRJERR_BAD_WORLD) {
    PRJERR_BAD_WORLD_SET(prj);
  }
d4932 1
a4932 1
  if (prj == 0x0) return PRJERR_NULL_POINTER;
a4935 1
  strcpy(prj->name, "conic equal area");
d4938 1
a4938 1
    return PRJERR_BAD_PARAM_SET(prj);
d4943 1
d4957 1
a4957 1
    return PRJERR_BAD_PARAM_SET(prj);
d4996 1
a4996 1
  if (prj == 0x0) return PRJERR_NULL_POINTER;
d4998 1
a4998 1
    if (status = coeset(prj)) return status;
d5062 1
a5062 1
            status = PRJERR_BAD_PIX;
a5074 3
  if (status == PRJERR_BAD_PIX) {
    PRJERR_BAD_PIX_SET(prj);
  }
d5089 1
a5089 1
  int mphi, mtheta, rowlen, rowoff, status;
d5096 1
a5096 1
  if (prj == 0x0) return PRJERR_NULL_POINTER;
d5098 1
a5098 1
    if (status = coeset(prj)) return status;
d5184 1
a5184 1
  if (prj == 0x0) return PRJERR_NULL_POINTER;
a5187 1
  strcpy(prj->name, "conic equidistant");
d5190 1
a5190 1
    return PRJERR_BAD_PARAM_SET(prj);
d5195 1
d5211 1
a5211 1
    return PRJERR_BAD_PARAM_SET(prj);
d5235 1
a5235 1
  int mx, my, rowlen, rowoff, status;
d5242 1
a5242 1
  if (prj == 0x0) return PRJERR_NULL_POINTER;
d5244 1
a5244 1
    if (status = codset(prj)) return status;
d5313 1
a5313 1
  int mphi, mtheta, rowlen, rowoff, status;
d5320 1
a5320 1
  if (prj == 0x0) return PRJERR_NULL_POINTER;
d5322 1
a5322 1
    if (status = codset(prj)) return status;
d5409 1
a5409 1
  if (prj == 0x0) return PRJERR_NULL_POINTER;
a5412 1
  strcpy(prj->name, "conic orthomorphic");
d5415 1
a5415 1
    return PRJERR_BAD_PARAM_SET(prj);
d5420 1
d5443 1
a5443 1
    return PRJERR_BAD_PARAM_SET(prj);
d5450 1
a5450 1
    return PRJERR_BAD_PARAM_SET(prj);
d5479 1
a5479 1
  if (prj == 0x0) return PRJERR_NULL_POINTER;
d5481 1
a5481 1
    if (status = cooset(prj)) return status;
d5539 1
a5539 1
          status = PRJERR_BAD_PIX;
a5550 3
  if (status == PRJERR_BAD_PIX) {
    PRJERR_BAD_PIX_SET(prj);
  }
d5572 1
a5572 1
  if (prj == 0x0) return PRJERR_NULL_POINTER;
d5574 1
a5574 1
    if (status = cooset(prj)) return status;
d5621 1
a5621 1
        status = PRJERR_BAD_WORLD;
a5633 3
  if (status == PRJERR_BAD_WORLD) {
    PRJERR_BAD_WORLD_SET(prj);
  }
d5664 1
a5664 1
  if (prj == 0x0) return PRJERR_NULL_POINTER;
a5667 1
  strcpy(prj->name, "Bonne's");
d5670 1
a5670 1
    return PRJERR_BAD_PARAM_SET(prj);
d5678 1
d5713 1
a5713 1
  int mx, my, rowlen, rowoff, status;
d5721 1
a5721 1
  if (prj == 0x0) return PRJERR_NULL_POINTER;
d5728 1
a5728 1
    if (status = bonset(prj)) return status;
d5805 1
a5805 1
  int mphi, mtheta, rowlen, rowoff, status;
d5812 1
a5812 1
  if (prj == 0x0) return PRJERR_NULL_POINTER;
d5819 1
a5819 1
    if (status = bonset(prj)) return status;
d5895 1
a5895 1
  if (prj == 0x0) return PRJERR_NULL_POINTER;
d5937 1
a5937 1
  int mx, my, rowlen, rowoff, status;
d5947 1
a5947 1
  if (prj == 0x0) return PRJERR_NULL_POINTER;
d5949 1
a5949 1
    if (status = pcoset(prj)) return status;
d6074 1
a6074 1
  int mphi, mtheta, rowlen, rowoff, status;
d6081 1
a6081 1
  if (prj == 0x0) return PRJERR_NULL_POINTER;
d6083 1
a6083 1
    if (status = pcoset(prj)) return status;
d6160 1
a6160 1
  if (prj == 0x0) return PRJERR_NULL_POINTER;
d6208 1
a6208 1
  if (prj == 0x0) return PRJERR_NULL_POINTER;
d6210 1
a6210 1
    if (status = tscset(prj)) return status;
d6257 1
a6257 1
          status = PRJERR_BAD_PIX;
d6265 1
a6265 1
          status = PRJERR_BAD_PIX;
a6321 3
  if (status == PRJERR_BAD_PIX) {
    PRJERR_BAD_PIX_SET(prj);
  }
d6344 1
a6344 1
  if (prj == 0x0) return PRJERR_NULL_POINTER;
d6346 1
a6346 1
    if (status = tscset(prj)) return status;
d6459 1
a6459 1
          status = PRJERR_BAD_WORLD;
d6466 1
a6466 1
          status = PRJERR_BAD_WORLD;
a6476 3
  if (status == PRJERR_BAD_WORLD) {
    PRJERR_BAD_WORLD_SET(prj);
  }
d6504 1
a6504 1
  if (prj == 0x0) return PRJERR_NULL_POINTER;
d6581 1
a6581 1
  if (prj == 0x0) return PRJERR_NULL_POINTER;
d6583 1
a6583 1
    if (status = cscset(prj)) return status;
d6630 1
a6630 1
          status = PRJERR_BAD_PIX;
d6638 1
a6638 1
          status = PRJERR_BAD_PIX;
a6737 3
  if (status == PRJERR_BAD_PIX) {
    PRJERR_BAD_PIX_SET(prj);
  }
d6776 1
a6776 1
  if (prj == 0x0) return PRJERR_NULL_POINTER;
d6778 1
a6778 1
    if (status = cscset(prj)) return status;
d6912 1
a6912 1
          status = PRJERR_BAD_WORLD;
d6919 1
a6919 1
          status = PRJERR_BAD_WORLD;
a6929 3
  if (status == PRJERR_BAD_WORLD) {
    PRJERR_BAD_WORLD_SET(prj);
  }
d6957 1
a6957 1
  if (prj == 0x0) return PRJERR_NULL_POINTER;
d7006 1
a7006 1
  if (prj == 0x0) return PRJERR_NULL_POINTER;
d7008 1
a7008 1
    if (status = qscset(prj)) return status;
d7055 1
a7055 1
          status = PRJERR_BAD_PIX;
d7063 1
a7063 1
          status = PRJERR_BAD_PIX;
d7126 1
a7126 1
          status = PRJERR_BAD_PIX;
a7223 3
  if (status == PRJERR_BAD_PIX) {
    PRJERR_BAD_PIX_SET(prj);
  }
d7248 1
a7248 1
  if (prj == 0x0) return PRJERR_NULL_POINTER;
d7250 1
a7250 1
    if (status = qscset(prj)) return status;
d7433 1
a7433 1
          status = PRJERR_BAD_WORLD;
d7440 1
a7440 1
          status = PRJERR_BAD_WORLD;
a7450 3
  if (status == PRJERR_BAD_WORLD) {
    PRJERR_BAD_WORLD_SET(prj);
  }
d7492 1
a7492 1
  if (prj == 0x0) return PRJERR_NULL_POINTER;
d7510 1
a7510 1
    return PRJERR_BAD_PARAM_SET(prj);
d7561 1
a7561 1
  if (prj == 0x0) return PRJERR_NULL_POINTER;
d7563 1
a7563 1
    if (status = hpxset(prj)) return status;
d7634 1
a7634 1
          status = PRJERR_BAD_PIX;
d7665 1
a7665 1
          status = PRJERR_BAD_PIX;
d7676 1
a7676 1
      status = PRJERR_BAD_PIX;
a7679 3
  if (status == PRJERR_BAD_PIX) {
    PRJERR_BAD_PIX_SET(prj);
  }
d7694 1
a7694 1
  int h, mphi, mtheta, offset, rowlen, rowoff, status;
d7702 1
a7702 1
  if (prj == 0x0) return PRJERR_NULL_POINTER;
d7704 1
a7704 1
    if (status = hpxset(prj)) return status;
@


4.7.1.3
log
@Revised implementation of Michael Droettboom's error messaging system.
@
text
@d31 1
a31 1
  $Id: prj.c,v 4.7.1.1 2011/02/07 07:04:22 cal103 Exp cal103 $
a35 1
#include <stdlib.h>
a37 1
#include "wcserr.h"
a40 1
#include "wcsutil.h"
d104 13
a116 13
#define PRJERR_BAD_PARAM_SET(function) \
  wcserr_set(&(prj->err), PRJERR_BAD_PARAM, function, __FILE__, __LINE__, \
    "Invalid parameters for %s projection", prj->name);

#define PRJERR_BAD_PIX_SET(function) \
  wcserr_set(&(prj->err), PRJERR_BAD_PIX, function, __FILE__, __LINE__, \
    "One or more of the (x, y) coordinates were invalid for %s projection", \
    prj->name);

#define PRJERR_BAD_WORLD_SET(function) \
  wcserr_set(&(prj->err), PRJERR_BAD_WORLD, function, __FILE__, __LINE__, \
    "One or more of the (lat, lng) coordinates were invalid for " \
    "%s projection", prj->name);
d148 2
a177 17
  prj->err = 0x0;

  return 0;
}

/*--------------------------------------------------------------------------*/

int prjfree(prj)

struct prjprm *prj;

{
  if (prj == 0x0) return PRJERR_NULL_POINTER;

  if (prj->err) free(prj->err);
  prj->err = 0x0;

d188 1
a188 2
  char hext[32];
  int  i, n;
a244 6

  wcsprintf("        err: %p\n", (void *)prj->err);
  if (prj->err) {
    wcserr_prt(prj->err, "");
  }

d256 2
a257 4
  wcsprintf("     prjx2s: %s\n",
    wcsutil_fptr2str((int (*)())prj->prjx2s, hext));
  wcsprintf("     prjs2x: %s\n",
    wcsutil_fptr2str((int (*)())prj->prjs2x, hext));
a268 2
  static const char *function = "prjset";

a269 1
  struct wcserr **err;
a271 1
  err = &(prj->err);
d331 3
a333 2
    status = wcserr_set(WCSERR_SET(PRJERR_BAD_PARAM),
               "Unrecognized projection code '%s'", prj->code);
d351 1
a351 1

d355 1
a355 1
    if ((status = prjset(prj))) return status;
d373 1
a373 1

d377 1
a377 1
    if ((status = prjset(prj))) return status;
d410 1
a410 1
      return PRJERR_BAD_PARAM_SET("prjoff");
d474 1
a474 1
    return PRJERR_BAD_PARAM_SET("azpset");
d479 1
a479 1
    return PRJERR_BAD_PARAM_SET("azpset");
d518 1
a518 1

d523 1
a523 1
    if ((status = azpset(prj))) return status;
d587 1
a587 1
            if (!status) status = PRJERR_BAD_PIX_SET("azpx2s");
d607 4
d635 1
a635 1
    if ((status = azpset(prj))) return status;
d684 1
a684 1
        if (!status) status = PRJERR_BAD_WORLD_SET("azps2x");
d695 1
a695 1
            if (!status) status = PRJERR_BAD_WORLD_SET("azps2x");
d712 1
a712 1
                if (!status) status = PRJERR_BAD_WORLD_SET("azps2x");
d725 4
d794 1
a794 1
    return PRJERR_BAD_PARAM_SET("szpset");
d838 1
a838 1
    if ((status = szpset(prj))) return status;
d901 1
a901 1
          if (!status) status = PRJERR_BAD_PIX_SET("szpx2s");
d928 1
a928 1
          if (!status) status = PRJERR_BAD_PIX_SET("szpx2s");
d942 4
d970 1
a970 1
    if ((status = szpset(prj))) return status;
d1019 1
a1019 1
      if (!status) status = PRJERR_BAD_WORLD_SET("szps2x");
d1033 1
a1033 1
            if (!status) status = PRJERR_BAD_WORLD_SET("szps2x");
d1051 1
a1051 1
                if (!status) status = PRJERR_BAD_WORLD_SET("szps2x");
d1064 4
d1137 1
a1137 1
    if ((status = tanset(prj))) return status;
d1213 1
a1213 1
    if ((status = tanset(prj))) return status;
d1259 1
a1259 1
      if (!status) status = PRJERR_BAD_WORLD_SET("tans2x");
d1267 1
a1267 1
        if (!status) status = PRJERR_BAD_WORLD_SET("tans2x");
d1278 3
d1358 1
a1358 1
    if ((status = stgset(prj))) return status;
d1434 1
a1434 1
    if ((status = stgset(prj))) return status;
d1480 1
a1480 1
      if (!status) status = PRJERR_BAD_WORLD_SET("stgs2x");
d1493 3
d1580 1
a1580 1
    if ((status = sinset(prj))) return status;
d1641 1
a1641 1
          if (!status) status = PRJERR_BAD_PIX_SET("sinx2s")
d1650 3
a1652 3
          /* Use small angle formula. */
          z = r2/2.0;
          *thetap = 90.0 - R2D*sqrt(r2/(1.0 + xy));
d1655 40
a1694 26
          a = prj->w[2];
          b = xy - prj->w[1];
          c = r2 - xy - xy + prj->w[3];
          d = b*b - a*c;

          /* Check for a solution. */
          if (d < 0.0) {
            *phip = 0.0;
            *thetap = 0.0;
            *(statp++) = 1;
            if (!status) status = PRJERR_BAD_PIX_SET("sinx2s")
            continue;
          }
          d = sqrt(d);

          /* Choose solution closest to pole. */
          sinth1 = (-b + d)/a;
          sinth2 = (-b - d)/a;
          sinthe = (sinth1 > sinth2) ? sinth1 : sinth2;
          if (sinthe > 1.0) {
            if (sinthe-1.0 < tol) {
              sinthe = 1.0;
            } else {
              sinthe = (sinth1 < sinth2) ? sinth1 : sinth2;
            }
          }
d1696 2
a1697 16
          if (sinthe < -1.0) {
            if (sinthe+1.0 > -tol) {
              sinthe = -1.0;
            }
          }

          if (sinthe > 1.0 || sinthe < -1.0) {
            *phip = 0.0;
            *thetap = 0.0;
            *(statp++) = 1;
            if (!status) status = PRJERR_BAD_PIX_SET("sinx2s")
            continue;
          }

          *thetap = asind(sinthe);
          z = 1.0 - sinthe;
d1713 3
d1740 1
a1740 1
    if ((status = sinset(prj))) return status;
d1798 1
a1798 1
        if (!status) status = PRJERR_BAD_WORLD_SET("sins2x");
d1819 1
a1819 1
            if (!status) status = PRJERR_BAD_WORLD_SET("sins2x");
d1830 3
d1910 1
a1910 1
    if ((status = arcset(prj))) return status;
d1987 1
a1987 1
    if ((status = arcset(prj))) return status;
d2090 1
a2090 1
    return PRJERR_BAD_PARAM_SET("zpnset");
d2104 1
a2104 1
      return PRJERR_BAD_PARAM_SET("zpnset");
d2182 1
a2182 1
    if ((status = zpnset(prj))) return status;
d2235 1
a2235 1
        return PRJERR_BAD_PARAM_SET("zpnx2s");
d2249 1
a2249 1
          if (!status) status = PRJERR_BAD_PIX_SET("zpnx2s");
d2263 1
a2263 1
            if (!status) status = PRJERR_BAD_PIX_SET("zpnx2s");
d2271 1
a2271 1
            if (!status) status = PRJERR_BAD_PIX_SET("zpnx2s");
d2287 1
a2287 1
            if (!status) status = PRJERR_BAD_PIX_SET("zpnx2s");
d2295 1
a2295 1
            if (!status) status = PRJERR_BAD_PIX_SET("zpnx2s");
d2336 3
d2363 1
a2363 1
    if ((status = zpnset(prj))) return status;
d2413 1
a2413 1
      if (!status) status = PRJERR_BAD_WORLD_SET("zpns2x");
d2423 3
d2504 1
a2504 1
    if ((status = zeaset(prj))) return status;
d2560 1
a2560 1
          if (!status) status = PRJERR_BAD_PIX_SET("zeax2s");
d2571 3
d2598 1
a2598 1
    if ((status = zeaset(prj))) return status;
d2710 1
a2710 1
    return PRJERR_BAD_PARAM_SET("airset");
d2746 1
a2746 1
    if ((status = airset(prj))) return status;
d2816 1
a2816 1
          if (!status) status = PRJERR_BAD_PIX_SET("airx2s");
d2846 1
a2846 1
          if (!status) status = PRJERR_BAD_PIX_SET("airx2s");
d2858 3
d2885 1
a2885 1
    if ((status = airset(prj))) return status;
d2940 1
a2940 1
      if (!status) status = PRJERR_BAD_WORLD_SET("airs2x");
d2950 3
d3010 1
a3010 1
      return PRJERR_BAD_PARAM_SET("cypset");
d3017 1
a3017 1
      return PRJERR_BAD_PARAM_SET("cypset");
d3024 1
a3024 1
      return PRJERR_BAD_PARAM_SET("cypset");
d3031 1
a3031 1
      return PRJERR_BAD_PARAM_SET("cypset");
d3064 1
a3064 1
    if ((status = cypset(prj))) return status;
d3130 1
a3130 1
    if ((status = cypset(prj))) return status;
d3170 1
a3170 1
      if (!status) status = PRJERR_BAD_WORLD_SET("cyps2x");
d3183 3
d3240 1
a3240 1
      return PRJERR_BAD_PARAM_SET("ceaset");
d3248 1
a3248 1
      return PRJERR_BAD_PARAM_SET("ceaset");
d3282 1
a3282 1
    if ((status = ceaset(prj))) return status;
d3324 1
a3324 1
        if (!status) status = PRJERR_BAD_PIX_SET("ceax2s");
d3338 3
d3365 1
a3365 1
    if ((status = ceaset(prj))) return status;
d3483 1
a3483 1
    if ((status = carset(prj))) return status;
d3548 1
a3548 1
    if ((status = carset(prj))) return status;
d3666 1
a3666 1
    if ((status = merset(prj))) return status;
d3731 1
a3731 1
    if ((status = merset(prj))) return status;
d3771 1
a3771 1
      if (!status) status = PRJERR_BAD_WORLD_SET("mers2x");
d3782 3
d3862 1
a3862 1
    if ((status = sflset(prj))) return status;
a3873 2
  status = 0;

d3902 1
a3902 1
      if (!status) status = PRJERR_BAD_PIX_SET("sflx2s");
d3916 3
d3943 1
a3943 1
    if ((status = sflset(prj))) return status;
d4071 1
a4071 1
    if ((status = parset(prj))) return status;
d4119 1
a4119 1
      if (!status) status = PRJERR_BAD_PIX_SET("parx2s");
d4139 1
a4139 1
          if (!status) status = PRJERR_BAD_PIX_SET("parx2s");
d4148 3
d4175 1
a4175 1
    if ((status = parset(prj))) return status;
d4299 1
a4299 1
    if ((status = molset(prj))) return status;
d4348 1
a4348 1
        if (!status) status = PRJERR_BAD_PIX_SET("molx2s");
d4367 1
a4367 1
        if (!status) status = PRJERR_BAD_PIX_SET("molx2s");
d4379 1
a4379 1
        if (!status) status = PRJERR_BAD_PIX_SET("molx2s");
d4393 1
a4393 1
          if (!status) status = PRJERR_BAD_PIX_SET("molx2s");
d4402 3
d4430 1
a4430 1
    if ((status = molset(prj))) return status;
d4578 1
a4578 1
    if ((status = aitset(prj))) return status;
d4629 1
a4629 1
          if (!status) status = PRJERR_BAD_PIX_SET("aitx2s");
d4648 1
a4648 1
          if (!status) status = PRJERR_BAD_PIX_SET("aitx2s");
d4661 3
d4688 1
a4688 1
    if ((status = aitset(prj))) return status;
d4779 1
a4779 1
    return PRJERR_BAD_PARAM_SET("copset");
d4794 1
a4794 1
    return PRJERR_BAD_PARAM_SET("copset");
d4801 1
a4801 1
    return PRJERR_BAD_PARAM_SET("copset");
d4835 1
a4835 1
    if ((status = copset(prj))) return status;
d4913 1
a4913 1
    if ((status = copset(prj))) return status;
d4961 1
a4961 1
      if (!status) status = PRJERR_BAD_WORLD_SET("cops2x");
d4968 1
a4968 1
        if (!status) status = PRJERR_BAD_WORLD_SET("cops2x");
d4979 3
d5030 1
a5030 1
    return PRJERR_BAD_PARAM_SET("coeset");
d5048 1
a5048 1
    return PRJERR_BAD_PARAM_SET("coeset");
d5089 1
a5089 1
    if ((status = coeset(prj))) return status;
d5153 1
a5153 1
            if (!status) status = PRJERR_BAD_PIX_SET("coex2s");
d5166 3
d5192 1
a5192 1
    if ((status = coeset(prj))) return status;
d5285 1
a5285 1
    return PRJERR_BAD_PARAM_SET("codset");
d5305 1
a5305 1
    return PRJERR_BAD_PARAM_SET("codset");
d5338 1
a5338 1
    if ((status = codset(prj))) return status;
d5416 1
a5416 1
    if ((status = codset(prj))) return status;
d5510 1
a5510 1
    return PRJERR_BAD_PARAM_SET("cooset");
d5537 1
a5537 1
    return PRJERR_BAD_PARAM_SET("cooset");
d5544 1
a5544 1
    return PRJERR_BAD_PARAM_SET("cooset");
d5575 1
a5575 1
    if ((status = cooset(prj))) return status;
d5633 1
a5633 1
          if (!status) status = PRJERR_BAD_PIX_SET("coox2s");
d5645 3
d5671 1
a5671 1
    if ((status = cooset(prj))) return status;
d5718 1
a5718 1
        if (!status) status = PRJERR_BAD_WORLD_SET("coos2x");
d5731 3
d5771 1
a5771 1
    return PRJERR_BAD_PARAM_SET("bonset");
d5828 1
a5828 1
    if ((status = bonset(prj))) return status;
d5919 1
a5919 1
    if ((status = bonset(prj))) return status;
d6049 1
a6049 1
    if ((status = pcoset(prj))) return status;
d6183 1
a6183 1
    if ((status = pcoset(prj))) return status;
d6310 1
a6310 1
    if ((status = tscset(prj))) return status;
d6357 1
a6357 1
          if (!status) status = PRJERR_BAD_PIX_SET("tscx2s");
d6365 1
a6365 1
          if (!status) status = PRJERR_BAD_PIX_SET("tscx2s");
d6422 3
d6449 1
a6449 1
    if ((status = tscset(prj))) return status;
d6562 1
a6562 1
          if (!status) status = PRJERR_BAD_WORLD_SET("tscs2x");
d6569 1
a6569 1
          if (!status) status = PRJERR_BAD_WORLD_SET("tscs2x");
d6580 3
d6689 1
a6689 1
    if ((status = cscset(prj))) return status;
d6736 1
a6736 1
          if (!status) status = PRJERR_BAD_PIX_SET("cscx2s");
d6744 1
a6744 1
          if (!status) status = PRJERR_BAD_PIX_SET("cscx2s");
d6844 3
d6887 1
a6887 1
    if ((status = cscset(prj))) return status;
d7021 1
a7021 1
          if (!status) status = PRJERR_BAD_WORLD_SET("cscs2x");
d7028 1
a7028 1
          if (!status) status = PRJERR_BAD_WORLD_SET("cscs2x");
d7039 3
d7120 1
a7120 1
    if ((status = qscset(prj))) return status;
d7167 1
a7167 1
          if (!status) status = PRJERR_BAD_PIX_SET("qscx2s");
d7175 1
a7175 1
          if (!status) status = PRJERR_BAD_PIX_SET("qscx2s");
d7238 1
a7238 1
          if (!status) status = PRJERR_BAD_PIX_SET("qscx2s");
d7336 3
d7365 1
a7365 1
    if ((status = qscset(prj))) return status;
d7548 1
a7548 1
          if (!status) status = PRJERR_BAD_WORLD_SET("qscs2x");
d7555 1
a7555 1
          if (!status) status = PRJERR_BAD_WORLD_SET("qscs2x");
d7566 3
d7628 1
a7628 1
    return PRJERR_BAD_PARAM_SET("hpxset");
d7681 1
a7681 1
    if ((status = hpxset(prj))) return status;
d7702 1
a7702 1
    /* x_c for K odd or theta > 0. */
d7752 1
a7752 1
          if (!status) status = PRJERR_BAD_PIX_SET("hpxx2s");
d7783 1
a7783 1
          if (!status) status = PRJERR_BAD_PIX_SET("hpxx2s");
d7794 1
a7794 1
      if (!status) status = PRJERR_BAD_PIX_SET("hpxx2s");
d7798 3
d7825 1
a7825 1
    if ((status = hpxset(prj))) return status;
d7845 1
a7845 1
    /* phi_c for K odd or theta > 0. */
@


4.7.1.4
log
@Trivial change to a comment.
@
text
@d31 1
a31 1
  $Id: prj.c,v 4.7.1.3 2011/08/09 02:43:50 cal103 Exp cal103 $
d106 1
a106 1
/* Convenience macros for generating common error messages. */
@


4.7.1.5
log
@Use the WCSPRINTF_PTR() macro for printing addresses.
@
text
@d31 1
a31 1
  $Id: prj.c,v 4.7.1.4 2011/08/10 04:24:32 cal103 Exp cal103 $
d265 1
a265 1
  WCSPRINTF_PTR("        err: ", prj->err, "\n");
@


4.6
log
@WCSLIB 4.6
@
text
@d3 2
a4 2
  WCSLIB 4.6 - an implementation of the FITS WCS standard.
  Copyright (C) 1995-2010, Mark Calabretta
d31 1
a31 1
  $Id: prj.c,v 4.5.1.1 2010/07/16 07:05:31 cal103 Exp cal103 $
d39 1
d159 1
a160 1
  prj->padding = 0;
d176 4
a179 4
  printf("       flag: %d\n",  prj->flag);
  printf("       code: \"%s\"\n",  prj->code);
  printf("         r0: %9f\n", prj->r0);
  printf("         pv:");
d184 1
a184 1
      printf(" (0)");
d186 1
a186 1
      printf(" %- 11.5g", prj->pv[0]);
d192 1
a192 1
        printf("\n           ");
d196 1
a196 1
        printf("  UNDEFINED   ");
d198 1
a198 1
        printf("  %- 11.5g", prj->pv[i]);
d201 1
a201 1
    printf("\n");
d203 1
a203 1
    printf(" (not used)\n");
d206 1
a206 1
    printf("       phi0: UNDEFINED\n");
d208 1
a208 1
    printf("       phi0: %9f\n", prj->phi0);
d211 1
a211 1
    printf("     theta0: UNDEFINED\n");
d213 1
a213 1
    printf("     theta0: %9f\n", prj->theta0);
d215 1
a215 1
  printf("     bounds: %d\n",  prj->bounds);
d217 13
a229 13
  printf("\n");
  printf("       name: \"%s\"\n", prj->name);
  printf("   category: %d (%s)\n", prj->category,
                                   prj_categories[prj->category]);
  printf("    pvrange: %d\n", prj->pvrange);
  printf("  simplezen: %d\n", prj->simplezen);
  printf("  equiareal: %d\n", prj->equiareal);
  printf("  conformal: %d\n", prj->conformal);
  printf("     global: %d\n", prj->global);
  printf("  divergent: %d\n", prj->divergent);
  printf("         x0: %f\n", prj->x0);
  printf("         y0: %f\n", prj->y0);
  printf("        w[]:");
d231 1
a231 1
    printf("  %- 11.5g", prj->w[i]);
d233 1
a233 1
  printf("\n            ");
d235 1
a235 1
    printf("  %- 11.5g", prj->w[i]);
d237 5
a241 4
  printf("\n");
  printf("          n: %d\n", prj->n);
  printf("     prjx2s: %p\n", (void *)prj->prjx2s);
  printf("     prjs2x: %p\n", (void *)prj->prjs2x);
d7471 1
d7481 2
a7482 2
*      prj->w[8]    (90*K/H)*r0*(pi/180)
*      prj->w[9]     (180/H)*r0*(pi/180)
d7513 2
a7514 1
  prj->n = ((int)prj->pv[2])%2;
d7553 2
a7554 1
  const double tol = 1.0e-12;
d7584 1
d7618 1
a7618 1
    } else if (absy <= 90.0) {
d7645 1
a7645 1
          h = (int)floor(*phip / prj->w[6]);
d7655 1
a7655 1
        if ((fabs(s) - prj->w[6]) < tol) {
d7723 4
a7726 2
    t  = -180.0 + (2.0*floor((*phip+180.0) * prj->w[7]) + 1.0) * prj->w[6];
    t  = prj->w[0] * (*phip - t);
d7731 1
a7731 1
      /* y[] is used to hold an intermediate value. */
d7771 1
a7771 1
          h = (int)floor((*xp + prj->x0) / prj->w[9]);
d7779 1
a7779 1
        /* Recall that y[] holds an intermediate value. */
d7783 3
@


4.6.1.1
log
@WCSLIB 4.6 development branch.
@
text
@d31 1
a31 1
  $Id: prj.c,v 4.6 2010/11/16 06:15:31 cal103 Exp $
@


4.6.1.2
log
@Updated date in copyright notice.
@
text
@d4 1
a4 1
  Copyright (C) 1995-2011, Mark Calabretta
d31 1
a31 1
  $Id: prj.c,v 4.6.1.1 2010/11/16 06:16:19 cal103 Exp cal103 $
@


4.6.1.3
log
@Fixed the bounds test in hpxx2s() added at 4.2.1.3.
@
text
@d31 1
a31 1
  $Id: prj.c,v 4.6.1.2 2011/01/14 06:33:16 cal103 Exp cal103 $
d7548 1
a7548 1
  double absy, s, sigma, t, yr, ymax;
a7595 1
  ymax   = prj->w[9] * prj->w[4];
d7612 1
a7612 1
    } else if (absy <= ymax) {
@


4.6.1.4
log
@In prjini(), initialize prj::m and in prjprt() print its value.  In
hpxset(), set prj::m true if H is odd, and in hpxx2s() and hpxs2x()
use it to correct the offset of the southern polar half-facets for
even K.  In hpxs2x(), put the phi = 180 meridian in the expected place.
@
text
@d31 1
a31 1
  $Id: prj.c,v 4.6.1.3 2011/01/19 23:49:02 cal103 Exp $
a157 1
  prj->m = 0;
d159 1
a236 1
  printf("          m: %d\n", prj->m);
a7468 1
*      prj->m       True if H is odd.
d7478 2
a7479 2
*      prj->w[8]    r0*(pi/180)*(90*K/H)
*      prj->w[9]    r0*(pi/180)*(180/H)
d7510 1
a7510 2
  prj->m = ((int)(prj->pv[1]+0.5))%2;
  prj->n = ((int)(prj->pv[2]+0.5))%2;
d7548 2
a7549 3
  double absy, s, sigma, t, yr;
  const double slim = prj->w[6] + 1e-12;
  const double ylim = prj->w[9] * prj->w[4];
a7578 1
    /* x_c for K odd or theta > 0. */ 
d7596 1
d7613 1
a7613 1
    } else if (absy <= ylim) {
d7640 1
a7640 1
          h = (int)floor(*phip / prj->w[6]) + prj->m;
d7650 1
a7650 1
        if (fabs(s) < slim) {
d7718 2
a7719 4

    /* phi_c for K odd or theta > 0. */ 
    t = -180.0 + (2.0*floor((*phip+180.0) * prj->w[7]) + 1.0) * prj->w[6];
    t = prj->w[0] * (*phip - t);
d7724 1
a7724 1
      /* y[] is used to hold (phi - phi_c). */
d7764 1
a7764 1
          h = (int)floor((*xp + prj->x0) / prj->w[9]) + prj->m;
d7772 1
a7772 1
        /* Recall that y[] holds (phi - phi_c). */
a7775 3

        /* Put the phi = 180 meridian in the expected place. */
        if (180.0 < *xp) *xp = 360.0 - *xp;
@


4.6.1.5
log
@Replaced calls to printf() with wcsprintf().
@
text
@d31 1
a31 1
  $Id: prj.c,v 4.6.1.4 2011/01/25 00:04:13 cal103 Exp cal103 $
a38 1
#include "wcsprintf.h"
d175 4
a178 4
  wcsprintf("       flag: %d\n",  prj->flag);
  wcsprintf("       code: \"%s\"\n",  prj->code);
  wcsprintf("         r0: %9f\n", prj->r0);
  wcsprintf("         pv:");
d183 1
a183 1
      wcsprintf(" (0)");
d185 1
a185 1
      wcsprintf(" %- 11.5g", prj->pv[0]);
d191 1
a191 1
        wcsprintf("\n           ");
d195 1
a195 1
        wcsprintf("  UNDEFINED   ");
d197 1
a197 1
        wcsprintf("  %- 11.5g", prj->pv[i]);
d200 1
a200 1
    wcsprintf("\n");
d202 1
a202 1
    wcsprintf(" (not used)\n");
d205 1
a205 1
    wcsprintf("       phi0: UNDEFINED\n");
d207 1
a207 1
    wcsprintf("       phi0: %9f\n", prj->phi0);
d210 1
a210 1
    wcsprintf("     theta0: UNDEFINED\n");
d212 1
a212 1
    wcsprintf("     theta0: %9f\n", prj->theta0);
d214 1
a214 1
  wcsprintf("     bounds: %d\n",  prj->bounds);
d216 13
a228 13
  wcsprintf("\n");
  wcsprintf("       name: \"%s\"\n", prj->name);
  wcsprintf("   category: %d (%s)\n", prj->category,
                                      prj_categories[prj->category]);
  wcsprintf("    pvrange: %d\n", prj->pvrange);
  wcsprintf("  simplezen: %d\n", prj->simplezen);
  wcsprintf("  equiareal: %d\n", prj->equiareal);
  wcsprintf("  conformal: %d\n", prj->conformal);
  wcsprintf("     global: %d\n", prj->global);
  wcsprintf("  divergent: %d\n", prj->divergent);
  wcsprintf("         x0: %f\n", prj->x0);
  wcsprintf("         y0: %f\n", prj->y0);
  wcsprintf("        w[]:");
d230 1
a230 1
    wcsprintf("  %- 11.5g", prj->w[i]);
d232 1
a232 1
  wcsprintf("\n            ");
d234 1
a234 1
    wcsprintf("  %- 11.5g", prj->w[i]);
d236 5
a240 5
  wcsprintf("\n");
  wcsprintf("          m: %d\n", prj->m);
  wcsprintf("          n: %d\n", prj->n);
  wcsprintf("     prjx2s: %p\n", (void *)prj->prjx2s);
  wcsprintf("     prjs2x: %p\n", (void *)prj->prjs2x);
@


4.5
log
@WCSLIB 4.5
@
text
@d3 1
a3 1
  WCSLIB 4.5 - an implementation of the FITS WCS standard.
d31 1
a31 1
  $Id: prj.c,v 4.4.1.2 2010/01/19 03:42:50 cal103 Exp cal103 $
@


4.5.1.1
log
@WCSLIB 4.5 development branch.
@
text
@d31 1
a31 1
  $Id: prj.c,v 4.5 2010/07/16 07:01:25 cal103 Exp $
@


4.4
log
@WCSLIB 4.4
@
text
@d3 2
a4 2
  WCSLIB 4.4 - an implementation of the FITS WCS standard.
  Copyright (C) 1995-2009, Mark Calabretta
d31 1
a31 1
  $Id: prj.c,v 4.3.1.5 2009/08/05 05:21:01 cal103 Exp cal103 $
@


4.4.1.1
log
@WCSLIB 4.4 development branch.
@
text
@d31 1
a31 1
  $Id: prj.c,v 4.4 2009/08/06 07:41:33 cal103 Exp $
@


4.4.1.2
log
@Updated date in copyright notice.
@
text
@d4 1
a4 1
  Copyright (C) 1995-2010, Mark Calabretta
d31 1
a31 1
  $Id: prj.c,v 4.4.1.1 2009/08/10 08:52:49 cal103 Exp cal103 $
@


4.3
log
@WCSLIB 4.3
@
text
@d3 2
a4 2
    WCSLIB 4.3 - an implementation of the FITS WCS standard.
    Copyright (C) 1995-2007, Mark Calabretta
d6 1
a6 1
    This file is part of WCSLIB.
d8 24
a31 24
    WCSLIB is free software: you can redistribute it and/or modify it under
    the terms of the GNU Lesser General Public License as published by the
    Free Software Foundation, either version 3 of the License, or (at your
    option) any later version.

    WCSLIB 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 Lesser General Public License for
    more details.

    You should have received a copy of the GNU Lesser General Public License
    along with WCSLIB.  If not, see <http://www.gnu.org/licenses/>.

    Correspondence concerning WCSLIB may be directed to:
       Internet email: mcalabre@@atnf.csiro.au
       Postal address: Dr. Mark Calabretta
                       Australia Telescope National Facility, CSIRO
                       PO Box 76
                       Epping NSW 1710
                       AUSTRALIA

    Author: Mark Calabretta, Australia Telescope National Facility
    http://www.atnf.csiro.au/~mcalabre/index.html
    $Id: prj.c,v 4.2.1.9 2007/12/26 03:00:45 cal103 Exp cal103 $
d54 2
a55 2
      {"undefined", "zenithal", "cylindrical", "pseudocylindrical",
       "conventional", "conic", "polyconic", "quadcube", "HEALPix"};
d61 3
a63 3
      {"AZP", "SZP", "TAN", "STG", "SIN", "ARC", "ZPN", "ZEA", "AIR", "CYP",
       "CEA", "CAR", "MER", "COP", "COE", "COD", "COO", "SFL", "PAR", "MOL",
       "AIT", "BON", "PCO", "TSC", "CSC", "QSC", "HPX"};
d96 5
a100 5
   "Success",
   "Null prjprm pointer passed",
   "Invalid projection parameters",
   "One or more of the (x,y) coordinates were invalid",
   "One or more of the (phi,theta) coordinates were invalid"};
d129 1
a129 1
   register int k;
d131 1
a131 1
   if (prj == 0x0) return 1;
d133 1
a133 1
   prj->flag = 0;
d135 25
a159 23
   strcpy(prj->code, "   ");
   prj->pv[0]  = 0.0;
   prj->pv[1]  = UNDEFINED;
   prj->pv[2]  = UNDEFINED;
   prj->pv[3]  = UNDEFINED;
   for (k = 4; k < PVN; prj->pv[k++] = 0.0);
   prj->r0     = 0.0;
   prj->phi0   = UNDEFINED;
   prj->theta0 = UNDEFINED;
   prj->bounds = 1;

   strcpy(prj->name, "undefined");
   prj->category  = 0;
   prj->pvrange   = 0;
   prj->simplezen = 0;
   prj->equiareal = 0;
   prj->conformal = 0;
   prj->global    = 0;
   prj->divergent = 0;
   prj->x0 = 0.0;
   prj->y0 = 0.0;
   for (k = 0; k < 10; prj->w[k++] = 0.0);
   prj->n = 0;
d161 1
a161 1
   return 0;
d171 1
a171 1
   int i, n;
d173 1
a173 1
   if (prj == 0x0) return 1;
d175 65
a239 65
   printf("       flag: %d\n",  prj->flag);
   printf("       code: \"%s\"\n",  prj->code);
   printf("         r0: %9f\n", prj->r0);
   printf("         pv:");
   if (prj->pvrange) {
      n = (prj->pvrange)%100;

      if (prj->pvrange/100) {
         printf(" (0)");
      } else {
         printf(" %- 11.5g", prj->pv[0]);
         n--;
      }

      for (i = 1; i <= n; i++) {
         if (i%5 == 1) {
            printf("\n           ");
         }

         if (undefined(prj->pv[i])) {
            printf("  UNDEFINED   ");
         } else {
            printf("  %- 11.5g", prj->pv[i]);
         }
      }
      printf("\n");
   } else {
      printf(" (not used)\n");
   }
   if (undefined(prj->phi0)) {
      printf("       phi0: UNDEFINED\n");
   } else {
      printf("       phi0: %9f\n", prj->phi0);
   }
   if (undefined(prj->theta0)) {
      printf("     theta0: UNDEFINED\n");
   } else {
      printf("     theta0: %9f\n", prj->theta0);
   }
   printf("     bounds: %d\n",  prj->bounds);

   printf("\n");
   printf("       name: \"%s\"\n", prj->name);
   printf("   category: %d (%s)\n", prj->category,
                                    prj_categories[prj->category]);
   printf("    pvrange: %d\n", prj->pvrange);
   printf("  simplezen: %d\n", prj->simplezen);
   printf("  equiareal: %d\n", prj->equiareal);
   printf("  conformal: %d\n", prj->conformal);
   printf("     global: %d\n", prj->global);
   printf("  divergent: %d\n", prj->divergent);
   printf("         x0: %f\n", prj->x0);
   printf("         y0: %f\n", prj->y0);
   printf("        w[]:");
   for (i = 0; i < 5; i++) {
      printf("  %- 11.5g", prj->w[i]);
   }
   printf("\n            ");
   for (i = 5; i < 10; i++) {
      printf("  %- 11.5g", prj->w[i]);
   }
   printf("\n");
   printf("          n: %d\n", prj->n);
   printf("     prjx2s: %p\n", (void *)prj->prjx2s);
   printf("     prjs2x: %p\n", (void *)prj->prjs2x);
d241 1
a241 1
   return 0;
d251 1
a251 1
   int status;
d253 1
a253 1
   if (prj == 0x0) return 1;
d255 60
a314 60
   /* Invoke the relevant initialization routine. */
   prj->code[3] = '\0';
   if (strcmp(prj->code, "AZP") == 0) {
      status = azpset(prj);
   } else if (strcmp(prj->code, "SZP") == 0) {
      status = szpset(prj);
   } else if (strcmp(prj->code, "TAN") == 0) {
      status = tanset(prj);
   } else if (strcmp(prj->code, "STG") == 0) {
      status = stgset(prj);
   } else if (strcmp(prj->code, "SIN") == 0) {
      status = sinset(prj);
   } else if (strcmp(prj->code, "ARC") == 0) {
      status = arcset(prj);
   } else if (strcmp(prj->code, "ZPN") == 0) {
      status = zpnset(prj);
   } else if (strcmp(prj->code, "ZEA") == 0) {
      status = zeaset(prj);
   } else if (strcmp(prj->code, "AIR") == 0) {
      status = airset(prj);
   } else if (strcmp(prj->code, "CYP") == 0) {
      status = cypset(prj);
   } else if (strcmp(prj->code, "CEA") == 0) {
      status = ceaset(prj);
   } else if (strcmp(prj->code, "CAR") == 0) {
      status = carset(prj);
   } else if (strcmp(prj->code, "MER") == 0) {
      status = merset(prj);
   } else if (strcmp(prj->code, "SFL") == 0) {
      status = sflset(prj);
   } else if (strcmp(prj->code, "PAR") == 0) {
      status = parset(prj);
   } else if (strcmp(prj->code, "MOL") == 0) {
      status = molset(prj);
   } else if (strcmp(prj->code, "AIT") == 0) {
      status = aitset(prj);
   } else if (strcmp(prj->code, "COP") == 0) {
      status = copset(prj);
   } else if (strcmp(prj->code, "COE") == 0) {
      status = coeset(prj);
   } else if (strcmp(prj->code, "COD") == 0) {
      status = codset(prj);
   } else if (strcmp(prj->code, "COO") == 0) {
      status = cooset(prj);
   } else if (strcmp(prj->code, "BON") == 0) {
      status = bonset(prj);
   } else if (strcmp(prj->code, "PCO") == 0) {
      status = pcoset(prj);
   } else if (strcmp(prj->code, "TSC") == 0) {
      status = tscset(prj);
   } else if (strcmp(prj->code, "CSC") == 0) {
      status = cscset(prj);
   } else if (strcmp(prj->code, "QSC") == 0) {
      status = qscset(prj);
   } else if (strcmp(prj->code, "HPX") == 0) {
      status = hpxset(prj);
   } else {
      /* Unrecognized projection code. */
      status = 2;
   }
d316 1
a316 1
   return status;
d330 5
a334 5
   /* Initialize. */
   if (prj == 0x0) return 1;
   if (prj->flag == 0) {
      if (prjset(prj)) return 2;
   }
d336 1
a336 1
   return prj->prjx2s(prj, nx, ny, sxy, spt, x, y, phi, theta, stat);
d350 5
a354 5
   /* Initialize. */
   if (prj == 0x0) return 1;
   if (prj->flag == 0) {
      if (prjset(prj)) return 2;
   }
d356 1
a356 1
   return prj->prjs2x(prj, nphi, ntheta, spt, sxy, phi, theta, x, y, stat);
d370 2
a371 1
   int    stat;
d373 1
a373 1
   if (prj == 0x0) return 1;
d375 2
a376 4
   if (undefined(prj->phi0) || undefined(prj->theta0)) {
      /* Set both to the projection-specific default if either undefined. */
      prj->phi0   = phi0;
      prj->theta0 = theta0;
d378 10
a387 2
      prj->x0 = 0.0;
      prj->y0 = 0.0;
d389 3
a391 6
   } else {
      if (prj->prjs2x(prj, 1, 1, 1, 1, &(prj->phi0), &(prj->theta0),
                      &(prj->x0), &(prj->y0), &stat)) {
         return 2;
      }
   }
d393 1
a393 1
   return 0;
d430 1
a430 17
   if (prj == 0x0) return 1;

   prj->flag = AZP;
   strcpy(prj->code, "AZP");

   if (undefined(prj->pv[1])) prj->pv[1] = 0.0;
   if (undefined(prj->pv[2])) prj->pv[2] = 0.0;
   if (prj->r0 == 0.0) prj->r0 = R2D;

   strcpy(prj->name, "zenithal/azimuthal perspective");
   prj->category  = ZENITHAL;
   prj->pvrange   = 102;
   prj->simplezen = prj->pv[2] == 0.0;
   prj->equiareal = 0;
   prj->conformal = 0;
   prj->global    = 0;
   prj->divergent = prj->pv[1] <= 1.0;
d432 2
a433 13
   prj->w[0] = prj->r0*(prj->pv[1] + 1.0);
   if (prj->w[0] == 0.0) {
      return 2;
   }

   prj->w[3] = cosd(prj->pv[2]);
   if (prj->w[3] == 0.0) {
      return 2;
   }

   prj->w[2] = 1.0/prj->w[3];
   prj->w[4] = sind(prj->pv[2]);
   prj->w[1] = prj->w[4] / prj->w[3];
d435 32
a466 5
   if (fabs(prj->pv[1]) > 1.0) {
      prj->w[5] = asind(-1.0/prj->pv[1]);
   } else {
      prj->w[5] = -90.0;
   }
d468 2
a469 2
   prj->w[6] = prj->pv[1] * prj->w[3];
   prj->w[7] = (fabs(prj->w[6]) < 1.0) ? 1.0 : 0.0;
d471 2
a472 2
   prj->prjx2s = azpx2s;
   prj->prjs2x = azps2x;
d474 1
a474 1
   return prjoff(prj, 0.0, 90.0);
d488 62
a549 48
   int mx, my, rowlen, rowoff, status;
   double a, b, q, r, s, t, xj, yj, yc, yc2;
   const double tol = 1.0e-13;
   register int ix, iy, *statp;
   register const double *xp, *yp;
   register double *phip, *thetap;


   /* Initialize. */
   if (prj == 0x0) return 1;
   if (prj->flag != AZP) {
      if (azpset(prj)) return 2;
   }

   if (ny > 0) {
      mx = nx;
      my = ny;
   } else {
      mx = 1;
      my = 1;
      ny = nx;
   }

   status = 0;


   /* Do x dependence. */
   xp = x;
   rowoff = 0;
   rowlen = nx*spt;
   for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
      xj = *xp + prj->x0;

      phip = phi + rowoff;
      for (iy = 0; iy < my; iy++) {
         *phip = xj;
         phip += rowlen;
      }
   }


   /* Do y dependence. */
   yp = y;
   phip   = phi;
   thetap = theta;
   statp  = stat;
   for (iy = 0; iy < ny; iy++, yp += sxy) {
      yj = *yp + prj->y0;
d551 2
a552 2
      yc  = yj*prj->w[3];
      yc2 = yc*yc;
d554 2
a555 1
      q = prj->w[0] + yj*prj->w[4];
d557 1
a557 2
      for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
         xj = *phip;
d559 11
a569 25
         r = sqrt(xj*xj + yc2);
         if (r == 0.0) {
            *phip = 0.0;
            *thetap = 90.0;
            *(statp++) = 0;

         } else {
            *phip = atan2d(xj, -yc);

            s = r / q;
            t = s*prj->pv[1]/sqrt(s*s + 1.0);

            s = atan2d(1.0, s);

            if (fabs(t) > 1.0) {
               if (fabs(t) > 1.0+tol) {
                  *thetap = 0.0;
                  *(statp++) = 1;
                  status = 3;
                  continue;
               }
               t = copysign(90.0, t);
            } else {
               t = asind(t);
            }
d571 2
a572 2
            a = s - t;
            b = s + t + 180.0;
d574 2
a575 2
            if (a > 90.0) a -= 360.0;
            if (b > 90.0) b -= 360.0;
d577 2
a578 3
            *thetap = (a > b) ? a : b;
            *(statp++) = 0;
         }
d580 2
a581 1
   }
d583 1
a583 1
   return status;
d597 60
a656 52
   int mphi, mtheta, rowlen, rowoff, status;
   double a, b, cosphi, costhe, r, s, sinphi, sinthe, t;
   register int iphi, itheta, istat, *statp;
   register const double *phip, *thetap;
   register double *xp, *yp;


   /* Initialize. */
   if (prj == 0x0) return 1;
   if (prj->flag != AZP) {
      if (azpset(prj)) return 2;
   }

   if (ntheta > 0) {
      mphi   = nphi;
      mtheta = ntheta;
   } else {
      mphi   = 1;
      mtheta = 1;
      ntheta = nphi;
   }

   status = 0;


   /* Do phi dependence. */
   phip = phi;
   rowoff = 0;
   rowlen = nphi*sxy;
   for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
      sinphi = sind(*phip);
      cosphi = cosd(*phip);

      xp = x + rowoff;
      yp = y + rowoff;
      for (itheta = 0; itheta < mtheta; itheta++) {
         *xp = sinphi;
         *yp = cosphi;
         xp += rowlen;
         yp += rowlen;
      }
   }


   /* Do theta dependence. */
   thetap = theta;
   xp = x;
   yp = y;
   statp = stat;
   for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
      costhe = cosd(*thetap);
      sinthe = sind(*thetap);
d658 2
a659 3
      for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
         s = prj->w[1]*(*yp);
         t = (prj->pv[1] + sinthe) + costhe*s;
d661 6
a666 4
         if (t == 0.0) {
            *xp = 0.0;
            *yp = 0.0;
            *(statp++) = 1;
d669 24
a692 36
         } else {
            r = prj->w[0]*costhe/t;

            /* Bounds checking. */
            istat = 0;
            if (prj->bounds) {
               if (*thetap < prj->w[5]) {
                  /* Overlap. */
                  istat  = 1;
                  status = 4;

               } else if (prj->w[7] > 0.0) {
                  /* Divergence. */
                  t = prj->pv[1] / sqrt(1.0 + s*s);

                  if (fabs(t) <= 1.0) {
                     s = atand(-s);
                     t = asind(t);
                     a = s - t;
                     b = s + t + 180.0;

                     if (a > 90.0) a -= 360.0;
                     if (b > 90.0) b -= 360.0;

                     if (*thetap < ((a > b) ? a : b)) {
                        istat  = 1;
                        status = 4;
                     }
                  }
               }
            }

            *xp =  r*(*xp) - prj->x0;
            *yp = -r*(*yp)*prj->w[2] - prj->y0;
            *(statp++) = istat;
         }
d694 2
a695 1
   }
d697 1
a697 1
   return status;
d739 1
a739 18
   if (prj == 0x0) return 1;

   prj->flag = SZP;
   strcpy(prj->code, "SZP");

   if (undefined(prj->pv[1])) prj->pv[1] =  0.0;
   if (undefined(prj->pv[2])) prj->pv[2] =  0.0;
   if (undefined(prj->pv[3])) prj->pv[3] = 90.0;
   if (prj->r0 == 0.0) prj->r0 = R2D;

   strcpy(prj->name, "slant zenithal perspective");
   prj->category  = ZENITHAL;
   prj->pvrange   = 103;
   prj->simplezen = prj->pv[3] == 90.0;
   prj->equiareal = 0;
   prj->conformal = 0;
   prj->global    = 0;
   prj->divergent = prj->pv[1] <= 1.0;
d741 2
a742 1
   prj->w[0] = 1.0/prj->r0;
d744 33
a776 17
   prj->w[3] = prj->pv[1] * sind(prj->pv[3]) + 1.0;
   if (prj->w[3] == 0.0) {
      return 2;
   }

   prj->w[1] = -prj->pv[1] * cosd(prj->pv[3]) * sind(prj->pv[2]);
   prj->w[2] =  prj->pv[1] * cosd(prj->pv[3]) * cosd(prj->pv[2]);
   prj->w[4] =  prj->r0 * prj->w[1];
   prj->w[5] =  prj->r0 * prj->w[2];
   prj->w[6] =  prj->r0 * prj->w[3];
   prj->w[7] =  (prj->w[3] - 1.0) * prj->w[3] - 1.0;

   if (fabs(prj->w[3] - 1.0) < 1.0) {
      prj->w[8] = asind(1.0 - prj->w[3]);
   } else {
      prj->w[8] = -90.0;
   }
d778 2
a779 2
   prj->prjx2s = szpx2s;
   prj->prjs2x = szps2x;
d781 1
a781 1
   return prjoff(prj, 0.0, 90.0);
d795 61
a855 48
   int mx, my, rowlen, rowoff, status;
   double a, b, c, d, r2, sinth1, sinth2, sinthe, t, x1, xr, xy, y1, yr, z;
   const double tol = 1.0e-13;
   register int ix, iy, *statp;
   register const double *xp, *yp;
   register double *phip, *thetap;


   /* Initialize. */
   if (prj == 0x0) return 1;
   if (prj->flag != SZP) {
      if (szpset(prj)) return 2;
   }

   if (ny > 0) {
      mx = nx;
      my = ny;
   } else {
      mx = 1;
      my = 1;
      ny = nx;
   }

   status = 0;


   /* Do x dependence. */
   xp = x;
   rowoff = 0;
   rowlen = nx*spt;
   for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
      xr = (*xp + prj->x0)*prj->w[0];

      phip = phi + rowoff;
      for (iy = 0; iy < my; iy++) {
         *phip = xr;
         phip += rowlen;
      }
   }


   /* Do y dependence. */
   yp = y;
   phip   = phi;
   thetap = theta;
   statp  = stat;
   for (iy = 0; iy < ny; iy++, yp += sxy) {
      yr = (*yp + prj->y0)*prj->w[0];
d857 52
a908 65
      for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
         xr = *phip;
         r2 = xr*xr + yr*yr;

         x1 = (xr - prj->w[1])/prj->w[3];
         y1 = (yr - prj->w[2])/prj->w[3];
         xy = xr*x1 + yr*y1;

         if (r2 < 1.0e-10) {
            /* Use small angle formula. */
            z = r2/2.0;
            *thetap = 90.0 - R2D*sqrt(r2/(1.0 + xy));

         } else {
            t = x1*x1 + y1*y1;
            a = t + 1.0;
            b = xy - t;
            c = r2 - xy - xy + t - 1.0;
            d = b*b - a*c;

            /* Check for a solution. */
            if (d < 0.0) {
               *phip = 0.0;
               *thetap = 0.0;
               *(statp++) = 1;
               status = 3;
               continue;
            }
            d = sqrt(d);

            /* Choose solution closest to pole. */
            sinth1 = (-b + d)/a;
            sinth2 = (-b - d)/a;
            sinthe = (sinth1 > sinth2) ? sinth1 : sinth2;
            if (sinthe > 1.0) {
               if (sinthe-1.0 < tol) {
                  sinthe = 1.0;
               } else {
                  sinthe = (sinth1 < sinth2) ? sinth1 : sinth2;
               }
            }

            if (sinthe < -1.0) {
               if (sinthe+1.0 > -tol) {
                  sinthe = -1.0;
               }
            }

            if (sinthe > 1.0 || sinthe < -1.0) {
               *phip   = 0.0;
               *thetap = 0.0;
               *(statp++) = 1;
               status = 3;
               continue;
            }

            *thetap = asind(sinthe);

            z = 1.0 - sinthe;
         }

         *phip = atan2d(xr - x1*z, -(yr - y1*z));
         *(statp++) = 0;
      }
   }
d910 1
a910 1
   return status;
d924 51
a974 52
   int mphi, mtheta, rowlen, rowoff, status;
   double a, b, cosphi, r, s, sinphi, t, u, v;
   register int iphi, itheta, istat, *statp;
   register const double *phip, *thetap;
   register double *xp, *yp;


   /* Initialize. */
   if (prj == 0x0) return 1;
   if (prj->flag != SZP) {
      if (szpset(prj)) return 2;
   }

   if (ntheta > 0) {
      mphi   = nphi;
      mtheta = ntheta;
   } else {
      mphi   = 1;
      mtheta = 1;
      ntheta = nphi;
   }

   status = 0;


   /* Do phi dependence. */
   phip = phi;
   rowoff = 0;
   rowlen = nphi*sxy;
   for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
      sinphi = sind(*phip);
      cosphi = cosd(*phip);

      xp = x + rowoff;
      yp = y + rowoff;
      for (itheta = 0; itheta < mtheta; itheta++) {
         *xp = sinphi;
         *yp = cosphi;
         xp += rowlen;
         yp += rowlen;
      }
   }


   /* Do theta dependence. */
   thetap = theta;
   xp = x;
   yp = y;
   statp = stat;
   for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
      s = 1.0 - sind(*thetap);
      t = prj->w[3] - s;
d976 8
a983 6
      if (t == 0.0) {
         for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
            *xp = 0.0;
            *yp = 0.0;
            *(statp++) = 1;
         }
d985 4
a988 1
         status = 4;
d990 8
a997 35
      } else {
         r = prj->w[6]*cosd(*thetap)/t;
         u = prj->w[4]*s/t + prj->x0;
         v = prj->w[5]*s/t + prj->y0;

         for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
            /* Bounds checking. */
            istat = 0;
            if (prj->bounds) {
               if (*thetap < prj->w[8]) {
                  /* Divergence. */
                  istat  = 1;
                  status = 4;

               } else if (fabs(prj->pv[1]) > 1.0) {
                  /* Overlap. */
                  s = prj->w[1]*(*xp) - prj->w[2]*(*yp);
                  t = 1.0/sqrt(prj->w[7] + s*s);

                  if (fabs(t) <= 1.0) {
                     s = atan2d(s, prj->w[3] - 1.0);
                     t = asind(t);
                     a = s - t;
                     b = s + t + 180.0;

                     if (a > 90.0) a -= 360.0;
                     if (b > 90.0) b -= 360.0;

                     if (*thetap < ((a > b) ? a : b)) {
                        istat  = 1;
                        status = 4;
                     }
                  }
               }
            }
d999 25
a1023 4
            *xp =  r*(*xp) - u;
            *yp = -r*(*yp) - v;
            *(statp++) = istat;
         }
d1025 2
a1026 1
   }
d1028 1
a1028 1
   return status;
d1054 1
a1054 1
   if (prj == 0x0) return 1;
d1056 2
a1057 2
   prj->flag = TAN;
   strcpy(prj->code, "TAN");
d1059 1
a1059 1
   if (prj->r0 == 0.0) prj->r0 = R2D;
d1061 8
a1068 8
   strcpy(prj->name, "gnomonic");
   prj->category  = ZENITHAL;
   prj->pvrange   = 0;
   prj->simplezen = 1;
   prj->equiareal = 0;
   prj->conformal = 0;
   prj->global    = 0;
   prj->divergent = 1;
d1070 2
a1071 2
   prj->prjx2s = tanx2s;
   prj->prjs2x = tans2x;
d1073 1
a1073 1
   return prjoff(prj, 0.0, 90.0);
d1087 56
a1142 46
   int mx, my, rowlen, rowoff;
   double r, xj, yj, yj2;
   register int ix, iy, *statp;
   register const double *xp, *yp;
   register double *phip, *thetap;


   /* Initialize. */
   if (prj == 0x0) return 1;
   if (prj->flag != TAN) {
      if (tanset(prj)) return 2;
   }

   if (ny > 0) {
      mx = nx;
      my = ny;
   } else {
      mx = 1;
      my = 1;
      ny = nx;
   }


   /* Do x dependence. */
   xp = x;
   rowoff = 0;
   rowlen = nx*spt;
   for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
      xj = *xp + prj->x0;

      phip = phi + rowoff;
      for (iy = 0; iy < my; iy++) {
         *phip = xj;
         phip += rowlen;
      }
   }


   /* Do y dependence. */
   yp = y;
   phip   = phi;
   thetap = theta;
   statp  = stat;
   for (iy = 0; iy < ny; iy++, yp += sxy) {
      yj  = *yp + prj->y0;
      yj2 = yj*yj;
d1144 4
a1147 14
      for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
         xj = *phip;

         r = sqrt(xj*xj + yj2);
         if (r == 0.0) {
            *phip = 0.0;
         } else {
            *phip = atan2d(xj, -yj);
         }

         *thetap = atan2d(prj->r0, r);
         *(statp++) = 0;
      }
   }
d1149 1
a1149 1
   return 0;
d1163 57
a1219 58
   int mphi, mtheta, rowlen, rowoff, status;
   double cosphi, r, s, sinphi;
   register int iphi, itheta, istat, *statp;
   register const double *phip, *thetap;
   register double *xp, *yp;


   /* Initialize. */
   if (prj == 0x0) return 1;
   if (prj->flag != TAN) {
      if (tanset(prj)) return 2;
   }

   if (ntheta > 0) {
      mphi   = nphi;
      mtheta = ntheta;
   } else {
      mphi   = 1;
      mtheta = 1;
      ntheta = nphi;
   }

   status = 0;


   /* Do phi dependence. */
   phip = phi;
   rowoff = 0;
   rowlen = nphi*sxy;
   for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
      sinphi = sind(*phip);
      cosphi = cosd(*phip);

      xp = x + rowoff;
      yp = y + rowoff;
      for (itheta = 0; itheta < mtheta; itheta++) {
         *xp = sinphi;
         *yp = cosphi;
         xp += rowlen;
         yp += rowlen;
      }
   }


   /* Do theta dependence. */
   thetap = theta;
   xp = x;
   yp = y;
   statp = stat;
   for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
      s = sind(*thetap);
      if (s == 0.0) {
         for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
            *xp = 0.0;
            *yp = 0.0;
            *(statp++) = 1;
         }
         status = 4;
d1221 2
a1222 2
      } else {
         r =  prj->r0*cosd(*thetap)/s;
d1224 5
a1228 5
         istat = 0;
         if (prj->bounds && s < 0.0) {
            istat  = 1;
            status = 4;
         }
d1230 4
a1233 5
         for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
            *xp =  r*(*xp) - prj->x0;
            *yp = -r*(*yp) - prj->y0;
            *(statp++) = istat;
         }
d1235 2
a1236 1
   }
d1238 1
a1238 1
   return status;
d1265 1
a1265 1
   if (prj == 0x0) return 1;
d1267 2
a1268 2
   prj->flag = STG;
   strcpy(prj->code, "STG");
d1270 17
a1286 17
   strcpy(prj->name, "stereographic");
   prj->category  = ZENITHAL;
   prj->pvrange   = 0;
   prj->simplezen = 1;
   prj->equiareal = 0;
   prj->conformal = 1;
   prj->global    = 0;
   prj->divergent = 1;

   if (prj->r0 == 0.0) {
      prj->r0 = R2D;
      prj->w[0] = 360.0/PI;
      prj->w[1] = PI/360.0;
   } else {
      prj->w[0] = 2.0*prj->r0;
      prj->w[1] = 1.0/prj->w[0];
   }
d1288 2
a1289 2
   prj->prjx2s = stgx2s;
   prj->prjs2x = stgs2x;
d1291 1
a1291 1
   return prjoff(prj, 0.0, 90.0);
d1305 56
a1360 46
   int mx, my, rowlen, rowoff;
   double r, xj, yj, yj2;
   register int ix, iy, *statp;
   register const double *xp, *yp;
   register double *phip, *thetap;


   /* Initialize. */
   if (prj == 0x0) return 1;
   if (prj->flag != STG) {
      if (stgset(prj)) return 2;
   }

   if (ny > 0) {
      mx = nx;
      my = ny;
   } else {
      mx = 1;
      my = 1;
      ny = nx;
   }


   /* Do x dependence. */
   xp = x;
   rowoff = 0;
   rowlen = nx*spt;
   for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
      xj = *xp + prj->x0;

      phip = phi + rowoff;
      for (iy = 0; iy < my; iy++) {
         *phip = xj;
         phip += rowlen;
      }
   }


   /* Do y dependence. */
   yp = y;
   phip   = phi;
   thetap = theta;
   statp  = stat;
   for (iy = 0; iy < ny; iy++, yp += sxy) {
      yj  = *yp + prj->y0;
      yj2 = yj*yj;
d1362 4
a1365 14
      for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
         xj  = *phip;

         r = sqrt(xj*xj + yj2);
         if (r == 0.0) {
            *phip = 0.0;
         } else {
            *phip = atan2d(xj, -yj);
         }

         *thetap = 90.0 - 2.0*atand(r*prj->w[1]);
         *(statp++) = 0;
      }
   }
d1367 1
a1367 1
   return 0;
d1381 57
a1437 58
   int mphi, mtheta, rowlen, rowoff, status;
   double cosphi, r, s, sinphi;
   register int iphi, itheta, *statp;
   register const double *phip, *thetap;
   register double *xp, *yp;


   /* Initialize. */
   if (prj == 0x0) return 1;
   if (prj->flag != STG) {
      if (stgset(prj)) return 2;
   }

   if (ntheta > 0) {
      mphi   = nphi;
      mtheta = ntheta;
   } else {
      mphi   = 1;
      mtheta = 1;
      ntheta = nphi;
   }

   status = 0;


   /* Do phi dependence. */
   phip = phi;
   rowoff = 0;
   rowlen = nphi*sxy;
   for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
      sinphi = sind(*phip);
      cosphi = cosd(*phip);

      xp = x + rowoff;
      yp = y + rowoff;
      for (itheta = 0; itheta < mtheta; itheta++) {
         *xp = sinphi;
         *yp = cosphi;
         xp += rowlen;
         yp += rowlen;
      }
   }


   /* Do theta dependence. */
   thetap = theta;
   xp = x;
   yp = y;
   statp = stat;
   for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
      s = 1.0 + sind(*thetap);
      if (s == 0.0) {
         for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
            *xp = 0.0;
            *yp = 0.0;
            *(statp++) = 1;
         }
         status = 4;
d1439 2
a1440 2
      } else {
         r = prj->w[0]*cosd(*thetap)/s;
d1442 4
a1445 5
         for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
            *xp =  r*(*xp) - prj->x0;
            *yp = -r*(*yp) - prj->y0;
            *(statp++) = 0;
         }
d1447 2
a1448 1
   }
d1450 1
a1450 1
   return status;
d1482 1
a1482 1
   if (prj == 0x0) return 1;
d1484 2
a1485 2
   prj->flag = SIN;
   strcpy(prj->code, "SIN");
d1487 17
a1503 17
   if (undefined(prj->pv[1])) prj->pv[1] = 0.0;
   if (undefined(prj->pv[2])) prj->pv[2] = 0.0;
   if (prj->r0 == 0.0) prj->r0 = R2D;

   strcpy(prj->name, "orthographic/synthesis");
   prj->category  = ZENITHAL;
   prj->pvrange   = 102;
   prj->simplezen = (prj->pv[1] == 0.0 && prj->pv[2] == 0.0);
   prj->equiareal = 0;
   prj->conformal = 0;
   prj->global    = 0;
   prj->divergent = 0;

   prj->w[0] = 1.0/prj->r0;
   prj->w[1] = prj->pv[1]*prj->pv[1] + prj->pv[2]*prj->pv[2];
   prj->w[2] = prj->w[1] + 1.0;
   prj->w[3] = prj->w[1] - 1.0;
d1505 2
a1506 2
   prj->prjx2s = sinx2s;
   prj->prjs2x = sins2x;
d1508 1
a1508 1
   return prjoff(prj, 0.0, 90.0);
d1522 58
a1579 53
   int mx, my, rowlen, rowoff, status;
   const double tol = 1.0e-13;
   double a, b, c, d, eta, r2, sinth1, sinth2, sinthe, x0, xi, x1, xy, y0,
          y02, y1, z;
   register int ix, iy, *statp;
   register const double *xp, *yp;
   register double *phip, *thetap;


   /* Initialize. */
   if (prj == 0x0) return 1;
   if (prj->flag != SIN) {
      if (sinset(prj)) return 2;
   }

   xi  = prj->pv[1];
   eta = prj->pv[2];

   if (ny > 0) {
      mx = nx;
      my = ny;
   } else {
      mx = 1;
      my = 1;
      ny = nx;
   }

   status = 0;


   /* Do x dependence. */
   xp = x;
   rowoff = 0;
   rowlen = nx*spt;
   for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
      x0 = (*xp + prj->x0)*prj->w[0];

      phip = phi + rowoff;
      for (iy = 0; iy < my; iy++) {
         *phip = x0;
         phip += rowlen;
      }
   }


   /* Do y dependence. */
   yp = y;
   phip   = phi;
   thetap = theta;
   statp  = stat;
   for (iy = 0; iy < ny; iy++, yp += sxy) {
      y0 = (*yp + prj->y0)*prj->w[0];
      y02 = y0*y0;
d1581 17
a1597 12
      for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
         /* Compute intermediaries. */
         x0 = *phip;
         r2 = x0*x0 + y02;

         if (prj->w[1] == 0.0) {
            /* Orthographic projection. */
            if (r2 != 0.0) {
               *phip = atan2d(x0, -y0);
            } else {
               *phip = 0.0;
            }
d1599 3
a1601 60
            if (r2 < 0.5) {
               *thetap = acosd(sqrt(r2));
            } else if (r2 <= 1.0) {
               *thetap = asind(sqrt(1.0 - r2));
            } else {
               *(statp++) = 1;
               status = 3;
               continue;
            }

         } else {
            /* "Synthesis" projection. */
            xy = x0*xi + y0*eta;

            if (r2 < 1.0e-10) {
               /* Use small angle formula. */
               z = r2/2.0;
               *thetap = 90.0 - R2D*sqrt(r2/(1.0 + xy));

            } else {
               a = prj->w[2];
               b = xy - prj->w[1];
               c = r2 - xy - xy + prj->w[3];
               d = b*b - a*c;

               /* Check for a solution. */
               if (d < 0.0) {
                  *phip = 0.0;
                  *thetap = 0.0;
                  *(statp++) = 1;
                  status = 3;
                  continue;
               }
               d = sqrt(d);

               /* Choose solution closest to pole. */
               sinth1 = (-b + d)/a;
               sinth2 = (-b - d)/a;
               sinthe = (sinth1 > sinth2) ? sinth1 : sinth2;
               if (sinthe > 1.0) {
                  if (sinthe-1.0 < tol) {
                     sinthe = 1.0;
                  } else {
                     sinthe = (sinth1 < sinth2) ? sinth1 : sinth2;
                  }
               }

               if (sinthe < -1.0) {
                  if (sinthe+1.0 > -tol) {
                     sinthe = -1.0;
                  }
               }

               if (sinthe > 1.0 || sinthe < -1.0) {
                  *phip = 0.0;
                  *thetap = 0.0;
                  *(statp++) = 1;
                  status = 3;
                  continue;
               }
d1603 63
a1665 12
               *thetap = asind(sinthe);
               z = 1.0 - sinthe;
            }

            x1 = -y0 + eta*z;
            y1 =  x0 -  xi*z;
            if (x1 == 0.0 && y1 == 0.0) {
               *phip = 0.0;
            } else {
               *phip = atan2d(y1,x1);
            }
         }
d1667 1
a1667 5
         *(statp++) = 0;
      }
   }

   return status;
d1681 53
a1733 58
   int mphi, mtheta, rowlen, rowoff, status;
   double cosphi, costhe, sinphi, r, t, z, z1, z2;
   register int iphi, itheta, istat, *statp;
   register const double *phip, *thetap;
   register double *xp, *yp;


   /* Initialize. */
   if (prj == 0x0) return 1;
   if (prj->flag != SIN) {
      if (sinset(prj)) return 2;
   }

   if (ntheta > 0) {
      mphi   = nphi;
      mtheta = ntheta;
   } else {
      mphi   = 1;
      mtheta = 1;
      ntheta = nphi;
   }

   status = 0;


   /* Do phi dependence. */
   phip = phi;
   rowoff = 0;
   rowlen = nphi*sxy;
   for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
      sinphi = sind(*phip);
      cosphi = cosd(*phip);

      xp = x + rowoff;
      yp = y + rowoff;
      for (itheta = 0; itheta < mtheta; itheta++) {
         *xp = sinphi;
         *yp = cosphi;
         xp += rowlen;
         yp += rowlen;
      }
   }


   /* Do theta dependence. */
   thetap = theta;
   xp = x;
   yp = y;
   statp = stat;
   for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
      t = (90.0 - fabs(*thetap))*D2R;
      if (t < 1.0e-5) {
         if (*thetap > 0.0) {
            z = t*t/2.0;
         } else {
            z = 2.0 - t*t/2.0;
         }
         costhe = t;
d1735 21
a1755 2
         z = 1.0 - sind(*thetap);
         costhe = cosd(*thetap);
a1756 1
      r = prj->r0*costhe;
d1758 11
a1768 4
      if (prj->w[1] == 0.0) {
         /* Orthographic projection. */
         istat = 0;
         if (prj->bounds && *thetap < 0.0) {
d1771 2
a1772 1
         }
d1774 3
a1776 26
         for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
            *xp =  r*(*xp) - prj->x0;
            *yp = -r*(*yp) - prj->y0;
            *(statp++) = istat;
         }

      } else {
         /* "Synthesis" projection. */
         z *= prj->r0;
         z1 = prj->pv[1]*z - prj->x0;
         z2 = prj->pv[2]*z - prj->y0;

         for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
            istat = 0;
            if (prj->bounds) {
               t = -atand(prj->pv[1]*(*xp) - prj->pv[2]*(*yp));
               if (*thetap < t) {
                  istat  = 1;
                  status = 4;
               }
            }

            *xp =  r*(*xp) + z1;
            *yp = -r*(*yp) + z2;
            *(statp++) = istat;
         }
d1778 2
a1779 1
   }
d1781 1
a1781 1
   return status;
d1808 1
a1808 1
   if (prj == 0x0) return 1;
d1810 2
a1811 2
   prj->flag = ARC;
   strcpy(prj->code, "ARC");
d1813 17
a1829 17
   strcpy(prj->name, "zenithal/azimuthal equidistant");
   prj->category  = ZENITHAL;
   prj->pvrange   = 0;
   prj->simplezen = 1;
   prj->equiareal = 0;
   prj->conformal = 0;
   prj->global    = 1;
   prj->divergent = 0;

   if (prj->r0 == 0.0) {
      prj->r0 = R2D;
      prj->w[0] = 1.0;
      prj->w[1] = 1.0;
   } else {
      prj->w[0] = prj->r0*D2R;
      prj->w[1] = 1.0/prj->w[0];
   }
d1831 2
a1832 2
   prj->prjx2s = arcx2s;
   prj->prjs2x = arcs2x;
d1834 1
a1834 1
   return prjoff(prj, 0.0, 90.0);
d1848 58
a1905 46
   int mx, my, rowlen, rowoff;
   double r, xj, yj, yj2;
   register int ix, iy, *statp;
   register const double *xp, *yp;
   register double *phip, *thetap;


   /* Initialize. */
   if (prj == 0x0) return 1;
   if (prj->flag != ARC) {
      if (arcset(prj)) return 2;
   }

   if (ny > 0) {
      mx = nx;
      my = ny;
   } else {
      mx = 1;
      my = 1;
      ny = nx;
   }


   /* Do x dependence. */
   xp = x;
   rowoff = 0;
   rowlen = nx*spt;
   for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
      xj = *xp + prj->x0;

      phip = phi + rowoff;
      for (iy = 0; iy < my; iy++) {
         *phip = xj;
         phip += rowlen;
      }
   }


   /* Do y dependence. */
   yp = y;
   phip   = phi;
   thetap = theta;
   statp  = stat;
   for (iy = 0; iy < ny; iy++, yp += sxy) {
      yj  = *yp + prj->y0;
      yj2 = yj*yj;
d1907 3
a1909 15
      for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
         xj = *phip;

         r = sqrt(xj*xj + yj2);
         if (r == 0.0) {
            *phip = 0.0;
            *thetap = 90.0;
         } else {
            *phip = atan2d(xj, -yj);
            *thetap = 90.0 - r*prj->w[1];
         }

         *(statp++) = 0;
      }
   }
d1911 1
a1911 1
   return 0;
d1925 55
a1979 49
   int mphi, mtheta, rowlen, rowoff;
   double cosphi, r, sinphi;
   register int iphi, itheta, *statp;
   register const double *phip, *thetap;
   register double *xp, *yp;


   /* Initialize. */
   if (prj == 0x0) return 1;
   if (prj->flag != ARC) {
      if (arcset(prj)) return 2;
   }

   if (ntheta > 0) {
      mphi   = nphi;
      mtheta = ntheta;
   } else {
      mphi   = 1;
      mtheta = 1;
      ntheta = nphi;
   }


   /* Do phi dependence. */
   phip = phi;
   rowoff = 0;
   rowlen = nphi*sxy;
   for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
      sinphi = sind(*phip);
      cosphi = cosd(*phip);

      xp = x + rowoff;
      yp = y + rowoff;
      for (itheta = 0; itheta < mtheta; itheta++) {
         *xp = sinphi;
         *yp = cosphi;
         xp += rowlen;
         yp += rowlen;
      }
   }


   /* Do theta dependence. */
   thetap = theta;
   xp = x;
   yp = y;
   statp = stat;
   for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
      r =  prj->w[0]*(90.0 - *thetap);
d1981 1
a1981 8
      for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
         *xp =  r*(*xp) - prj->x0;
         *yp = -r*(*yp) - prj->y0;
         *(statp++) = 0;
      }
   }

   return 0;
d2012 40
a2051 79
   int j, k, m;
   double d, d1, d2, r, zd, zd1, zd2;
   const double tol = 1.0e-13;

   if (prj == 0x0) return 1;

   strcpy(prj->code, "ZPN");
   prj->flag = ZPN;

   if (undefined(prj->pv[1])) prj->pv[1] = 0.0;
   if (undefined(prj->pv[2])) prj->pv[2] = 0.0;
   if (undefined(prj->pv[3])) prj->pv[3] = 0.0;
   if (prj->r0 == 0.0) prj->r0 = R2D;

   strcpy(prj->name, "zenithal/azimuthal polynomial");
   prj->category  = ZENITHAL;
   prj->pvrange   = 30;
   prj->simplezen = 1;
   prj->equiareal = 0;
   prj->conformal = 0;
   prj->global    = 0;
   prj->divergent = 0;

   /* Find the highest non-zero coefficient. */
   for (k = PVN-1; k >= 0 && prj->pv[k] == 0.0; k--);
   if (k < 0) return 2;

   prj->n = k;

   if (k < 2) {
      /* No point of inflection. */
      prj->w[0] = PI;

   } else {
      /* Find the point of inflection closest to the pole. */
      zd1 = 0.0;
      d1  = prj->pv[1];
      if (d1 <= 0.0) {
         return 2;
      }

      /* Find the point where the derivative first goes negative. */
      for (j = 0; j < 180; j++) {
         zd2 = j*D2R;
         d2  = 0.0;
         for (m = k; m > 0; m--) {
            d2 = d2*zd2 + m*prj->pv[m];
         }

         if (d2 <= 0.0) break;
         zd1 = zd2;
         d1  = d2;
      }

      if (j == 180) {
         /* No negative derivative -> no point of inflection. */
         zd = PI;
         prj->global = 1;
      } else {
         /* Find where the derivative is zero. */
         for (j = 1; j <= 10; j++) {
            zd = zd1 - d1*(zd2-zd1)/(d2-d1);

            d = 0.0;
            for (m = k; m > 0; m--) {
               d = d*zd + m*prj->pv[m];
            }

            if (fabs(d) < tol) break;

            if (d < 0.0) {
               zd2 = zd;
               d2  = d;
            } else {
               zd1 = zd;
               d1  = d;
            }
         }
      }
d2053 46
a2098 7
      r = 0.0;
      for (m = k; m >= 0; m--) {
         r = r*zd + prj->pv[m];
      }
      prj->w[0] = zd;
      prj->w[1] = r;
   }
d2100 2
a2101 2
   prj->prjx2s = zpnx2s;
   prj->prjs2x = zpns2x;
d2103 1
a2103 1
   return prjoff(prj, 0.0, 90.0);
d2117 61
a2177 51
   int j, k, m, mx, my, rowlen, rowoff, status;
   double a, b, c, d, lambda, r, r1, r2, rt, xj, yj, yj2, zd, zd1, zd2;
   const double tol = 1.0e-13;
   register int ix, iy, *statp;
   register const double *xp, *yp;
   register double *phip, *thetap;


   /* Initialize. */
   if (prj == 0x0) return 1;
   if (prj->flag != ZPN) {
      if (zpnset(prj)) return 2;
   }

   k = prj->n;

   if (ny > 0) {
      mx = nx;
      my = ny;
   } else {
      mx = 1;
      my = 1;
      ny = nx;
   }

   status = 0;


   /* Do x dependence. */
   xp = x;
   rowoff = 0;
   rowlen = nx*spt;
   for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
      xj = *xp + prj->x0;

      phip = phi + rowoff;
      for (iy = 0; iy < my; iy++) {
         *phip = xj;
         phip += rowlen;
      }
   }


   /* Do y dependence. */
   yp = y;
   phip   = phi;
   thetap = theta;
   statp  = stat;
   for (iy = 0; iy < ny; iy++, yp += sxy) {
      yj  = *yp + prj->y0;
      yj2 = yj*yj;
d2179 49
a2227 2
      for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
         xj = *phip;
d2229 37
a2265 73
         r = sqrt(xj*xj + yj2)/prj->r0;
         if (r == 0.0) {
            *phip = 0.0;
         } else {
            *phip = atan2d(xj, -yj);
         }

         if (k < 1) {
            /* Constant - no solution. */
            return 2;
         } else if (k == 1) {
            /* Linear. */
            zd = (r - prj->pv[0])/prj->pv[1];
         } else if (k == 2) {
            /* Quadratic. */
            a = prj->pv[2];
            b = prj->pv[1];
            c = prj->pv[0] - r;

            d = b*b - 4.0*a*c;
            if (d < 0.0) {
               *thetap = 0.0;
               *(statp++) = 1;
               status = 3;
               continue;
            }
            d = sqrt(d);

            /* Choose solution closest to pole. */
            zd1 = (-b + d)/(2.0*a);
            zd2 = (-b - d)/(2.0*a);
            zd  = (zd1<zd2) ? zd1 : zd2;
            if (zd < -tol) zd = (zd1>zd2) ? zd1 : zd2;
            if (zd < 0.0) {
               if (zd < -tol) {
                  *thetap = 0.0;
                  *(statp++) = 1;
                  status = 3;
                  continue;
               }
               zd = 0.0;
            } else if (zd > PI) {
               if (zd > PI+tol) {
                  *thetap = 0.0;
                  *(statp++) = 1;
                  status = 3;
                  continue;
               }
               zd = PI;
            }
         } else {
            /* Higher order - solve iteratively. */
            zd1 = 0.0;
            r1  = prj->pv[0];
            zd2 = prj->w[0];
            r2  = prj->w[1];

            if (r < r1) {
               if (r < r1-tol) {
                  *thetap = 0.0;
                  *(statp++) = 1;
                  status = 3;
                  continue;
               }
               zd = zd1;
            } else if (r > r2) {
               if (r > r2+tol) {
                  *thetap = 0.0;
                  *(statp++) = 1;
                  status = 3;
                  continue;
               }
               zd = zd2;
d2267 3
a2269 28
               /* Disect the interval. */
               for (j = 0; j < 100; j++) {
                  lambda = (r2 - r)/(r2 - r1);
                  if (lambda < 0.1) {
                     lambda = 0.1;
                  } else if (lambda > 0.9) {
                     lambda = 0.9;
                  }

                  zd = zd2 - lambda*(zd2 - zd1);

                  rt = 0.0;
                  for (m = k; m >= 0; m--) {
                      rt = (rt * zd) + prj->pv[m];
                  }

                  if (rt < r) {
                     if (r-rt < tol) break;
                     r1 = rt;
                     zd1 = zd;
                  } else {
                     if (rt-r < tol) break;
                     r2 = rt;
                     zd2 = zd;
                  }

                  if (fabs(zd2-zd1) < tol) break;
               }
a2270 1
         }
d2272 3
a2274 2
         *thetap = 90.0 - zd*R2D;
         *(statp++) = 0;
a2275 1
   }
d2277 6
a2282 1
   return status;
d2296 69
a2364 57
   int m, mphi, mtheta, rowlen, rowoff, status;
   double cosphi, r, s, sinphi;
   register int iphi, itheta, istat, *statp;
   register const double *phip, *thetap;
   register double *xp, *yp;


   /* Initialize. */
   if (prj == 0x0) return 1;
   if (prj->flag != ZPN) {
      if (zpnset(prj)) return 2;
   }

   if (ntheta > 0) {
      mphi   = nphi;
      mtheta = ntheta;
   } else {
      mphi   = 1;
      mtheta = 1;
      ntheta = nphi;
   }

   status = 0;


   /* Do phi dependence. */
   phip = phi;
   rowoff = 0;
   rowlen = nphi*sxy;
   for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
      sinphi = sind(*phip);
      cosphi = cosd(*phip);

      xp = x + rowoff;
      yp = y + rowoff;
      for (itheta = 0; itheta < mtheta; itheta++) {
         *xp = sinphi;
         *yp = cosphi;
         xp += rowlen;
         yp += rowlen;
      }
   }


   /* Do theta dependence. */
   thetap = theta;
   xp = x;
   yp = y;
   statp = stat;
   for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
      s = (90.0 - *thetap)*D2R;

      r = 0.0;
      for (m = prj->n; m >= 0; m--) {
         r = r*s + prj->pv[m];
      }
      r *= prj->r0;
d2366 1
a2366 14
      istat = 0;
      if (prj->bounds && s > prj->w[0]) {
         istat  = 1;
         status = 4;
      }

      for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
         *xp =  r*(*xp) - prj->x0;
         *yp = -r*(*yp) - prj->y0;
         *(statp++) = istat;
      }
   }

   return status;
d2393 1
a2393 1
   if (prj == 0x0) return 1;
d2395 2
a2396 2
   prj->flag = ZEA;
   strcpy(prj->code, "ZEA");
d2398 17
a2414 17
   strcpy(prj->name, "zenithal/azimuthal equal area");
   prj->category  = ZENITHAL;
   prj->pvrange   = 0;
   prj->simplezen = 1;
   prj->equiareal = 1;
   prj->conformal = 0;
   prj->global    = 1;
   prj->divergent = 0;

   if (prj->r0 == 0.0) {
      prj->r0 = R2D;
      prj->w[0] = 360.0/PI;
      prj->w[1] = PI/360.0;
   } else {
      prj->w[0] = 2.0*prj->r0;
      prj->w[1] = 1.0/prj->w[0];
   }
d2416 2
a2417 2
   prj->prjx2s = zeax2s;
   prj->prjs2x = zeas2x;
d2419 1
a2419 1
   return prjoff(prj, 0.0, 90.0);
d2433 59
a2491 49
   int mx, my, rowlen, rowoff, status;
   double r, s, xj, yj, yj2;
   const double tol = 1.0e-12;
   register int ix, iy, *statp;
   register const double *xp, *yp;
   register double *phip, *thetap;


   /* Initialize. */
   if (prj == 0x0) return 1;
   if (prj->flag != ZEA) {
      if (zeaset(prj)) return 2;
   }

   if (ny > 0) {
      mx = nx;
      my = ny;
   } else {
      mx = 1;
      my = 1;
      ny = nx;
   }

   status = 0;


   /* Do x dependence. */
   xp = x;
   rowoff = 0;
   rowlen = nx*spt;
   for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
      xj = *xp + prj->x0;

      phip = phi + rowoff;
      for (iy = 0; iy < my; iy++) {
         *phip = xj;
         phip += rowlen;
      }
   }


   /* Do y dependence. */
   yp = y;
   phip   = phi;
   thetap = theta;
   statp  = stat;
   for (iy = 0; iy < ny; iy++, yp += sxy) {
      yj  = *yp + prj->y0;
      yj2 = yj*yj;
d2493 13
a2505 2
      for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
         xj  = *phip;
d2507 3
a2509 24
         r = sqrt(xj*xj + yj2);
         if (r == 0.0) {
            *phip = 0.0;
         } else {
            *phip = atan2d(xj, -yj);
         }

         s = r*prj->w[1];
         if (fabs(s) > 1.0) {
            if (fabs(r - prj->w[0]) < tol) {
               *thetap = -90.0;
            } else {
               *thetap = 0.0;
               *(statp++) = 1;
               status = 3;
               continue;
            }
         } else {
            *thetap = 90.0 - 2.0*asind(s);
         }

         *(statp++) = 0;
      }
   }
d2511 1
a2511 1
   return status;
d2525 55
a2579 49
   int mphi, mtheta, rowlen, rowoff;
   double cosphi, r, sinphi;
   register int iphi, itheta, *statp;
   register const double *phip, *thetap;
   register double *xp, *yp;


   /* Initialize. */
   if (prj == 0x0) return 1;
   if (prj->flag != ZEA) {
      if (zeaset(prj)) return 2;
   }

   if (ntheta > 0) {
      mphi   = nphi;
      mtheta = ntheta;
   } else {
      mphi   = 1;
      mtheta = 1;
      ntheta = nphi;
   }


   /* Do phi dependence. */
   phip = phi;
   rowoff = 0;
   rowlen = nphi*sxy;
   for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
      sinphi = sind(*phip);
      cosphi = cosd(*phip);

      xp = x + rowoff;
      yp = y + rowoff;
      for (itheta = 0; itheta < mtheta; itheta++) {
         *xp = sinphi;
         *yp = cosphi;
         xp += rowlen;
         yp += rowlen;
      }
   }


   /* Do theta dependence. */
   thetap = theta;
   xp = x;
   yp = y;
   statp = stat;
   for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
      r =  prj->w[0]*sind((90.0 - *thetap)/2.0);
d2581 1
a2581 8
      for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
         *xp =  r*(*xp) - prj->x0;
         *yp = -r*(*yp) - prj->y0;
         *(statp++) = 0;
      }
   }

   return 0;
d2618 2
a2619 4
   const double tol = 1.0e-4;
   double cosxi;

   if (prj == 0x0) return 1;
d2621 1
a2621 2
   prj->flag = AIR;
   strcpy(prj->code, "AIR");
d2623 2
a2624 23
   if (undefined(prj->pv[1])) prj->pv[1] = 90.0;
   if (prj->r0 == 0.0) prj->r0 = R2D;

   strcpy(prj->name, "Airy's zenithal");
   prj->category  = ZENITHAL;
   prj->pvrange   = 101;
   prj->simplezen = 1;
   prj->equiareal = 0;
   prj->conformal = 0;
   prj->global    = 0;
   prj->divergent = 1;

   prj->w[0] = 2.0*prj->r0;
   if (prj->pv[1] == 90.0) {
      prj->w[1] = -0.5;
      prj->w[2] =  1.0;
   } else if (prj->pv[1] > -90.0) {
      cosxi = cosd((90.0 - prj->pv[1])/2.0);
      prj->w[1] = log(cosxi)*(cosxi*cosxi)/(1.0-cosxi*cosxi);
      prj->w[2] = 0.5 - prj->w[1];
   } else {
      return 2;
   }
d2626 28
a2653 4
   prj->w[3] = prj->w[0] * prj->w[2];
   prj->w[4] = tol;
   prj->w[5] = prj->w[2]*tol;
   prj->w[6] = R2D/prj->w[2];
d2655 2
a2656 2
   prj->prjx2s = airx2s;
   prj->prjs2x = airs2x;
d2658 1
a2658 1
   return prjoff(prj, 0.0, 90.0);
d2672 59
a2730 52
   int k, mx, my, rowlen, rowoff, status;
   double cosxi, lambda, r, r1, r2, rt, tanxi, x1, x2, xi, xj, yj, yj2;
   const double tol = 1.0e-12;
   register int ix, iy, *statp;
   register const double *xp, *yp;
   register double *phip, *thetap;


   /* Initialize. */
   if (prj == 0x0) return 1;
   if (prj->flag != AIR) {
      if (airset(prj)) return 2;
   }

   if (ny > 0) {
      mx = nx;
      my = ny;
   } else {
      mx = 1;
      my = 1;
      ny = nx;
   }

   status = 0;


   /* Do x dependence. */
   xp = x;
   rowoff = 0;
   rowlen = nx*spt;
   for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
      xj = *xp + prj->x0;

      phip = phi + rowoff;
      for (iy = 0; iy < my; iy++) {
         *phip = xj;
         phip += rowlen;
      }
   }


   /* Do y dependence. */
   yp = y;
   phip   = phi;
   thetap = theta;
   statp  = stat;
   for (iy = 0; iy < ny; iy++, yp += sxy) {
      yj  = *yp + prj->y0;
      yj2 = yj*yj;

      for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
         xj = *phip;
a2731 31
         r = sqrt(xj*xj + yj2)/prj->w[0];
         if (r == 0.0) {
            *phip = 0.0;
         } else {
            *phip = atan2d(xj, -yj);
         }


         if (r == 0.0) {
            xi = 0.0;
         } else if (r < prj->w[5]) {
            xi = r*prj->w[6];
         } else {
            /* Find a solution interval. */
            x1 = x2 = 1.0;
            r1 = r2 = 0.0;
            for (k = 0; k < 30; k++) {
               x2 = x1/2.0;
               tanxi = sqrt(1.0-x2*x2)/x2;
               r2 = -(log(x2)/tanxi + prj->w[1]*tanxi);

               if (r2 >= r) break;
               x1 = x2;
               r1 = r2;
            }
            if (k == 30) {
               *thetap = 0.0;
               *(statp++) = 1;
               status = 3;
               continue;
            }
d2733 61
a2793 37
            for (k = 0; k < 100; k++) {
               /* Weighted division of the interval. */
               lambda = (r2-r)/(r2-r1);
               if (lambda < 0.1) {
                  lambda = 0.1;
               } else if (lambda > 0.9) {
                  lambda = 0.9;
               }
               cosxi = x2 - lambda*(x2-x1);

               tanxi = sqrt(1.0-cosxi*cosxi)/cosxi;
               rt = -(log(cosxi)/tanxi + prj->w[1]*tanxi);

               if (rt < r) {
                  if (r-rt < tol) break;
                  r1 = rt;
                  x1 = cosxi;
               } else {
                  if (rt-r < tol) break;
                  r2 = rt;
                  x2 = cosxi;
               }
            }
            if (k == 100) {
               *thetap = 0.0;
               *(statp++) = 1;
               status = 3;
               continue;
            }

            xi = acosd(cosxi);
         }

         *thetap = 90.0 - 2.0*xi;
         *(statp++) = 0;
      }
   }
d2795 1
a2795 1
   return status;
d2809 50
a2858 51
   int mphi, mtheta, rowlen, rowoff, status;
   double cosphi, cosxi, r, tanxi, xi, sinphi;
   register int iphi, itheta, istat, *statp;
   register const double *phip, *thetap;
   register double *xp, *yp;


   /* Initialize. */
   if (prj == 0x0) return 1;
   if (prj->flag != AIR) {
      if (airset(prj)) return 2;
   }

   if (ntheta > 0) {
      mphi   = nphi;
      mtheta = ntheta;
   } else {
      mphi   = 1;
      mtheta = 1;
      ntheta = nphi;
   }

   status = 0;


   /* Do phi dependence. */
   phip = phi;
   rowoff = 0;
   rowlen = nphi*sxy;
   for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
      sinphi = sind(*phip);
      cosphi = cosd(*phip);

      xp = x + rowoff;
      yp = y + rowoff;
      for (itheta = 0; itheta < mtheta; itheta++) {
         *xp = sinphi;
         *yp = cosphi;
         xp += rowlen;
         yp += rowlen;
      }
   }


   /* Do theta dependence. */
   thetap = theta;
   xp = x;
   yp = y;
   statp = stat;
   for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
      istat = 0;
d2860 10
a2869 15
      if (*thetap == 90.0) {
         r = 0.0;
      } else if (*thetap > -90.0) {
         xi = D2R*(90.0 - *thetap)/2.0;
         if (xi < prj->w[4]) {
            r = xi*prj->w[3];
         } else {
            cosxi = cosd((90.0 - *thetap)/2.0);
            tanxi = sqrt(1.0-cosxi*cosxi)/cosxi;
            r = -prj->w[0]*(log(cosxi)/tanxi + prj->w[1]*tanxi);
         }
      } else {
         r = 0.0;
         istat  = 1;
         status = 4;
d2871 12
d2884 1
a2884 8
      for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
         *xp =  r*(*xp) - prj->x0;
         *yp = -r*(*yp) - prj->y0;
         *(statp++) = istat;
      }
   }

   return status;
d2919 1
a2919 1
   if (prj == 0x0) return 1;
d2921 2
a2922 2
   prj->flag = CYP;
   strcpy(prj->code, "CYP");
d2924 2
a2925 2
   if (undefined(prj->pv[1])) prj->pv[1] = 1.0;
   if (undefined(prj->pv[2])) prj->pv[2] = 1.0;
d2927 8
a2934 8
   strcpy(prj->name, "cylindrical perspective");
   prj->category  = CYLINDRICAL;
   prj->pvrange   = 102;
   prj->simplezen = 0;
   prj->equiareal = 0;
   prj->conformal = 0;
   prj->global    = prj->pv[1] < -1.0 || 0.0 < prj->pv[1];
   prj->divergent = !prj->global;
d2936 2
a2937 2
   if (prj->r0 == 0.0) {
      prj->r0 = R2D;
d2939 4
a2942 4
      prj->w[0] = prj->pv[2];
      if (prj->w[0] == 0.0) {
         return 2;
      }
d2944 1
a2944 1
      prj->w[1] = 1.0/prj->w[0];
d2946 4
a2949 4
      prj->w[2] = R2D*(prj->pv[1] + prj->pv[2]);
      if (prj->w[2] == 0.0) {
         return 2;
      }
d2951 6
a2956 6
      prj->w[3] = 1.0/prj->w[2];
   } else {
      prj->w[0] = prj->r0*prj->pv[2]*D2R;
      if (prj->w[0] == 0.0) {
         return 2;
      }
d2958 1
a2958 1
      prj->w[1] = 1.0/prj->w[0];
d2960 4
a2963 4
      prj->w[2] = prj->r0*(prj->pv[1] + prj->pv[2]);
      if (prj->w[2] == 0.0) {
         return 2;
      }
d2965 2
a2966 2
      prj->w[3] = 1.0/prj->w[2];
   }
d2968 2
a2969 2
   prj->prjx2s = cypx2s;
   prj->prjs2x = cyps2x;
d2971 1
a2971 1
   return prjoff(prj, 0.0, 0.0);
d2985 51
a3035 51
   int mx, my, rowlen, rowoff;
   double eta, s, t;
   register int ix, iy, *statp;
   register const double *xp, *yp;
   register double *phip, *thetap;


   /* Initialize. */
   if (prj == 0x0) return 1;
   if (prj->flag != CYP) {
      if (cypset(prj)) return 2;
   }

   if (ny > 0) {
      mx = nx;
      my = ny;
   } else {
      mx = 1;
      my = 1;
      ny = nx;
   }


   /* Do x dependence. */
   xp = x;
   rowoff = 0;
   rowlen = nx*spt;
   for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
      s = prj->w[1]*(*xp + prj->x0);

      phip = phi + rowoff;
      for (iy = 0; iy < my; iy++) {
         *phip = s;
         phip += rowlen;
      }
   }


   /* Do y dependence. */
   yp = y;
   thetap = theta;
   statp = stat;
   for (iy = 0; iy < ny; iy++, yp += sxy) {
      eta = prj->w[3]*(*yp + prj->y0);
      t = atan2d(eta,1.0) + asind(eta*prj->pv[1]/sqrt(eta*eta+1.0));

      for (ix = 0; ix < mx; ix++, thetap += spt) {
         *thetap = t;
         *(statp++) = 0;
      }
   }
d3037 1
a3037 1
   return 0;
d3051 62
a3112 62
   int mphi, mtheta, rowlen, rowoff, status;
   double eta, xi;
   register int iphi, itheta, istat, *statp;
   register const double *phip, *thetap;
   register double *xp, *yp;


   /* Initialize. */
   if (prj == 0x0) return 1;
   if (prj->flag != CYP) {
      if (cypset(prj)) return 2;
   }

   if (ntheta > 0) {
      mphi   = nphi;
      mtheta = ntheta;
   } else {
      mphi   = 1;
      mtheta = 1;
      ntheta = nphi;
   }

   status = 0;


   /* Do phi dependence. */
   phip = phi;
   rowoff = 0;
   rowlen = nphi*sxy;
   for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
      xi = prj->w[0]*(*phip) - prj->x0;

      xp = x + rowoff;
      for (itheta = 0; itheta < mtheta; itheta++) {
         *xp = xi;
         xp += rowlen;
      }
   }


   /* Do theta dependence. */
   thetap = theta;
   yp = y;
   statp = stat;
   for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
      eta = prj->pv[1] + cosd(*thetap);

      istat = 0;
      if (eta == 0.0) {
         istat  = 1;
         status = 4;

      } else {
         eta = prj->w[2]*sind(*thetap)/eta;
      }

      eta -= prj->y0;
      for (iphi = 0; iphi < mphi; iphi++, yp += sxy) {
         *yp = eta;
         *(statp++) = istat;
      }
   }
d3114 1
a3114 1
   return status;
d3147 1
a3147 1
   if (prj == 0x0) return 1;
d3149 2
a3150 2
   prj->flag = CEA;
   strcpy(prj->code, "CEA");
d3152 1
a3152 1
   if (undefined(prj->pv[1])) prj->pv[1] = 1.0;
d3154 27
a3180 27
   strcpy(prj->name, "cylindrical equal area");
   prj->category  = CYLINDRICAL;
   prj->pvrange   = 101;
   prj->simplezen = 0;
   prj->equiareal = 1;
   prj->conformal = 0;
   prj->global    = 1;
   prj->divergent = 0;

   if (prj->r0 == 0.0) {
      prj->r0 = R2D;
      prj->w[0] = 1.0;
      prj->w[1] = 1.0;
      if (prj->pv[1] <= 0.0 || prj->pv[1] > 1.0) {
         return 2;
      }
      prj->w[2] = prj->r0/prj->pv[1];
      prj->w[3] = prj->pv[1]/prj->r0;
   } else {
      prj->w[0] = prj->r0*D2R;
      prj->w[1] = R2D/prj->r0;
      if (prj->pv[1] <= 0.0 || prj->pv[1] > 1.0) {
         return 2;
      }
      prj->w[2] = prj->r0/prj->pv[1];
      prj->w[3] = prj->pv[1]/prj->r0;
   }
d3182 2
a3183 2
   prj->prjx2s = ceax2s;
   prj->prjs2x = ceas2x;
d3185 1
a3185 1
   return prjoff(prj, 0.0, 0.0);
d3199 54
a3252 57
   int mx, my, rowlen, rowoff, status;
   double s;
   const double tol = 1.0e-13;
   register int istat, ix, iy, *statp;
   register const double *xp, *yp;
   register double *phip, *thetap;


   /* Initialize. */
   if (prj == 0x0) return 1;
   if (prj->flag != CEA) {
      if (ceaset(prj)) return 2;
   }

   if (ny > 0) {
      mx = nx;
      my = ny;
   } else {
      mx = 1;
      my = 1;
      ny = nx;
   }

   status = 0;


   /* Do x dependence. */
   xp = x;
   rowoff = 0;
   rowlen = nx*spt;
   for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
      s = prj->w[1]*(*xp + prj->x0);

      phip = phi + rowoff;
      for (iy = 0; iy < my; iy++) {
         *phip = s;
         phip += rowlen;
      }
   }


   /* Do y dependence. */
   yp = y;
   thetap = theta;
   statp = stat;
   for (iy = 0; iy < ny; iy++, yp += sxy) {
      s = prj->w[3]*(*yp + prj->y0);

      istat = 0;
      if (fabs(s) > 1.0) {
         if (fabs(s) > 1.0+tol) {
            s = 0.0;
            istat  = 1;
            status = 3;
         } else {
            s = copysign(90.0, s);
         }
d3254 1
a3254 1
         s = asind(s);
d3256 9
d3266 1
a3266 7
      for (ix = 0; ix < mx; ix++, thetap += spt) {
         *thetap = s;
         *(statp++) = istat;
      }
   }

   return status;
d3280 50
a3329 50
   int mphi, mtheta, rowlen, rowoff;
   double eta, xi;
   register int iphi, itheta, *statp;
   register const double *phip, *thetap;
   register double *xp, *yp;


   /* Initialize. */
   if (prj == 0x0) return 1;
   if (prj->flag != CEA) {
      if (ceaset(prj)) return 2;
   }

   if (ntheta > 0) {
      mphi   = nphi;
      mtheta = ntheta;
   } else {
      mphi   = 1;
      mtheta = 1;
      ntheta = nphi;
   }


   /* Do phi dependence. */
   phip = phi;
   rowoff = 0;
   rowlen = nphi*sxy;
   for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
      xi = prj->w[0]*(*phip) - prj->x0;

      xp = x + rowoff;
      for (itheta = 0; itheta < mtheta; itheta++) {
         *xp = xi;
         xp += rowlen;
      }
   }


   /* Do theta dependence. */
   thetap = theta;
   yp = y;
   statp = stat;
   for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
      eta = prj->w[2]*sind(*thetap) - prj->y0;

      for (iphi = 0; iphi < mphi; iphi++, yp += sxy) {
         *yp = eta;
         *(statp++) = 0;
      }
   }
d3331 1
a3331 1
   return 0;
d3358 1
a3358 1
   if (prj == 0x0) return 1;
d3360 2
a3361 2
   prj->flag = CAR;
   strcpy(prj->code, "CAR");
d3363 17
a3379 17
   strcpy(prj->name, "plate caree");
   prj->category  = CYLINDRICAL;
   prj->pvrange   = 0;
   prj->simplezen = 0;
   prj->equiareal = 0;
   prj->conformal = 0;
   prj->global    = 1;
   prj->divergent = 0;

   if (prj->r0 == 0.0) {
      prj->r0 = R2D;
      prj->w[0] = 1.0;
      prj->w[1] = 1.0;
   } else {
      prj->w[0] = prj->r0*D2R;
      prj->w[1] = 1.0/prj->w[0];
   }
d3381 2
a3382 2
   prj->prjx2s = carx2s;
   prj->prjs2x = cars2x;
d3384 1
a3384 1
   return prjoff(prj, 0.0, 0.0);
d3398 50
a3447 50
   int mx, my, rowlen, rowoff;
   double s, t;
   register int ix, iy, *statp;
   register const double *xp, *yp;
   register double *phip, *thetap;


   /* Initialize. */
   if (prj == 0x0) return 1;
   if (prj->flag != CAR) {
      if (carset(prj)) return 2;
   }

   if (ny > 0) {
      mx = nx;
      my = ny;
   } else {
      mx = 1;
      my = 1;
      ny = nx;
   }


   /* Do x dependence. */
   xp = x;
   rowoff = 0;
   rowlen = nx*spt;
   for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
      s = prj->w[1]*(*xp + prj->x0);

      phip = phi + rowoff;
      for (iy = 0; iy < my; iy++) {
         *phip = s;
         phip += rowlen;
      }
   }


   /* Do y dependence. */
   yp = y;
   thetap = theta;
   statp = stat;
   for (iy = 0; iy < ny; iy++, yp += sxy) {
      t = prj->w[1]*(*yp + prj->y0);

      for (ix = 0; ix < mx; ix++, thetap += spt) {
         *thetap = t;
         *(statp++) = 0;
      }
   }
d3449 1
a3449 1
   return 0;
d3463 50
a3512 50
   int mphi, mtheta, rowlen, rowoff;
   double eta, xi;
   register int iphi, itheta, *statp;
   register const double *phip, *thetap;
   register double *xp, *yp;


   /* Initialize. */
   if (prj == 0x0) return 1;
   if (prj->flag != CAR) {
      if (carset(prj)) return 2;
   }

   if (ntheta > 0) {
      mphi   = nphi;
      mtheta = ntheta;
   } else {
      mphi   = 1;
      mtheta = 1;
      ntheta = nphi;
   }


   /* Do phi dependence. */
   phip = phi;
   rowoff = 0;
   rowlen = nphi*sxy;
   for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
      xi = prj->w[0]*(*phip) - prj->x0;

      xp = x + rowoff;
      for (itheta = 0; itheta < mtheta; itheta++) {
         *xp = xi;
         xp += rowlen;
      }
   }


   /* Do theta dependence. */
   thetap = theta;
   yp = y;
   statp = stat;
   for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
      eta = prj->w[0]*(*thetap) - prj->y0;

      for (iphi = 0; iphi < mphi; iphi++, yp += sxy) {
         *yp = eta;
         *(statp++) = 0;
      }
   }
d3514 1
a3514 1
   return 0;
d3541 1
a3541 1
   if (prj == 0x0) return 1;
d3543 2
a3544 2
   prj->flag = MER;
   strcpy(prj->code, "MER");
d3546 17
a3562 17
   strcpy(prj->name, "Mercator's");
   prj->category  = CYLINDRICAL;
   prj->pvrange   = 0;
   prj->simplezen = 0;
   prj->equiareal = 0;
   prj->conformal = 1;
   prj->global    = 0;
   prj->divergent = 1;

   if (prj->r0 == 0.0) {
      prj->r0 = R2D;
      prj->w[0] = 1.0;
      prj->w[1] = 1.0;
   } else {
      prj->w[0] = prj->r0*D2R;
      prj->w[1] = 1.0/prj->w[0];
   }
d3564 2
a3565 2
   prj->prjx2s = merx2s;
   prj->prjs2x = mers2x;
d3567 1
a3567 1
   return prjoff(prj, 0.0, 0.0);
d3581 50
a3630 50
   int mx, my, rowlen, rowoff;
   double s, t;
   register int ix, iy, *statp;
   register const double *xp, *yp;
   register double *phip, *thetap;


   /* Initialize. */
   if (prj == 0x0) return 1;
   if (prj->flag != MER) {
      if (merset(prj)) return 2;
   }

   if (ny > 0) {
      mx = nx;
      my = ny;
   } else {
      mx = 1;
      my = 1;
      ny = nx;
   }


   /* Do x dependence. */
   xp = x;
   rowoff = 0;
   rowlen = nx*spt;
   for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
      s = prj->w[1]*(*xp + prj->x0);

      phip = phi + rowoff;
      for (iy = 0; iy < my; iy++) {
         *phip = s;
         phip += rowlen;
      }
   }


   /* Do y dependence. */
   yp = y;
   thetap = theta;
   statp  = stat;
   for (iy = 0; iy < ny; iy++, yp += sxy) {
      t = 2.0*atand(exp((*yp + prj->y0)/prj->r0)) - 90.0;

      for (ix = 0; ix < mx; ix++, thetap += spt) {
         *thetap = t;
         *(statp++) = 0;
      }
   }
d3632 1
a3632 1
   return 0;
d3646 60
a3705 60
   int mphi, mtheta, rowlen, rowoff, status;
   double eta, xi;
   register int iphi, itheta, istat, *statp;
   register const double *phip, *thetap;
   register double *xp, *yp;


   /* Initialize. */
   if (prj == 0x0) return 1;
   if (prj->flag != MER) {
      if (merset(prj)) return 2;
   }

   if (ntheta > 0) {
      mphi   = nphi;
      mtheta = ntheta;
   } else {
      mphi   = 1;
      mtheta = 1;
      ntheta = nphi;
   }

   status = 0;


   /* Do phi dependence. */
   phip = phi;
   rowoff = 0;
   rowlen = nphi*sxy;
   for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
      xi  = prj->w[0]*(*phip) - prj->x0;

      xp = x + rowoff;
      for (itheta = 0; itheta < mtheta; itheta++) {
         *xp = xi;
         xp += rowlen;
      }
   }


   /* Do theta dependence. */
   thetap = theta;
   yp = y;
   statp = stat;
   for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
      istat = 0;

      if (*thetap <= -90.0 || *thetap >= 90.0) {
         eta = 0.0;
         istat  = 1;
         status = 4;
      } else {
         eta = prj->r0*log(tand((*thetap+90.0)/2.0)) - prj->y0;
      }

      for (iphi = 0; iphi < mphi; iphi++, yp += sxy) {
         *yp = eta;
         *(statp++) = istat;
      }
   }
d3707 1
a3707 1
   return status;
d3734 1
a3734 1
   if (prj == 0x0) return 1;
d3736 2
a3737 2
   prj->flag = SFL;
   strcpy(prj->code, "SFL");
d3739 17
a3755 17
   strcpy(prj->name, "Sanson-Flamsteed");
   prj->category  = PSEUDOCYLINDRICAL;
   prj->pvrange   = 0;
   prj->simplezen = 0;
   prj->equiareal = 1;
   prj->conformal = 0;
   prj->global    = 1;
   prj->divergent = 0;

   if (prj->r0 == 0.0) {
      prj->r0 = R2D;
      prj->w[0] = 1.0;
      prj->w[1] = 1.0;
   } else {
      prj->w[0] = prj->r0*D2R;
      prj->w[1] = 1.0/prj->w[0];
   }
d3757 2
a3758 2
   prj->prjx2s = sflx2s;
   prj->prjs2x = sfls2x;
d3760 1
a3760 1
   return prjoff(prj, 0.0, 0.0);
d3774 63
a3836 63
   int mx, my, rowlen, rowoff, status;
   double s, t, yj;
   register int istat, ix, iy, *statp;
   register const double *xp, *yp;
   register double *phip, *thetap;


   /* Initialize. */
   if (prj == 0x0) return 1;
   if (prj->flag != SFL) {
      if (sflset(prj)) return 2;
   }

   if (ny > 0) {
      mx = nx;
      my = ny;
   } else {
      mx = 1;
      my = 1;
      ny = nx;
   }


   /* Do x dependence. */
   xp = x;
   rowoff = 0;
   rowlen = nx*spt;
   for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
      s = prj->w[1]*(*xp + prj->x0);

      phip = phi + rowoff;
      for (iy = 0; iy < my; iy++) {
         *phip = s;
         phip += rowlen;
      }
   }


   /* Do y dependence. */
   yp = y;
   phip   = phi;
   thetap = theta;
   statp  = stat;
   for (iy = 0; iy < ny; iy++, yp += sxy) {
      yj = *yp + prj->y0;
      s = cos(yj/prj->r0);

      istat = 0;
      if (s == 0.0) {
         istat  = 1;
         status = 3;
      } else {
         s = 1.0/s;
      }

      t = prj->w[1]*yj;

      for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
         *phip  *= s;
         *thetap = t;
         *(statp++) = 0;
      }
   }
d3838 1
a3838 1
   return 0;
d3852 53
a3904 53
   int mphi, mtheta, rowlen, rowoff;
   double eta, xi;
   register int iphi, itheta, *statp;
   register const double *phip, *thetap;
   register double *xp, *yp;


   /* Initialize. */
   if (prj == 0x0) return 1;
   if (prj->flag != SFL) {
      if (sflset(prj)) return 2;
   }

   if (ntheta > 0) {
      mphi   = nphi;
      mtheta = ntheta;
   } else {
      mphi   = 1;
      mtheta = 1;
      ntheta = nphi;
   }


   /* Do phi dependence. */
   phip = phi;
   rowoff = 0;
   rowlen = nphi*sxy;
   for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
      xi = prj->w[0]*(*phip);

      xp = x + rowoff;
      for (itheta = 0; itheta < mtheta; itheta++) {
         *xp = xi;
         xp += rowlen;
      }
   }


   /* Do theta dependence. */
   thetap = theta;
   xp = x;
   yp = y;
   statp = stat;
   for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
      xi  = cosd(*thetap);
      eta = prj->w[0]*(*thetap) - prj->y0;

      for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
         *xp = xi*(*xp) - prj->x0;
         *yp = eta;
         *(statp++) = 0;
      }
   }
d3906 1
a3906 1
   return 0;
d3935 1
a3935 1
   if (prj == 0x0) return 1;
d3937 2
a3938 2
   prj->flag = PAR;
   strcpy(prj->code, "PAR");
d3940 21
a3960 21
   strcpy(prj->name, "parabolic");
   prj->category  = PSEUDOCYLINDRICAL;
   prj->pvrange   = 0;
   prj->simplezen = 0;
   prj->equiareal = 1;
   prj->conformal = 0;
   prj->global    = 1;
   prj->divergent = 0;

   if (prj->r0 == 0.0) {
      prj->r0 = R2D;
      prj->w[0] = 1.0;
      prj->w[1] = 1.0;
      prj->w[2] = 180.0;
      prj->w[3] = 1.0/prj->w[2];
   } else {
      prj->w[0] = prj->r0*D2R;
      prj->w[1] = 1.0/prj->w[0];
      prj->w[2] = PI*prj->r0;
      prj->w[3] = 1.0/prj->w[2];
   }
d3962 2
a3963 2
   prj->prjx2s = parx2s;
   prj->prjs2x = pars2x;
d3965 1
a3965 1
   return prjoff(prj, 0.0, 0.0);
d3979 60
a4038 53
   int mx, my, rowlen, rowoff, status;
   double r, s, t, xj;
   const double tol = 1.0e-13;
   register int istat, ix, iy, *statp;
   register const double *xp, *yp;
   register double *phip, *thetap;


   /* Initialize. */
   if (prj == 0x0) return 1;
   if (prj->flag != PAR) {
      if (parset(prj)) return 2;
   }

   if (ny > 0) {
      mx = nx;
      my = ny;
   } else {
      mx = 1;
      my = 1;
      ny = nx;
   }

   status = 0;


   /* Do x dependence. */
   xp = x;
   rowoff = 0;
   rowlen = nx*spt;
   for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
      xj = *xp + prj->x0;
      s = prj->w[1]*xj;
      t = fabs(xj) - tol;

      phip   = phi   + rowoff;
      thetap = theta + rowoff;
      for (iy = 0; iy < my; iy++) {
         *phip   = s;
         *thetap = t;
         phip   += rowlen;
         thetap += rowlen;
      }
   }


   /* Do y dependence. */
   yp = y;
   phip   = phi;
   thetap = theta;
   statp  = stat;
   for (iy = 0; iy < ny; iy++, yp += sxy) {
      r = prj->w[3]*(*yp + prj->y0);
d4040 7
a4046 17
      istat = 0;
      if (r > 1.0 || r < -1.0) {
         s = 0.0;
         t = 0.0;
         istat  = 1;
         status = 3;

      } else {
         s = 1.0 - 4.0*r*r;
         if (s == 0.0) {
            /* Deferred test. */
            istat = -1;
         } else {
            s = 1.0/s;
         }

         t = 3.0*asind(r);
d4049 2
a4050 9
      for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
         if (istat < 0) {
            if (*thetap < 0.0) {
               *(statp++) = 0;
            } else {
               *(statp++) = 1;
               status = 3;
            }
         }
d4052 8
a4059 2
         *phip  *= s;
         *thetap = t;
a4060 1
   }
d4062 6
a4067 1
   return status;
d4081 54
a4134 47
   int mphi, mtheta, rowlen, rowoff;
   double eta, s, xi;
   register int iphi, itheta, *statp;
   register const double *phip, *thetap;
   register double *xp, *yp;


   /* Initialize. */
   if (prj == 0x0) return 1;
   if (prj->flag != PAR) {
      if (parset(prj)) return 2;
   }

   if (ntheta > 0) {
      mphi   = nphi;
      mtheta = ntheta;
   } else {
      mphi   = 1;
      mtheta = 1;
      ntheta = nphi;
   }


   /* Do phi dependence. */
   phip = phi;
   rowoff = 0;
   rowlen = nphi*sxy;
   for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
      xi = prj->w[0]*(*phip);

      xp = x + rowoff;
      for (itheta = 0; itheta < mtheta; itheta++) {
         *xp = xi;
         xp += rowlen;
      }
   }


   /* Do theta dependence. */
   thetap = theta;
   xp = x;
   yp = y;
   statp = stat;
   for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
      s = sind((*thetap)/3.0);
      xi = (1.0 - 4.0*s*s);
      eta = prj->w[2]*s - prj->y0;
d4136 1
a4136 8
      for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
         *xp = xi*(*xp) - prj->x0;
         *yp = eta;
         *(statp++) = 0;
      }
   }

   return 0;
d4165 1
a4165 1
   if (prj == 0x0) return 1;
d4167 2
a4168 2
   prj->flag = MOL;
   strcpy(prj->code, "MOL");
d4170 1
a4170 1
   if (prj->r0 == 0.0) prj->r0 = R2D;
d4172 14
a4185 14
   strcpy(prj->name, "Mollweide's");
   prj->category  = PSEUDOCYLINDRICAL;
   prj->pvrange   = 0;
   prj->simplezen = 0;
   prj->equiareal = 1;
   prj->conformal = 0;
   prj->global    = 1;
   prj->divergent = 0;

   prj->w[0] = SQRT2*prj->r0;
   prj->w[1] = prj->w[0]/90.0;
   prj->w[2] = 1.0/prj->w[0];
   prj->w[3] = 90.0/prj->r0;
   prj->w[4] = 2.0/PI;
d4187 2
a4188 2
   prj->prjx2s = molx2s;
   prj->prjs2x = mols2x;
d4190 1
a4190 1
   return prjoff(prj, 0.0, 0.0);
d4204 65
a4268 55
   int mx, my, rowlen, rowoff, status;
   double r, s, t, xj, y0, yj, z;
   const double tol = 1.0e-12;
   register int istat, ix, iy, *statp;
   register const double *xp, *yp;
   register double *phip, *thetap;


   /* Initialize. */
   if (prj == 0x0) return 1;
   if (prj->flag != MOL) {
      if (molset(prj)) return 2;
   }

   if (ny > 0) {
      mx = nx;
      my = ny;
   } else {
      mx = 1;
      my = 1;
      ny = nx;
   }

   status = 0;


   /* Do x dependence. */
   xp = x;
   rowoff = 0;
   rowlen = nx*spt;
   for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
      xj = *xp + prj->x0;
      s = prj->w[3]*xj;
      t = fabs(xj) - tol;

      phip   = phi   + rowoff;
      thetap = theta + rowoff;
      for (iy = 0; iy < my; iy++) {
         *phip   = s;
         *thetap = t;
         phip   += rowlen;
         thetap += rowlen;
      }
   }


   /* Do y dependence. */
   yp = y;
   phip   = phi;
   thetap = theta;
   statp  = stat;
   for (iy = 0; iy < ny; iy++, yp += sxy) {
      yj = *yp + prj->y0;
      y0 = yj/prj->r0;
      r  = 2.0 - y0*y0;
d4270 2
a4271 12
      istat = 0;
      if (r <= tol) {
         if (r < -tol) {
            istat  = 1;
            status = 3;
         } else {
            /* OK if fabs(x) < tol whence phi = 0.0. */
            istat = -1;
         }

         r = 0.0;
         s = 0.0;
d4273 11
d4285 1
a4285 2
         r = sqrt(r);
         s = 1.0/r;
d4287 9
a4295 10

      z = yj*prj->w[2];
      if (fabs(z) > 1.0) {
         if (fabs(z) > 1.0+tol) {
            z = 0.0;
            istat  = 1;
            status = 3;
         } else {
            z = copysign(1.0, z) + y0*r/PI;
         }
d4297 1
a4297 1
         z = asin(z)*prj->w[4] + y0*r/PI;
d4299 3
d4303 8
a4310 8
      if (fabs(z) > 1.0) {
         if (fabs(z) > 1.0+tol) {
            z = 0.0;
            istat  = 1;
            status = 3;
         } else {
            z = copysign(1.0, z);
         }
d4313 4
a4316 1
      t = asind(z);
d4318 1
a4318 16
      for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
         if (istat < 0) {
            if (*thetap < 0.0) {
               *(statp++) = 0;
            } else {
               *(statp++) = 1;
               status = 3;
            }
         }

         *phip  *= s;
         *thetap = t;
      }
   }

   return status;
d4332 80
a4411 72
   int k, mphi, mtheta, rowlen, rowoff;
   double eta, gamma, resid, u, v, v0, v1, xi;
   const double tol = 1.0e-13;
   register int iphi, itheta, *statp;
   register const double *phip, *thetap;
   register double *xp, *yp;


   /* Initialize. */
   if (prj == 0x0) return 1;
   if (prj->flag != MOL) {
      if (molset(prj)) return 2;
   }

   if (ntheta > 0) {
      mphi   = nphi;
      mtheta = ntheta;
   } else {
      mphi   = 1;
      mtheta = 1;
      ntheta = nphi;
   }


   /* Do phi dependence. */
   phip = phi;
   rowoff = 0;
   rowlen = nphi*sxy;
   for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
      xi = prj->w[1]*(*phip);

      xp = x + rowoff;
      for (itheta = 0; itheta < mtheta; itheta++) {
         *xp = xi;
         xp += rowlen;
      }
   }


   /* Do theta dependence. */
   thetap = theta;
   xp = x;
   yp = y;
   statp = stat;
   for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
      if (fabs(*thetap) == 90.0) {
         xi  = 0.0;
         eta = copysign(prj->w[0], *thetap);
      } else if (*thetap == 0.0) {
         xi  = 1.0;
         eta = 0.0;
      } else {
         u  = PI*sind(*thetap);
         v0 = -PI;
         v1 =  PI;
         v  = u;
         for (k = 0; k < 100; k++) {
            resid = (v - u) + sin(v);
            if (resid < 0.0) {
               if (resid > -tol) break;
               v0 = v;
            } else {
               if (resid < tol) break;
               v1 = v;
            }
            v = (v0 + v1)/2.0;
         }

         gamma = v/2.0;
         xi  = cos(gamma);
         eta = prj->w[0]*sin(gamma);
      }
d4413 1
a4413 9
      eta -= prj->y0;
      for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
         *xp = xi*(*xp) - prj->x0;
         *yp = eta;
         *(statp++) = 0;
      }
   }

   return 0;
d4442 1
a4442 1
   if (prj == 0x0) return 1;
d4444 2
a4445 2
   prj->flag = AIT;
   strcpy(prj->code, "AIT");
d4447 1
a4447 1
   if (prj->r0 == 0.0) prj->r0 = R2D;
d4449 13
a4461 13
   strcpy(prj->name, "Hammer-Aitoff");
   prj->category  = CONVENTIONAL;
   prj->pvrange   = 0;
   prj->simplezen = 0;
   prj->equiareal = 1;
   prj->conformal = 0;
   prj->global    = 1;
   prj->divergent = 0;

   prj->w[0] = 2.0*prj->r0*prj->r0;
   prj->w[1] = 1.0/(2.0*prj->w[0]);
   prj->w[2] = prj->w[1]/4.0;
   prj->w[3] = 1.0/(2.0*prj->r0);
d4463 2
a4464 2
   prj->prjx2s = aitx2s;
   prj->prjs2x = aits2x;
d4466 1
a4466 1
   return prjoff(prj, 0.0, 0.0);
d4480 54
a4533 54
   int mx, my, rowlen, rowoff, status;
   double s, t, x0, xj, y0, yj, yj2, z;
   const double tol = 1.0e-13;
   register int ix, iy, istat, *statp;
   register const double *xp, *yp;
   register double *phip, *thetap;


   /* Initialize. */
   if (prj == 0x0) return 1;
   if (prj->flag != AIT) {
      if (aitset(prj)) return 2;
   }

   if (ny > 0) {
      mx = nx;
      my = ny;
   } else {
      mx = 1;
      my = 1;
      ny = nx;
   }

   status = 0;


   /* Do x dependence. */
   xp = x;
   rowoff = 0;
   rowlen = nx*spt;
   for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
      xj = *xp + prj->x0;
      s  = 1.0 - xj*xj*prj->w[2];
      t  = xj*prj->w[3];

      phip   = phi   + rowoff;
      thetap = theta + rowoff;
      for (iy = 0; iy < my; iy++) {
         *phip   = s;
         *thetap = t;
         phip   += rowlen;
         thetap += rowlen;
      }
   }


   /* Do y dependence. */
   yp = y;
   phip   = phi;
   thetap = theta;
   statp  = stat;
   for (iy = 0; iy < ny; iy++, yp += sxy) {
      yj  = *yp + prj->y0;
      yj2 = yj*yj*prj->w[1];
d4535 2
a4536 2
      for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
         s = *phip - yj2;
d4538 9
a4546 6
         istat = 0;
         if (s < 0.5) {
            if (s < 0.5-tol) {
               istat  = 1;
               status = 3;
            }
d4548 8
a4555 2
            s = 0.5;
         }
d4557 7
a4563 16
         z = sqrt(s);
         x0 = 2.0*z*z - 1.0;
         y0 = z*(*thetap);
         if (x0 == 0.0 && y0 == 0.0) {
            *phip = 0.0;
         } else {
            *phip = 2.0*atan2d(y0, x0);
         }

         t = z*yj/prj->r0;
         if (fabs(t) > 1.0) {
            if (fabs(t) > 1.0+tol) {
               istat  = 1;
               status = 3;
            }
            t = copysign(90.0, t);
d4565 3
a4567 3
         } else {
            t = asind(t);
         }
d4569 4
a4572 4
         *thetap = t;
         *(statp++) = istat;
      }
   }
d4574 1
a4574 1
   return status;
d4588 57
a4644 51
   int mphi, mtheta, rowlen, rowoff;
   double cosphi, costhe, sinphi, sinthe, w;
   register int iphi, itheta, *statp;
   register const double *phip, *thetap;
   register double *xp, *yp;


   /* Initialize. */
   if (prj == 0x0) return 1;
   if (prj->flag != AIT) {
      if (aitset(prj)) return 2;
   }

   if (ntheta > 0) {
      mphi   = nphi;
      mtheta = ntheta;
   } else {
      mphi   = 1;
      mtheta = 1;
      ntheta = nphi;
   }


   /* Do phi dependence. */
   phip = phi;
   rowoff = 0;
   rowlen = nphi*sxy;
   for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
      w = (*phip)/2.0;
      sinphi = sind(w);
      cosphi = cosd(w);

      xp = x + rowoff;
      yp = y + rowoff;
      for (itheta = 0; itheta < mtheta; itheta++) {
         *xp = sinphi;
         *yp = cosphi;
         xp += rowlen;
         yp += rowlen;
      }
   }


   /* Do theta dependence. */
   thetap = theta;
   xp = x;
   yp = y;
   statp = stat;
   for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
      costhe = cosd(*thetap);
      sinthe = sind(*thetap);
d4646 1
a4646 9
      for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
         w = sqrt(prj->w[0]/(1.0 + costhe*(*yp)));
         *xp = 2.0*w*costhe*(*xp) - prj->x0;
         *yp = w*sinthe - prj->y0;
         *(statp++) = 0;
      }
   }

   return 0;
d4682 1
a4682 19
   if (prj == 0x0) return 1;

   prj->flag = COP;
   strcpy(prj->code, "COP");

   if (undefined(prj->pv[1])) {
      return 2;
   }
   if (undefined(prj->pv[2])) prj->pv[2] = 0.0;
   if (prj->r0 == 0.0) prj->r0 = R2D;

   strcpy(prj->name, "conic perspective");
   prj->category  = CONIC;
   prj->pvrange   = 102;
   prj->simplezen = 0;
   prj->equiareal = 0;
   prj->conformal = 0;
   prj->global    = 0;
   prj->divergent = 1;
d4684 2
a4685 11
   prj->w[0] = sind(prj->pv[1]);
   if (prj->w[0] == 0.0) {
      return 2;
   }

   prj->w[1] = 1.0/prj->w[0];

   prj->w[3] = prj->r0*cosd(prj->pv[2]);
   if (prj->w[3] == 0.0) {
      return 2;
   }
d4687 29
a4715 2
   prj->w[4] = 1.0/prj->w[3];
   prj->w[5] = 1.0/tand(prj->pv[1]);
d4717 1
a4717 1
   prj->w[2] = prj->w[3]*prj->w[5];
d4719 2
a4720 2
   prj->prjx2s = copx2s;
   prj->prjs2x = cops2x;
d4722 1
a4722 1
   return prjoff(prj, 0.0, prj->pv[1]);
d4736 45
a4780 45
   int mx, my, rowlen, rowoff;
   double alpha, dy, dy2, r, xj;
   register int ix, iy, *statp;
   register const double *xp, *yp;
   register double *phip, *thetap;

   /* Initialize. */
   if (prj == 0x0) return 1;
   if (prj->flag != COP) {
      if (copset(prj)) return 2;
   }

   if (ny > 0) {
      mx = nx;
      my = ny;
   } else {
      mx = 1;
      my = 1;
      ny = nx;
   }


   /* Do x dependence. */
   xp = x;
   rowoff = 0;
   rowlen = nx*spt;
   for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
      xj = *xp + prj->x0;

      phip = phi + rowoff;
      for (iy = 0; iy < my; iy++) {
         *phip = xj;
         phip += rowlen;
      }
   }


   /* Do y dependence. */
   yp = y;
   phip   = phi;
   thetap = theta;
   statp  = stat;
   for (iy = 0; iy < ny; iy++, yp += sxy) {
      dy  = prj->w[2] - (*yp + prj->y0);
      dy2 = dy*dy;
d4782 2
a4783 2
      for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
         xj = *phip;
d4785 2
a4786 2
         r = sqrt(xj*xj + dy2);
         if (prj->pv[1] < 0.0) r = -r;
d4788 5
a4792 5
         if (r == 0.0) {
            alpha = 0.0;
         } else {
            alpha = atan2d(xj/r, dy/r);
         }
d4794 5
a4798 5
         *phip = alpha*prj->w[1];
         *thetap = prj->pv[1] + atand(prj->w[5] - r*prj->w[4]);
         *(statp++) = 0;
      }
   }
d4800 1
a4800 1
   return 0;
d4814 52
a4865 53
   int mphi, mtheta, rowlen, rowoff, status;
   double alpha, cosalpha, r, s, t, sinalpha, y0;
   register int iphi, itheta, istat, *statp;
   register const double *phip, *thetap;
   register double *xp, *yp;

   /* Initialize. */
   if (prj == 0x0) return 1;
   if (prj->flag != COP) {
      if (copset(prj)) return 2;
   }

   if (ntheta > 0) {
      mphi   = nphi;
      mtheta = ntheta;
   } else {
      mphi   = 1;
      mtheta = 1;
      ntheta = nphi;
   }

   status = 0;


   /* Do phi dependence. */
   phip = phi;
   rowoff = 0;
   rowlen = nphi*sxy;
   for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
      alpha = prj->w[0]*(*phip);
      sinalpha = sind(alpha);
      cosalpha = cosd(alpha);

      xp = x + rowoff;
      yp = y + rowoff;
      for (itheta = 0; itheta < mtheta; itheta++) {
         *xp = sinalpha;
         *yp = cosalpha;
         xp += rowlen;
         yp += rowlen;
      }
   }


   /* Do theta dependence. */
   thetap = theta;
   xp = x;
   yp = y;
   statp = stat;
   y0 = prj->y0 - prj->w[2];
   for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
      t = *thetap - prj->pv[1];
      s = cosd(t);
d4867 5
a4871 5
      istat = 0;
      if (s == 0.0) {
         r = 0.0;
         istat  = 1;
         status = 4;
d4873 2
a4874 2
      } else {
         r = prj->w[2] - prj->w[3]*sind(t)/s;
d4876 12
a4887 12
         if (prj->bounds && r*prj->w[0] < 0.0) {
            istat  = 1;
            status = 4;
         }
      }

      for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
         *xp =  r*(*xp) - prj->x0;
         *yp = -r*(*yp) - y0;
         *(statp++) = istat;
      }
   }
d4889 1
a4889 1
   return status;
d4928 1
a4928 24
   double theta1, theta2;

   if (prj == 0x0) return 1;

   prj->flag = COE;
   strcpy(prj->code, "COE");

   if (undefined(prj->pv[1])) {
      return 2;
   }
   if (undefined(prj->pv[2])) prj->pv[2] = 0.0;
   if (prj->r0 == 0.0) prj->r0 = R2D;

   strcpy(prj->name, "conic equal area");
   prj->category  = CONIC;
   prj->pvrange   = 102;
   prj->simplezen = 0;
   prj->equiareal = 1;
   prj->conformal = 0;
   prj->global    = 1;
   prj->divergent = 0;

   theta1 = prj->pv[1] - prj->pv[2];
   theta2 = prj->pv[1] + prj->pv[2];
d4930 1
a4930 4
   prj->w[0] = (sind(theta1) + sind(theta2))/2.0;
   if (prj->w[0] == 0.0) {
      return 2;
   }
d4932 2
a4933 1
   prj->w[1] = 1.0/prj->w[0];
d4935 31
a4965 6
   prj->w[3] = prj->r0/prj->w[0];
   prj->w[4] = 1.0 + sind(theta1)*sind(theta2);
   prj->w[5] = 2.0*prj->w[0];
   prj->w[6] = prj->w[3]*prj->w[3]*prj->w[4];
   prj->w[7] = 1.0/(2.0*prj->r0*prj->w[3]);
   prj->w[8] = prj->w[3]*sqrt(prj->w[4] + prj->w[5]);
d4967 1
a4967 1
   prj->w[2] = prj->w[3]*sqrt(prj->w[4] - prj->w[5]*sind(prj->pv[1]));
d4969 2
a4970 2
   prj->prjx2s = coex2s;
   prj->prjs2x = coes2x;
d4972 1
a4972 1
   return prjoff(prj, 0.0, prj->pv[1]);
d4986 48
a5033 48
   int mx, my, rowlen, rowoff, status;
   double alpha, dy, dy2, r, t, w, xj;
   const double tol = 1.0e-12;
   register int ix, iy, istat, *statp;
   register const double *xp, *yp;
   register double *phip, *thetap;

   /* Initialize. */
   if (prj == 0x0) return 1;
   if (prj->flag != COE) {
      if (coeset(prj)) return 2;
   }

   if (ny > 0) {
      mx = nx;
      my = ny;
   } else {
      mx = 1;
      my = 1;
      ny = nx;
   }

   status = 0;


   /* Do x dependence. */
   xp = x;
   rowoff = 0;
   rowlen = nx*spt;
   for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
      xj = *xp + prj->x0;

      phip = phi + rowoff;
      for (iy = 0; iy < my; iy++) {
         *phip = xj;
         phip += rowlen;
      }
   }


   /* Do y dependence. */
   yp = y;
   phip   = phi;
   thetap = theta;
   statp  = stat;
   for (iy = 0; iy < ny; iy++, yp += sxy) {
      dy  = prj->w[2] - (*yp + prj->y0);
      dy2 = dy*dy;
d5035 2
a5036 2
      for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
         xj = *phip;
d5038 2
a5039 2
         r = sqrt(xj*xj + dy2);
         if (prj->pv[1] < 0.0) r = -r;
d5041 5
a5045 5
         if (r == 0.0) {
            alpha = 0.0;
         } else {
            alpha = atan2d(xj/r, dy/r);
         }
d5047 9
a5055 2
         istat = 0;
         if (fabs(r - prj->w[8]) < tol) {
d5057 9
a5065 16
         } else {
            w = (prj->w[6] - r*r)*prj->w[7];
            if (fabs(w) > 1.0) {
               if (fabs(w-1.0) < tol) {
                  t = 90.0;
               } else if (fabs(w+1.0) < tol) {
                  t = -90.0;
               } else {
                  t = 0.0;
                  istat  = 1;
                  status = 3;
               }
            } else {
               t = asind(w);
            }
         }
d5067 5
a5071 5
         *phip = alpha*prj->w[1];
         *thetap = t;
         *(statp++) = istat;
      }
   }
d5073 1
a5073 1
   return status;
d5087 60
a5146 54
   int mphi, mtheta, rowlen, rowoff;
   double alpha, cosalpha, r, sinalpha, y0;
   register int iphi, itheta, *statp;
   register const double *phip, *thetap;
   register double *xp, *yp;

   /* Initialize. */
   if (prj == 0x0) return 1;
   if (prj->flag != COE) {
      if (coeset(prj)) return 2;
   }

   if (ntheta > 0) {
      mphi   = nphi;
      mtheta = ntheta;
   } else {
      mphi   = 1;
      mtheta = 1;
      ntheta = nphi;
   }


   /* Do phi dependence. */
   phip = phi;
   rowoff = 0;
   rowlen = nphi*sxy;
   for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
      alpha = prj->w[0]*(*phip);
      sinalpha = sind(alpha);
      cosalpha = cosd(alpha);

      xp = x + rowoff;
      yp = y + rowoff;
      for (itheta = 0; itheta < mtheta; itheta++) {
         *xp = sinalpha;
         *yp = cosalpha;
         xp += rowlen;
         yp += rowlen;
      }
   }


   /* Do theta dependence. */
   thetap = theta;
   xp = x;
   yp = y;
   statp = stat;
   y0 = prj->y0 - prj->w[2];
   for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
      if (*thetap == -90.0) {
         r = prj->w[8];
      } else {
         r = prj->w[3]*sqrt(prj->w[4] - prj->w[5]*sind(*thetap));
      }
d5148 1
a5148 8
      for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
         *xp =  r*(*xp) - prj->x0;
         *yp = -r*(*yp) - y0;
         *(statp++) = 0;
      }
   }

   return 0;
d5182 1
a5182 1
   if (prj == 0x0) return 1;
d5184 2
a5185 2
   prj->flag = COD;
   strcpy(prj->code, "COD");
d5187 28
a5214 24
   if (undefined(prj->pv[1])) {
      return 2;
   }
   if (undefined(prj->pv[2])) prj->pv[2] = 0.0;
   if (prj->r0 == 0.0) prj->r0 = R2D;

   strcpy(prj->name, "conic equidistant");
   prj->category  = CONIC;
   prj->pvrange   = 102;
   prj->simplezen = 0;
   prj->equiareal = 0;
   prj->conformal = 0;
   prj->global    = 1;
   prj->divergent = 0;

   if (prj->pv[2] == 0.0) {
      prj->w[0] = prj->r0*sind(prj->pv[1])*D2R;
   } else {
      prj->w[0] = prj->r0*sind(prj->pv[1])*sind(prj->pv[2])/prj->pv[2];
   }

   if (prj->w[0] == 0.0) {
      return 2;
   }
d5216 2
a5217 3
   prj->w[1] = 1.0/prj->w[0];
   prj->w[2] = prj->r0*cosd(prj->pv[2])*cosd(prj->pv[1])/prj->w[0];
   prj->w[3] = prj->w[2] + prj->pv[1];
d5219 1
a5219 4
   prj->prjx2s = codx2s;
   prj->prjs2x = cods2x;

   return prjoff(prj, 0.0, prj->pv[1]);
d5233 45
a5277 45
   int mx, my, rowlen, rowoff;
   double alpha, dy, dy2, r, xj;
   register int ix, iy, *statp;
   register const double *xp, *yp;
   register double *phip, *thetap;

   /* Initialize. */
   if (prj == 0x0) return 1;
   if (prj->flag != COD) {
      if (codset(prj)) return 2;
   }

   if (ny > 0) {
      mx = nx;
      my = ny;
   } else {
      mx = 1;
      my = 1;
      ny = nx;
   }


   /* Do x dependence. */
   xp = x;
   rowoff = 0;
   rowlen = nx*spt;
   for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
      xj = *xp + prj->x0;

      phip = phi + rowoff;
      for (iy = 0; iy < my; iy++) {
         *phip = xj;
         phip += rowlen;
      }
   }


   /* Do y dependence. */
   yp = y;
   phip   = phi;
   thetap = theta;
   statp  = stat;
   for (iy = 0; iy < ny; iy++, yp += sxy) {
      dy  = prj->w[2] - (*yp + prj->y0);
      dy2 = dy*dy;
d5279 2
a5280 2
      for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
         xj = *phip;
d5282 2
a5283 2
         r = sqrt(xj*xj + dy2);
         if (prj->pv[1] < 0.0) r = -r;
d5285 5
a5289 5
         if (r == 0.0) {
            alpha = 0.0;
         } else {
            alpha = atan2d(xj/r, dy/r);
         }
d5291 5
a5295 5
         *phip = alpha*prj->w[1];
         *thetap = prj->w[3] - r;
         *(statp++) = 0;
      }
   }
d5297 1
a5297 1
   return 0;
d5311 56
a5366 57
   int mphi, mtheta, rowlen, rowoff;
   double alpha, cosalpha, r, sinalpha, y0;
   register int iphi, itheta, *statp;
   register const double *phip, *thetap;
   register double *xp, *yp;

   /* Initialize. */
   if (prj == 0x0) return 1;
   if (prj->flag != COD) {
      if (codset(prj)) return 2;
   }

   if (ntheta > 0) {
      mphi   = nphi;
      mtheta = ntheta;
   } else {
      mphi   = 1;
      mtheta = 1;
      ntheta = nphi;
   }


   /* Do phi dependence. */
   phip = phi;
   rowoff = 0;
   rowlen = nphi*sxy;
   for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
      alpha = prj->w[0]*(*phip);
      sinalpha = sind(alpha);
      cosalpha = cosd(alpha);

      xp = x + rowoff;
      yp = y + rowoff;
      for (itheta = 0; itheta < mtheta; itheta++) {
         *xp = sinalpha;
         *yp = cosalpha;
         xp += rowlen;
         yp += rowlen;
      }
   }


   /* Do theta dependence. */
   thetap = theta;
   xp = x;
   yp = y;
   statp = stat;
   y0 = prj->y0 - prj->w[2];
   for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
      r = prj->w[3] - *thetap;

      for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
         *xp =  r*(*xp) - prj->x0;
         *yp = -r*(*yp) - y0;
         *(statp++) = 0;
      }
   }
d5368 1
a5368 1
   return 0;
d5405 1
a5405 1
   double cos1, cos2, tan1, tan2, theta1, theta2;
d5407 1
a5407 1
   if (prj == 0x0) return 1;
d5409 2
a5410 2
   prj->flag = COO;
   strcpy(prj->code, "COO");
d5412 40
a5451 31
   if (undefined(prj->pv[1])) {
      return 2;
   }
   if (undefined(prj->pv[2])) prj->pv[2] = 0.0;
   if (prj->r0 == 0.0) prj->r0 = R2D;

   strcpy(prj->name, "conic orthomorphic");
   prj->category  = CONIC;
   prj->pvrange   = 102;
   prj->simplezen = 0;
   prj->equiareal = 0;
   prj->conformal = 1;
   prj->global    = 0;
   prj->divergent = 1;

   theta1 = prj->pv[1] - prj->pv[2];
   theta2 = prj->pv[1] + prj->pv[2];

   tan1 = tand((90.0 - theta1)/2.0);
   cos1 = cosd(theta1);

   if (theta1 == theta2) {
      prj->w[0] = sind(theta1);
   } else {
      tan2 = tand((90.0 - theta2)/2.0);
      cos2 = cosd(theta2);
      prj->w[0] = log(cos2/cos1)/log(tan2/tan1);
   }
   if (prj->w[0] == 0.0) {
      return 2;
   }
d5453 2
a5454 8
   prj->w[1] = 1.0/prj->w[0];

   prj->w[3] = prj->r0*(cos1/prj->w[0])/pow(tan1,prj->w[0]);
   if (prj->w[3] == 0.0) {
      return 2;
   }
   prj->w[2] = prj->w[3]*pow(tand((90.0 - prj->pv[1])/2.0),prj->w[0]);
   prj->w[4] = 1.0/prj->w[3];
d5456 1
a5456 4
   prj->prjx2s = coox2s;
   prj->prjs2x = coos2x;

   return prjoff(prj, 0.0, prj->pv[1]);
d5470 47
a5516 47
   int mx, my, rowlen, rowoff, status;
   double alpha, dy, dy2, r, t, xj;
   register int ix, iy, istat, *statp;
   register const double *xp, *yp;
   register double *phip, *thetap;

   /* Initialize. */
   if (prj == 0x0) return 1;
   if (prj->flag != COO) {
      if (cooset(prj)) return 2;
   }

   if (ny > 0) {
      mx = nx;
      my = ny;
   } else {
      mx = 1;
      my = 1;
      ny = nx;
   }

   status = 0;


   /* Do x dependence. */
   xp = x;
   rowoff = 0;
   rowlen = nx*spt;
   for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
      xj = *xp + prj->x0;

      phip = phi + rowoff;
      for (iy = 0; iy < my; iy++) {
         *phip = xj;
         phip += rowlen;
      }
   }


   /* Do y dependence. */
   yp = y;
   phip   = phi;
   thetap = theta;
   statp  = stat;
   for (iy = 0; iy < ny; iy++, yp += sxy) {
      dy  = prj->w[2] - (*yp + prj->y0);
      dy2 = dy*dy;
d5518 2
a5519 2
      for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
         xj = *phip;
d5521 2
a5522 2
         r = sqrt(xj*xj + dy2);
         if (prj->pv[1] < 0.0) r = -r;
d5524 5
a5528 18
         if (r == 0.0) {
            alpha = 0.0;
         } else {
            alpha = atan2d(xj/r, dy/r);
         }

         istat = 0;
         if (r == 0.0) {
            if (prj->w[0] < 0.0) {
               t = -90.0;
            } else {
               t = 0.0;
               istat  = 1;
               status = 3;
            }
         } else {
            t = 90.0 - 2.0*atand(pow(r*prj->w[4],prj->w[1]));
         }
d5530 11
a5540 3
         *phip = alpha*prj->w[1];
         *thetap = t;
         *(statp++) = istat;
a5541 1
   }
d5543 7
a5549 1
   return status;
d5563 51
a5613 52
   int mphi, mtheta, rowlen, rowoff, status;
   double alpha, cosalpha, r, sinalpha, y0;
   register int iphi, itheta, istat, *statp;
   register const double *phip, *thetap;
   register double *xp, *yp;

   /* Initialize. */
   if (prj == 0x0) return 1;
   if (prj->flag != COO) {
      if (cooset(prj)) return 2;
   }

   if (ntheta > 0) {
      mphi   = nphi;
      mtheta = ntheta;
   } else {
      mphi   = 1;
      mtheta = 1;
      ntheta = nphi;
   }

   status = 0;


   /* Do phi dependence. */
   phip = phi;
   rowoff = 0;
   rowlen = nphi*sxy;
   for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
      alpha = prj->w[0]*(*phip);
      sinalpha = sind(alpha);
      cosalpha = cosd(alpha);

      xp = x + rowoff;
      yp = y + rowoff;
      for (itheta = 0; itheta < mtheta; itheta++) {
         *xp = sinalpha;
         *yp = cosalpha;
         xp += rowlen;
         yp += rowlen;
      }
   }


   /* Do theta dependence. */
   thetap = theta;
   xp = x;
   yp = y;
   statp = stat;
   y0 = prj->y0 - prj->w[2];
   for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
      istat = 0;
d5615 16
a5630 16
      if (*thetap == -90.0) {
         r = 0.0;
         if (prj->w[0] >= 0.0) {
            istat  = 1;
            status = 4;
         }
      } else {
         r = prj->w[3]*pow(tand((90.0 - *thetap)/2.0),prj->w[0]);
      }

      for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
         *xp =  r*(*xp) - prj->x0;
         *yp = -r*(*yp) - y0;
         *(statp++) = istat;
      }
   }
d5632 1
a5632 1
   return status;
d5662 1
a5662 4
   if (prj == 0x0) return 1;

   prj->flag = BON;
   strcpy(prj->code, "BON");
d5664 2
a5665 3
   if (undefined(prj->pv[1])) {
      return 2;
   }
d5667 26
a5692 23
   if (prj->pv[1] == 0.0) {
      /* Sanson-Flamsteed. */
      return sflset(prj);
   }

   strcpy(prj->name, "Bonne's");
   prj->category  = POLYCONIC;
   prj->pvrange   = 101;
   prj->simplezen = 0;
   prj->equiareal = 1;
   prj->conformal = 0;
   prj->global    = 1;
   prj->divergent = 0;

   if (prj->r0 == 0.0) {
      prj->r0 = R2D;
      prj->w[1] = 1.0;
      prj->w[2] = prj->r0*cosd(prj->pv[1])/sind(prj->pv[1]) + prj->pv[1];
   } else {
      prj->w[1] = prj->r0*D2R;
      prj->w[2] = prj->r0*(cosd(prj->pv[1])/sind(prj->pv[1]) +
                           prj->pv[1]*D2R);
   }
d5694 2
a5695 2
   prj->prjx2s = bonx2s;
   prj->prjs2x = bons2x;
d5697 1
a5697 1
   return prjoff(prj, 0.0, 0.0);
d5711 51
a5761 51
   int mx, my, rowlen, rowoff;
   double alpha, dy, dy2, costhe, r, s, t, xj;
   register int ix, iy, *statp;
   register const double *xp, *yp;
   register double *phip, *thetap;


   /* Initialize. */
   if (prj == 0x0) return 1;
   if (prj->pv[1] == 0.0) {
      /* Sanson-Flamsteed. */
      return sflx2s(prj, nx, ny, sxy, spt, x, y, phi, theta, stat);
   }

   if (prj->flag != BON) {
      if (bonset(prj)) return 2;
   }

   if (ny > 0) {
      mx = nx;
      my = ny;
   } else {
      mx = 1;
      my = 1;
      ny = nx;
   }


   /* Do x dependence. */
   xp = x;
   rowoff = 0;
   rowlen = nx*spt;
   for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
      xj = *xp + prj->x0;

      phip = phi + rowoff;
      for (iy = 0; iy < my; iy++) {
         *phip = xj;
         phip += rowlen;
      }
   }


   /* Do y dependence. */
   yp = y;
   phip   = phi;
   thetap = theta;
   statp  = stat;
   for (iy = 0; iy < ny; iy++, yp += sxy) {
      dy  = prj->w[2] - (*yp + prj->y0);
      dy2 = dy*dy;
d5763 2
a5764 2
      for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
         xj = *phip;
d5766 2
a5767 2
         r = sqrt(xj*xj + dy2);
         if (prj->pv[1] < 0.0) r = -r;
d5769 4
a5772 17
         if (r == 0.0) {
            alpha = 0.0;
         } else {
            alpha = atan2d(xj/r, dy/r);
         }

         t = (prj->w[2] - r)/prj->w[1];
         costhe = cosd(t);
         if (costhe == 0.0) {
            s = 0.0;
         } else {
            s = alpha*(r/prj->r0)/costhe;
         }

         *phip = s;
         *thetap = t;
         *(statp++) = 0;
a5773 1
   }
d5775 15
a5789 1
   return 0;
d5803 61
a5863 52
   int mphi, mtheta, rowlen, rowoff;
   double alpha, r, s, y0;
   register int iphi, itheta, *statp;
   register const double *phip, *thetap;
   register double *xp, *yp;

   /* Initialize. */
   if (prj == 0x0) return 1;
   if (prj->pv[1] == 0.0) {
      /* Sanson-Flamsteed. */
      return sfls2x(prj, nphi, ntheta, spt, sxy, phi, theta, x, y, stat);
   }

   if (prj->flag != BON) {
      if (bonset(prj)) return 2;
   }

   if (ntheta > 0) {
      mphi   = nphi;
      mtheta = ntheta;
   } else {
      mphi   = 1;
      mtheta = 1;
      ntheta = nphi;
   }

   y0 = prj->y0 - prj->w[2];


   /* Do phi dependence. */
   phip = phi;
   rowoff = 0;
   rowlen = nphi*sxy;
   for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
      s = prj->r0*(*phip);

      xp = x + rowoff;
      for (itheta = 0; itheta < mtheta; itheta++) {
         *xp = s;
         xp += rowlen;
      }
   }


   /* Do theta dependence. */
   thetap = theta;
   xp = x;
   yp = y;
   statp = stat;
   for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
      r = prj->w[2] - prj->w[1]*(*thetap);
      s = cosd(*thetap)/r;
d5865 1
a5865 9
      for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
         alpha = s*(*xp);
         *xp =  r*sind(alpha) - prj->x0;
         *yp = -r*cosd(alpha) - y0;
         *(statp++) = 0;
      }
   }

   return 0;
d5893 1
a5893 1
   if (prj == 0x0) return 1;
d5895 2
a5896 2
   prj->flag = PCO;
   strcpy(prj->code, "PCO");
d5898 19
a5916 19
   strcpy(prj->name, "polyconic");
   prj->category  = POLYCONIC;
   prj->pvrange   = 0;
   prj->simplezen = 0;
   prj->equiareal = 0;
   prj->conformal = 0;
   prj->global    = 1;
   prj->divergent = 0;

   if (prj->r0 == 0.0) {
      prj->r0 = R2D;
      prj->w[0] = 1.0;
      prj->w[1] = 1.0;
      prj->w[2] = 360.0/PI;
   } else {
      prj->w[0] = prj->r0*D2R;
      prj->w[1] = 1.0/prj->w[0];
      prj->w[2] = 2.0*prj->r0;
   }
d5918 2
a5919 2
   prj->prjx2s = pcox2s;
   prj->prjs2x = pcos2x;
d5921 1
a5921 1
   return prjoff(prj, 0.0, 0.0);
d5935 59
a5993 48
   int mx, my, rowlen, rowoff;
   double f, fneg, fpos, lambda, tanthe, the, theneg, thepos, w, x1, xj, xx,
          yj, ymthe, y1;
   const double tol = 1.0e-12;
   register int ix, iy, k, *statp;
   register const double *xp, *yp;
   register double *phip, *thetap;


   /* Initialize. */
   if (prj == 0x0) return 1;
   if (prj->flag != PCO) {
      if (pcoset(prj)) return 2;
   }

   if (ny > 0) {
      mx = nx;
      my = ny;
   } else {
      mx = 1;
      my = 1;
      ny = nx;
   }


   /* Do x dependence. */
   xp = x;
   rowoff = 0;
   rowlen = nx*spt;
   for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
      xj = *xp + prj->x0;

      phip = phi + rowoff;
      for (iy = 0; iy < my; iy++) {
         *phip = xj;
         phip += rowlen;
      }
   }


   /* Do y dependence. */
   yp = y;
   phip   = phi;
   thetap = theta;
   statp  = stat;
   for (iy = 0; iy < ny; iy++, yp += sxy) {
      yj = *yp + prj->y0;
      w  = fabs(yj*prj->w[1]);
d5995 62
a6056 73
      for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
         xj = *phip;

         if (w < tol) {
            *phip = xj*prj->w[1];
            *thetap = 0.0;

         } else if (fabs(w-90.0) < tol) {
            *phip = 0.0;
            *thetap = copysign(90.0, yj);

         } else {
            /* Iterative solution using weighted division of the interval. */
            if (yj > 0.0) {
               thepos =  90.0;
            } else {
               thepos = -90.0;
            }
            theneg = 0.0;

            xx = xj*xj;
            ymthe = yj - prj->w[0]*thepos;
            fpos = xx + ymthe*ymthe;
            fneg = -999.0;

            for (k = 0; k < 64; k++) {
               if (fneg < -100.0) {
                  /* Equal division of the interval. */
                  the = (thepos+theneg)/2.0;
               } else {
                  /* Weighted division of the interval. */
                  lambda = fpos/(fpos-fneg);
                  if (lambda < 0.1) {
                     lambda = 0.1;
                  } else if (lambda > 0.9) {
                     lambda = 0.9;
                  }
                  the = thepos - lambda*(thepos-theneg);
               }

               /* Compute the residue. */
               ymthe = yj - prj->w[0]*(the);
               tanthe = tand(the);
               f = xx + ymthe*(ymthe - prj->w[2]/tanthe);

               /* Check for convergence. */
               if (fabs(f) < tol) break;
               if (fabs(thepos-theneg) < tol) break;

               /* Redefine the interval. */
               if (f > 0.0) {
                  thepos = the;
                  fpos = f;
               } else {
                  theneg = the;
                  fneg = f;
               }
            }

            x1 = prj->r0 - ymthe*tanthe;
            y1 = xj*tanthe;
            if (x1 == 0.0 && y1 == 0.0) {
               *phip = 0.0;
            } else {
               *phip = atan2d(y1, x1)/sind(the);
            }

            *thetap = the;
         }

         *(statp++) = 0;
      }
   }
d6058 1
a6058 1
   return 0;
d6072 54
a6125 44
   int mphi, mtheta, rowlen, rowoff;
   double alpha, costhe, cotthe, sinthe, therad;
   register int iphi, itheta, *statp;
   register const double *phip, *thetap;
   register double *xp, *yp;

   /* Initialize. */
   if (prj == 0x0) return 1;
   if (prj->flag != PCO) {
      if (pcoset(prj)) return 2;
   }

   if (ntheta > 0) {
      mphi   = nphi;
      mtheta = ntheta;
   } else {
      mphi   = 1;
      mtheta = 1;
      ntheta = nphi;
   }


   /* Do phi dependence. */
   phip = phi;
   rowoff = 0;
   rowlen = nphi*sxy;
   for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
      xp = x + rowoff;
      for (itheta = 0; itheta < mtheta; itheta++) {
         *xp = *phip;
         xp += rowlen;
      }
   }


   /* Do theta dependence. */
   thetap = theta;
   xp = x;
   yp = y;
   statp = stat;
   for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
      therad = (*thetap)*D2R;
      costhe = cosd(*thetap);
      sinthe = sind(*thetap);
d6127 3
a6129 10
      for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
         if (sinthe == 0.0) {
            *xp =  prj->w[0]*(*xp) - prj->x0;
            *yp = -prj->y0;
         } else {
            alpha  = (*xp)*sinthe;
            cotthe = costhe/sinthe;
            *xp = prj->r0*cotthe*sind(alpha) - prj->x0;
            *yp = prj->r0*(cotthe*(1.0 - cosd(alpha)) + therad) - prj->y0;
         }
d6131 1
a6131 5
         *(statp++) = 0;
      }
   }

   return 0;
d6158 1
a6158 1
   if (prj == 0x0) return 1;
d6160 2
a6161 2
   prj->flag = TSC;
   strcpy(prj->code, "TSC");
d6163 17
a6179 17
   strcpy(prj->name, "tangential spherical cube");
   prj->category  = QUADCUBE;
   prj->pvrange   = 0;
   prj->simplezen = 0;
   prj->equiareal = 0;
   prj->conformal = 0;
   prj->global    = 1;
   prj->divergent = 0;

   if (prj->r0 == 0.0) {
      prj->r0 = R2D;
      prj->w[0] = 45.0;
      prj->w[1] = 1.0/45.0;
   } else {
      prj->w[0] = prj->r0*PI/4.0;
      prj->w[1] = 1.0/prj->w[0];
   }
d6181 2
a6182 2
   prj->prjx2s = tscx2s;
   prj->prjs2x = tscs2x;
d6184 1
a6184 1
   return prjoff(prj, 0.0, 0.0);
d6198 110
a6307 47
   int mx, my, rowlen, rowoff, status;
   double l, m, n, xf, yf;
   register int ix, iy, *statp;
   register const double *xp, *yp;
   register double *phip, *thetap;


   /* Initialize. */
   if (prj == 0x0) return 1;
   if (prj->flag != TSC) {
      if (tscset(prj)) return 2;
   }

   if (ny > 0) {
      mx = nx;
      my = ny;
   } else {
      mx = 1;
      my = 1;
      ny = nx;
   }

   status = 0;


   /* Do x dependence. */
   xp = x;
   rowoff = 0;
   rowlen = nx*spt;
   for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
      xf = (*xp + prj->x0)*prj->w[1];

      phip = phi + rowoff;
      for (iy = 0; iy < my; iy++) {
         *phip = xf;
         phip += rowlen;
      }
   }


   /* Do y dependence. */
   yp = y;
   phip   = phi;
   thetap = theta;
   statp  = stat;
   for (iy = 0; iy < ny; iy++, yp += sxy) {
      yf = (*yp + prj->y0)*prj->w[1];
d6309 5
a6313 2
      for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
         xf = *phip;
d6315 4
a6318 21
         /* Check bounds. */
         if (fabs(xf) <= 1.0) {
            if (fabs(yf) > 3.0) {
               *phip = 0.0;
               *thetap = 0.0;
               *(statp++) = 1;
               status = 3;
               continue;
            }
         } else {
            if (fabs(xf) > 7.0 || fabs(yf) > 1.0) {
               *phip = 0.0;
               *thetap = 0.0;
               *(statp++) = 1;
               status = 3;
               continue;
            }
         }

         /* Map negative faces to the other side. */
         if (xf < -1.0) xf += 8.0;
d6320 1
a6320 50
         /* Determine the face. */
         if (xf > 5.0) {
            /* face = 4 */
            xf = xf - 6.0;
            m  = -1.0/sqrt(1.0 + xf*xf + yf*yf);
            l  = -m*xf;
            n  = -m*yf;
         } else if (xf > 3.0) {
            /* face = 3 */
            xf = xf - 4.0;
            l  = -1.0/sqrt(1.0 + xf*xf + yf*yf);
            m  =  l*xf;
            n  = -l*yf;
         } else if (xf > 1.0) {
            /* face = 2 */
            xf = xf - 2.0;
            m  =  1.0/sqrt(1.0 + xf*xf + yf*yf);
            l  = -m*xf;
            n  =  m*yf;
         } else if (yf > 1.0) {
            /* face = 0 */
            yf = yf - 2.0;
            n  = 1.0/sqrt(1.0 + xf*xf + yf*yf);
            l  = -n*yf;
            m  =  n*xf;
         } else if (yf < -1.0) {
            /* face = 5 */
            yf = yf + 2.0;
            n  = -1.0/sqrt(1.0 + xf*xf + yf*yf);
            l  = -n*yf;
            m  = -n*xf;
         } else {
            /* face = 1 */
            l  =  1.0/sqrt(1.0 + xf*xf + yf*yf);
            m  =  l*xf;
            n  =  l*yf;
         }

         if (l == 0.0 && m == 0.0) {
            *phip = 0.0;
         } else {
            *phip = atan2d(m, l);
         }

         *thetap = asind(n);
         *(statp++) = 0;
      }
   }

   return status;
d6334 118
a6451 52
   int face, mphi, mtheta, rowlen, rowoff, status;
   double cosphi, costhe, l, m, n, sinphi, sinthe, x0, xf, y0, yf, zeta;
   const double tol = 1.0e-12;
   register int iphi, istat, itheta, *statp;
   register const double *phip, *thetap;
   register double *xp, *yp;

   /* Initialize. */
   if (prj == 0x0) return 1;
   if (prj->flag != TSC) {
      if (tscset(prj)) return 2;
   }

   if (ntheta > 0) {
      mphi   = nphi;
      mtheta = ntheta;
   } else {
      mphi   = 1;
      mtheta = 1;
      ntheta = nphi;
   }

   status = 0;


   /* Do phi dependence. */
   phip = phi;
   rowoff = 0;
   rowlen = nphi*sxy;
   for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
      cosphi = cosd(*phip);
      sinphi = sind(*phip);

      xp = x + rowoff;
      yp = y + rowoff;
      for (itheta = 0; itheta < mtheta; itheta++) {
         *xp = cosphi;
         *yp = sinphi;
         xp += rowlen;
         yp += rowlen;
      }
   }


   /* Do theta dependence. */
   thetap = theta;
   xp = x;
   yp = y;
   statp = stat;
   for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
      costhe = cosd(*thetap);
      sinthe = sind(*thetap);
d6453 21
a6473 83
      for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
         l = costhe*(*xp);
         m = costhe*(*yp);
         n = sinthe;

         face = 0;
         zeta = n;
         if (l > zeta) {
            face = 1;
            zeta = l;
         }
         if (m > zeta) {
            face = 2;
            zeta = m;
         }
         if (-l > zeta) {
            face = 3;
            zeta = -l;
         }
         if (-m > zeta) {
            face = 4;
            zeta = -m;
         }
         if (-n > zeta) {
            face = 5;
            zeta = -n;
         }

         switch (face) {
         case 1:
            xf =  m/zeta;
            yf =  n/zeta;
            x0 =  0.0;
            y0 =  0.0;
            break;
         case 2:
            xf = -l/zeta;
            yf =  n/zeta;
            x0 =  2.0;
            y0 =  0.0;
            break;
         case 3:
            xf = -m/zeta;
            yf =  n/zeta;
            x0 =  4.0;
            y0 =  0.0;
            break;
         case 4:
            xf =  l/zeta;
            yf =  n/zeta;
            x0 =  6.0;
            y0 =  0.0;
            break;
         case 5:
            xf =  m/zeta;
            yf =  l/zeta;
            x0 =  0.0;
            y0 = -2.0;
            break;
         default:
            /* face == 0 */
            xf =  m/zeta;
            yf = -l/zeta;
            x0 =  0.0;
            y0 =  2.0;
            break;
         }

         istat = 0;
         if (fabs(xf) > 1.0) {
            if (fabs(xf) > 1.0+tol) {
               istat  = 1;
               status = 4;
            }
            xf = copysign(1.0, xf);
         }
         if (fabs(yf) > 1.0) {
            if (fabs(yf) > 1.0+tol) {
               istat  = 1;
               status = 4;
            }
            yf = copysign(1.0, yf);
         }
d6475 1
a6475 7
         *xp = prj->w[0]*(xf + x0) - prj->x0;
         *yp = prj->w[0]*(yf + y0) - prj->y0;
         *(statp++) = istat;
      }
   }

   return status;
d6502 1
a6502 1
   if (prj == 0x0) return 1;
d6504 2
a6505 2
   prj->flag = CSC;
   strcpy(prj->code, "CSC");
d6507 17
a6523 17
   strcpy(prj->name, "COBE quadrilateralized spherical cube");
   prj->category  = QUADCUBE;
   prj->pvrange   = 0;
   prj->simplezen = 0;
   prj->equiareal = 0;
   prj->conformal = 0;
   prj->global    = 1;
   prj->divergent = 0;

   if (prj->r0 == 0.0) {
      prj->r0 = R2D;
      prj->w[0] = 45.0;
      prj->w[1] = 1.0/45.0;
   } else {
      prj->w[0] = prj->r0*PI/4.0;
      prj->w[1] = 1.0/prj->w[0];
   }
d6525 2
a6526 2
   prj->prjx2s = cscx2s;
   prj->prjs2x = cscs2x;
d6528 1
a6528 1
   return prjoff(prj, 0.0, 0.0);
d6542 121
a6662 76
   int face, mx, my, rowlen, rowoff, status;
   double l, m, n;
   register int ix, iy, *statp;
   register const double *xp, *yp;
   register double *phip, *thetap;

   float     chi, psi, xf, xx, yf, yy, z0, z1, z2, z3, z4, z5, z6;
   const float p00 = -0.27292696;
   const float p10 = -0.07629969;
   const float p20 = -0.22797056;
   const float p30 =  0.54852384;
   const float p40 = -0.62930065;
   const float p50 =  0.25795794;
   const float p60 =  0.02584375;
   const float p01 = -0.02819452;
   const float p11 = -0.01471565;
   const float p21 =  0.48051509;
   const float p31 = -1.74114454;
   const float p41 =  1.71547508;
   const float p51 = -0.53022337;
   const float p02 =  0.27058160;
   const float p12 = -0.56800938;
   const float p22 =  0.30803317;
   const float p32 =  0.98938102;
   const float p42 = -0.83180469;
   const float p03 = -0.60441560;
   const float p13 =  1.50880086;
   const float p23 = -0.93678576;
   const float p33 =  0.08693841;
   const float p04 =  0.93412077;
   const float p14 = -1.41601920;
   const float p24 =  0.33887446;
   const float p05 = -0.63915306;
   const float p15 =  0.52032238;
   const float p06 =  0.14381585;

   /* Initialize. */
   if (prj == 0x0) return 1;
   if (prj->flag != CSC) {
      if (cscset(prj)) return 2;
   }

   if (ny > 0) {
      mx = nx;
      my = ny;
   } else {
      mx = 1;
      my = 1;
      ny = nx;
   }

   status = 0;


   /* Do x dependence. */
   xp = x;
   rowoff = 0;
   rowlen = nx*spt;
   for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
      xf = (*xp + prj->x0)*prj->w[1];

      phip = phi + rowoff;
      for (iy = 0; iy < my; iy++) {
         *phip = xf;
         phip += rowlen;
      }
   }


   /* Do y dependence. */
   yp = y;
   phip   = phi;
   thetap = theta;
   statp  = stat;
   for (iy = 0; iy < ny; iy++, yp += sxy) {
      yf = (*yp + prj->y0)*prj->w[1];
d6664 2
a6665 2
      for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
         xf = *phip;
d6667 57
a6723 18
         /* Check bounds. */
         if (fabs(xf) <= 1.0) {
            if (fabs(yf) > 3.0) {
               *phip = 0.0;
               *thetap = 0.0;
               *(statp++) = 1;
               status = 3;
               continue;
            }
         } else {
            if (fabs(xf) > 7.0 || fabs(yf) > 1.0) {
               *phip = 0.0;
               *thetap = 0.0;
               *(statp++) = 1;
               status = 3;
               continue;
            }
         }
d6725 5
a6729 89
         /* Map negative faces to the other side. */
         if (xf < -1.0) xf += 8.0;

         /* Determine the face. */
         if (xf > 5.0) {
            face = 4;
            xf = xf - 6.0;
         } else if (xf > 3.0) {
            face = 3;
            xf = xf - 4.0;
         } else if (xf > 1.0) {
            face = 2;
            xf = xf - 2.0;
         } else if (yf > 1.0) {
            face = 0;
            yf = yf - 2.0;
         } else if (yf < -1.0) {
            face = 5;
            yf = yf + 2.0;
         } else {
            face = 1;
         }

         xx  =  xf*xf;
         yy  =  yf*yf;

         z0 = p00 + xx*(p10 + xx*(p20 + xx*(p30 + xx*(p40 + xx*(p50 +
                    xx*(p60))))));
         z1 = p01 + xx*(p11 + xx*(p21 + xx*(p31 + xx*(p41 + xx*(p51)))));
         z2 = p02 + xx*(p12 + xx*(p22 + xx*(p32 + xx*(p42))));
         z3 = p03 + xx*(p13 + xx*(p23 + xx*(p33)));
         z4 = p04 + xx*(p14 + xx*(p24));
         z5 = p05 + xx*(p15);
         z6 = p06;

         chi = z0 + yy*(z1 + yy*(z2 + yy*(z3 + yy*(z4 + yy*(z5 + yy*z6)))));
         chi = xf + xf*(1.0 - xx)*chi;

         z0 = p00 + yy*(p10 + yy*(p20 + yy*(p30 + yy*(p40 + yy*(p50 +
                    yy*(p60))))));
         z1 = p01 + yy*(p11 + yy*(p21 + yy*(p31 + yy*(p41 + yy*(p51)))));
         z2 = p02 + yy*(p12 + yy*(p22 + yy*(p32 + yy*(p42))));
         z3 = p03 + yy*(p13 + yy*(p23 + yy*(p33)));
         z4 = p04 + yy*(p14 + yy*(p24));
         z5 = p05 + yy*(p15);
         z6 = p06;

         psi = z0 + xx*(z1 + xx*(z2 + xx*(z3 + xx*(z4 + xx*(z5 + xx*z6)))));
         psi = yf + yf*(1.0 - yy)*psi;

         switch (face) {
         case 1:
            l =  1.0/sqrt(chi*chi + psi*psi + 1.0);
            m =  chi*l;
            n =  psi*l;
            break;
         case 2:
            m =  1.0/sqrt(chi*chi + psi*psi + 1.0);
            l = -chi*m;
            n =  psi*m;
            break;
         case 3:
            l = -1.0/sqrt(chi*chi + psi*psi + 1.0);
            m =  chi*l;
            n = -psi*l;
            break;
         case 4:
            m = -1.0/sqrt(chi*chi + psi*psi + 1.0);
            l = -chi*m;
            n = -psi*m;
            break;
         case 5:
            n = -1.0/sqrt(chi*chi + psi*psi + 1.0);
            l = -psi*n;
            m = -chi*n;
            break;
         default:
            /* face == 0 */
            n =  1.0/sqrt(chi*chi + psi*psi + 1.0);
            l = -psi*n;
            m =  chi*n;
            break;
         }

         if (l == 0.0 && m == 0.0) {
            *phip = 0.0;
         } else {
            *phip = atan2d(m, l);
         }
d6731 4
a6734 4
         *thetap = asind(n);
         *(statp++) = 0;
      }
   }
d6736 1
a6736 1
   return status;
d6750 148
a6897 67
   int face, mphi, mtheta, rowlen, rowoff, status;
   double cosphi, costhe, eta, l, m, n, sinphi, sinthe, xi, zeta;
   const float tol = 1.0e-7;
   register int iphi, istat, itheta, *statp;
   register const double *phip, *thetap;
   register double *xp, *yp;

   float chi, chi2, chi2psi2, chi4, chipsi, psi, psi2, psi4, chi2co, psi2co, x0, xf, y0, yf;
   const float gstar  =  1.37484847732;
   const float mm     =  0.004869491981;
   const float gamma  = -0.13161671474;
   const float omega1 = -0.159596235474;
   const float d0  =  0.0759196200467;
   const float d1  = -0.0217762490699;
   const float c00 =  0.141189631152;
   const float c10 =  0.0809701286525;
   const float c01 = -0.281528535557;
   const float c11 =  0.15384112876;
   const float c20 = -0.178251207466;
   const float c02 =  0.106959469314;


   /* Initialize. */
   if (prj == 0x0) return 1;
   if (prj->flag != CSC) {
      if (cscset(prj)) return 2;
   }

   if (ntheta > 0) {
      mphi   = nphi;
      mtheta = ntheta;
   } else {
      mphi   = 1;
      mtheta = 1;
      ntheta = nphi;
   }

   status = 0;


   /* Do phi dependence. */
   phip = phi;
   rowoff = 0;
   rowlen = nphi*sxy;
   for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
      cosphi = cosd(*phip);
      sinphi = sind(*phip);

      xp = x + rowoff;
      yp = y + rowoff;
      for (itheta = 0; itheta < mtheta; itheta++) {
         *xp = cosphi;
         *yp = sinphi;
         xp += rowlen;
         yp += rowlen;
      }
   }


   /* Do theta dependence. */
   thetap = theta;
   xp = x;
   yp = y;
   statp = stat;
   for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
      costhe = cosd(*thetap);
      sinthe = sind(*thetap);
d6899 1
a6899 83
      for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
         l = costhe*(*xp);
         m = costhe*(*yp);
         n = sinthe;

         face = 0;
         zeta = n;
         if (l > zeta) {
            face = 1;
            zeta = l;
         }
         if (m > zeta) {
            face = 2;
            zeta = m;
         }
         if (-l > zeta) {
            face = 3;
            zeta = -l;
         }
         if (-m > zeta) {
            face = 4;
            zeta = -m;
         }
         if (-n > zeta) {
            face = 5;
            zeta = -n;
         }

         switch (face) {
         case 1:
            xi  =  m;
            eta =  n;
            x0  =  0.0;
            y0  =  0.0;
            break;
         case 2:
            xi  = -l;
            eta =  n;
            x0  =  2.0;
            y0  =  0.0;
            break;
         case 3:
            xi  = -m;
            eta =  n;
            x0  =  4.0;
            y0  =  0.0;
            break;
         case 4:
            xi  =  l;
            eta =  n;
            x0  =  6.0;
            y0  =  0.0;
            break;
         case 5:
            xi  =  m;
            eta =  l;
            x0  =  0.0;
            y0  = -2.0;
            break;
         default:
            /* face == 0 */
            xi  =  m;
            eta = -l;
            x0  =  0.0;
            y0  =  2.0;
            break;
         }

         chi =  xi/zeta;
         psi = eta/zeta;

         chi2 = chi*chi;
         psi2 = psi*psi;
         chi2co = 1.0 - chi2;
         psi2co = 1.0 - psi2;

         /* Avoid floating underflows. */
         chipsi = fabs(chi*psi);
         chi4   = (chi2 > 1.0e-16) ? chi2*chi2 : 0.0;
         psi4   = (psi2 > 1.0e-16) ? psi2*psi2 : 0.0;
         chi2psi2 = (chipsi > 1.0e-16) ? chi2*psi2 : 0.0;

         xf = chi*(chi2 + chi2co*(gstar + psi2*(gamma*chi2co + mm*chi2 +
d6902 1
a6902 1
         yf = psi*(psi2 + psi2co*(gstar + chi2*(gamma*psi2co + mm*psi2 +
d6906 21
a6926 21
         istat = 0;
         if (fabs(xf) > 1.0) {
            if (fabs(xf) > 1.0+tol) {
               istat  = 1;
               status = 4;
            }
            xf = copysign(1.0, xf);
         }
         if (fabs(yf) > 1.0) {
            if (fabs(yf) > 1.0+tol) {
               istat  = 1;
               status = 4;
            }
            yf = copysign(1.0, yf);
         }

         *xp = prj->w[0]*(xf + x0) - prj->x0;
         *yp = prj->w[0]*(yf + y0) - prj->y0;
         *(statp++) = istat;
      }
   }
d6928 1
a6928 1
   return status;
d6955 1
a6955 1
   if (prj == 0x0) return 1;
d6957 2
a6958 2
   prj->flag = QSC;
   strcpy(prj->code, "QSC");
d6960 17
a6976 17
   strcpy(prj->name, "quadrilateralized spherical cube");
   prj->category  = QUADCUBE;
   prj->pvrange   = 0;
   prj->simplezen = 0;
   prj->equiareal = 1;
   prj->conformal = 0;
   prj->global    = 1;
   prj->divergent = 0;

   if (prj->r0 == 0.0) {
      prj->r0 = R2D;
      prj->w[0] = 45.0;
      prj->w[1] = 1.0/45.0;
   } else {
      prj->w[0] = prj->r0*PI/4.0;
      prj->w[1] = 1.0/prj->w[0];
   }
d6978 2
a6979 2
   prj->prjx2s = qscx2s;
   prj->prjs2x = qscs2x;
d6981 1
a6981 1
   return prjoff(prj, 0.0, 0.0);
d6995 93
a7087 48
   int direct, face, mx, my, rowlen, rowoff, status;
   double l, m, n, omega, tau, xf, yf, w, zeco, zeta;
   const double tol = 1.0e-12;
   register int ix, iy, *statp;
   register const double *xp, *yp;
   register double *phip, *thetap;


   /* Initialize. */
   if (prj == 0x0) return 1;
   if (prj->flag != QSC) {
      if (qscset(prj)) return 2;
   }

   if (ny > 0) {
      mx = nx;
      my = ny;
   } else {
      mx = 1;
      my = 1;
      ny = nx;
   }

   status = 0;


   /* Do x dependence. */
   xp = x;
   rowoff = 0;
   rowlen = nx*spt;
   for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
      xf = (*xp + prj->x0)*prj->w[1];

      phip = phi + rowoff;
      for (iy = 0; iy < my; iy++) {
         *phip = xf;
         phip += rowlen;
      }
   }


   /* Do y dependence. */
   yp = y;
   phip   = phi;
   thetap = theta;
   statp  = stat;
   for (iy = 0; iy < ny; iy++, yp += sxy) {
      yf = (*yp + prj->y0)*prj->w[1];
d7089 45
a7133 2
      for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
         xf = *phip;
d7135 75
a7209 18
         /* Check bounds. */
         if (fabs(xf) <= 1.0) {
            if (fabs(yf) > 3.0) {
               *phip = 0.0;
               *thetap = 0.0;
               *(statp++) = 1;
               status = 3;
               continue;
            }
         } else {
            if (fabs(xf) > 7.0 || fabs(yf) > 1.0) {
               *phip = 0.0;
               *thetap = 0.0;
               *(statp++) = 1;
               status = 3;
               continue;
            }
         }
d7211 5
a7215 143
         /* Map negative faces to the other side. */
         if (xf < -1.0) xf += 8.0;

         /* Determine the face. */
         if (xf > 5.0) {
            face = 4;
            xf -= 6.0;
         } else if (xf > 3.0) {
            face = 3;
            xf -= 4.0;
         } else if (xf > 1.0) {
            face = 2;
            xf -= 2.0;
         } else if (yf > 1.0) {
            face = 0;
            yf -= 2.0;
         } else if (yf < -1.0) {
            face = 5;
            yf += 2.0;
         } else {
            face = 1;
         }

         direct = (fabs(xf) > fabs(yf));
         if (direct) {
            if (xf == 0.0) {
               omega = 0.0;
               tau  = 1.0;
               zeta = 1.0;
               zeco = 0.0;
            } else {
               w = 15.0*yf/xf;
               omega = sind(w)/(cosd(w) - SQRT2INV);
               tau  = 1.0 + omega*omega;
               zeco = xf*xf*(1.0 - 1.0/sqrt(1.0 + tau));
               zeta = 1.0 - zeco;
            }
         } else {
            if (yf == 0.0) {
               omega = 0.0;
               tau  = 1.0;
               zeta = 1.0;
               zeco = 0.0;
            } else {
               w = 15.0*xf/yf;
               omega = sind(w)/(cosd(w) - SQRT2INV);
               tau  = 1.0 + omega*omega;
               zeco = yf*yf*(1.0 - 1.0/sqrt(1.0 + tau));
               zeta = 1.0 - zeco;
            }
         }

         if (zeta < -1.0) {
            if (zeta < -1.0-tol) {
               *phip = 0.0;
               *thetap = 0.0;
               *(statp++) = 1;
               status = 3;
               continue;
            }

            zeta = -1.0;
            zeco =  2.0;
            w    =  0.0;
         } else {
            w = sqrt(zeco*(2.0-zeco)/tau);
         }

         switch (face) {
         case 1:
            l = zeta;
            if (direct) {
               m = w;
               if (xf < 0.0) m = -m;
               n = m*omega;
            } else {
               n = w;
               if (yf < 0.0) n = -n;
               m = n*omega;
            }
            break;
         case 2:
            m = zeta;
            if (direct) {
               l = w;
               if (xf > 0.0) l = -l;
               n = -l*omega;
            } else {
               n = w;
               if (yf < 0.0) n = -n;
               l = -n*omega;
            }
            break;
         case 3:
            l = -zeta;
            if (direct) {
               m = w;
               if (xf > 0.0) m = -m;
               n = -m*omega;
            } else {
               n = w;
               if (yf < 0.0) n = -n;
               m = -n*omega;
            }
            break;
         case 4:
            m = -zeta;
            if (direct) {
               l = w;
               if (xf < 0.0) l = -l;
               n = l*omega;
            } else {
               n = w;
               if (yf < 0.0) n = -n;
               l = n*omega;
            }
            break;
         case 5:
            n = -zeta;
            if (direct) {
               m = w;
               if (xf < 0.0) m = -m;
               l = m*omega;
            } else {
               l = w;
               if (yf < 0.0) l = -l;
               m = l*omega;
            }
            break;
         default:
            /* face == 0 */
            n = zeta;
            if (direct) {
               m = w;
               if (xf < 0.0) m = -m;
               l = -m*omega;
            } else {
               l = w;
               if (yf > 0.0) l = -l;
               m = -l*omega;
            }
            break;
         }
d7217 4
a7220 5
         if (l == 0.0 && m == 0.0) {
            *phip = 0.0;
         } else {
            *phip = atan2d(m, l);
         }
d7222 1
a7222 6
         *thetap = asind(n);
         *(statp++) = 0;
      }
   }

   return status;
d7236 52
a7287 54
   int face, mphi, mtheta, rowlen, rowoff, status;
   double cosphi, costhe, eta, l, m, n, omega, p, sinphi, sinthe, t, tau, x0,
          xf, xi, y0, yf, zeco, zeta;
   const double tol = 1.0e-12;
   register int iphi, istat, itheta, *statp;
   register const double *phip, *thetap;
   register double *xp, *yp;


   /* Initialize. */
   if (prj == 0x0) return 1;
   if (prj->flag != QSC) {
      if (qscset(prj)) return 2;
   }

   if (ntheta > 0) {
      mphi   = nphi;
      mtheta = ntheta;
   } else {
      mphi   = 1;
      mtheta = 1;
      ntheta = nphi;
   }

   status = 0;


   /* Do phi dependence. */
   phip = phi;
   rowoff = 0;
   rowlen = nphi*sxy;
   for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
      cosphi = cosd(*phip);
      sinphi = sind(*phip);

      xp = x + rowoff;
      yp = y + rowoff;
      for (itheta = 0; itheta < mtheta; itheta++) {
         *xp = cosphi;
         *yp = sinphi;
         xp += rowlen;
         yp += rowlen;
      }
   }


   /* Do theta dependence. */
   thetap = theta;
   xp = x;
   yp = y;
   statp = stat;
   for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
      costhe = cosd(*thetap);
      sinthe = sind(*thetap);
d7289 137
a7425 7
      for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
         if (fabs(*thetap) == 90.0) {
            *xp = -prj->x0;
            *yp = copysign(2.0*prj->w[0], *thetap) - prj->y0;
            *(statp++) = 0;
            continue;
         }
d7427 21
a7447 129
         l = costhe*(*xp);
         m = costhe*(*yp);
         n = sinthe;

         face = 0;
         zeta = n;
         if (l > zeta) {
            face = 1;
            zeta = l;
         }
         if (m > zeta) {
            face = 2;
            zeta = m;
         }
         if (-l > zeta) {
            face = 3;
            zeta = -l;
         }
         if (-m > zeta) {
            face = 4;
            zeta = -m;
         }
         if (-n > zeta) {
            face = 5;
            zeta = -n;
         }

         zeco = 1.0 - zeta;

         switch (face) {
         case 1:
            xi  = m;
            eta = n;
            if (zeco < 1.0e-8) {
               /* Small angle formula. */
               t = (*thetap)*D2R;
               p = atan2(*yp, *xp);
               zeco = (p*p + t*t)/2.0;
            }
            x0 = 0.0;
            y0 = 0.0;
            break;
         case 2:
            xi  = -l;
            eta =  n;
            if (zeco < 1.0e-8) {
               /* Small angle formula. */
               t = (*thetap)*D2R;
               p = atan2(*yp, *xp) - PI/2.0;
               zeco = (p*p + t*t)/2.0;
            }
            x0 = 2.0;
            y0 = 0.0;
            break;
         case 3:
            xi  = -m;
            eta =  n;
            if (zeco < 1.0e-8) {
               /* Small angle formula. */
               t = (*thetap)*D2R;
               p = atan2(*yp, *xp);
               p -= copysign(PI, p);
               zeco = (p*p + t*t)/2.0;
            }
            x0 = 4.0;
            y0 = 0.0;
            break;
         case 4:
            xi  = l;
            eta = n;
            if (zeco < 1.0e-8) {
               /* Small angle formula. */
               t = (*thetap)*D2R;
               p = atan2(*yp, *xp) + PI/2.0;
               zeco = (p*p + t*t)/2.0;
            }
            x0 = 6;
            y0 = 0.0;
            break;
         case 5:
            xi  =  m;
            eta =  l;
            if (zeco < 1.0e-8) {
               /* Small angle formula. */
               t = (*thetap + 90.0)*D2R;
               zeco = t*t/2.0;
            }
            x0 =  0.0;
            y0 = -2;
            break;
         default:
            /* face == 0 */
            xi  =  m;
            eta = -l;
            if (zeco < 1.0e-8) {
               /* Small angle formula. */
               t = (90.0 - *thetap)*D2R;
               zeco = t*t/2.0;
            }
            x0 = 0.0;
            y0 = 2.0;
            break;
         }

         xf = 0.0;
         yf = 0.0;
         if (xi != 0.0 || eta != 0.0) {
            if (-xi > fabs(eta)) {
               omega = eta/xi;
               tau = 1.0 + omega*omega;
               xf  = -sqrt(zeco/(1.0 - 1.0/sqrt(1.0+tau)));
               yf  = (xf/15.0)*(atand(omega) - asind(omega/sqrt(tau+tau)));
            } else if (xi > fabs(eta)) {
               omega = eta/xi;
               tau = 1.0 + omega*omega;
               xf  =  sqrt(zeco/(1.0 - 1.0/sqrt(1.0+tau)));
               yf  = (xf/15.0)*(atand(omega) - asind(omega/sqrt(tau+tau)));
            } else if (-eta >= fabs(xi)) {
               omega = xi/eta;
               tau = 1.0 + omega*omega;
               yf  = -sqrt(zeco/(1.0 - 1.0/sqrt(1.0+tau)));
               xf  = (yf/15.0)*(atand(omega) - asind(omega/sqrt(tau+tau)));
            } else if (eta >= fabs(xi)) {
               omega = xi/eta;
               tau = 1.0 + omega*omega;
               yf  =  sqrt(zeco/(1.0 - 1.0/sqrt(1.0+tau)));
               xf  = (yf/15.0)*(atand(omega) - asind(omega/sqrt(tau+tau)));
            }
         }
d7449 1
a7449 23
         istat = 0;
         if (fabs(xf) > 1.0) {
            if (fabs(xf) > 1.0+tol) {
               istat  = 1;
               status = 4;
            }
            xf = copysign(1.0, xf);
         }
         if (fabs(yf) > 1.0) {
            if (fabs(yf) > 1.0+tol) {
               istat  = 1;
               status = 4;
            }
            yf = copysign(1.0, yf);
         }

         *xp = prj->w[0]*(xf + x0) - prj->x0;
         *yp = prj->w[0]*(yf + y0) - prj->y0;
         *(statp++) = istat;
      }
   }

   return status;
d7489 1
a7489 1
   if (prj == 0x0) return 1;
d7491 2
a7492 2
   prj->flag = HPX;
   strcpy(prj->code, "HPX");
d7494 2
a7495 2
   if (undefined(prj->pv[1])) prj->pv[1] = 4.0;
   if (undefined(prj->pv[2])) prj->pv[2] = 3.0;
d7497 32
a7528 12
   strcpy(prj->name, "HEALPix");
   prj->category  = HEALPIX;
   prj->pvrange   = 102;
   prj->simplezen = 0;
   prj->equiareal = 1;
   prj->conformal = 0;
   prj->global    = 1;
   prj->divergent = 0;

   if (prj->pv[1] <= 0.0 || prj->pv[2] <= 0.0) {
      return 2;
   }
d7530 2
a7531 1
   prj->n = ((int)prj->pv[2])%2;
d7533 1
a7533 22
   if (prj->r0 == 0.0) {
      prj->r0 = R2D;
      prj->w[0] = 1.0;
      prj->w[1] = 1.0;
   } else {
      prj->w[0] = prj->r0*D2R;
      prj->w[1] = R2D/prj->r0;
   }

   prj->w[2] = (prj->pv[2] - 1.0) / prj->pv[2];
   prj->w[3] = 90.0 * prj->pv[2] / prj->pv[1];
   prj->w[4] = (prj->pv[2] + 1.0) / 2.0;
   prj->w[5] = 90.0 * (prj->pv[2] - 1.0) / prj->pv[1];
   prj->w[6] = 180.0 / prj->pv[1];
   prj->w[7] = prj->pv[1] / 360.0;
   prj->w[8] = prj->w[3] * prj->w[0];
   prj->w[9] = prj->w[6] * prj->w[0];

   prj->prjx2s = hpxx2s;
   prj->prjs2x = hpxs2x;

   return prjoff(prj, 0.0, 0.0);
d7547 64
a7610 55
   int h, mx, my, offset, rowlen, rowoff, status;
   double absy, s, sigma, t, yr;
   const double tol = 1.0e-12;
   register int istat, ix, iy, *statp;
   register const double *xp, *yp;
   register double *phip, *thetap;


   /* Initialize. */
   if (prj == 0x0) return 1;
   if (prj->flag != HPX) {
      if (hpxset(prj)) return 2;
   }

   if (ny > 0) {
      mx = nx;
      my = ny;
   } else {
      mx = 1;
      my = 1;
      ny = nx;
   }

   status = 0;


   /* Do x dependence. */
   xp = x;
   rowoff = 0;
   rowlen = nx*spt;
   for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
      s = prj->w[1] * (*xp + prj->x0);
      t = -180.0 + (2.0 * floor((*xp + 180.0) * prj->w[7]) + 1.0) * prj->w[6];
      t = prj->w[1] * (*xp - t);

      phip   = phi + rowoff;
      thetap = theta + rowoff;
      for (iy = 0; iy < my; iy++) {
         /* theta[] is used to hold (x - x_c). */
         *phip   = s;
         *thetap = t;
         phip   += rowlen;
         thetap += rowlen;
      }
   }


   /* Do y dependence. */
   yp = y;
   phip   = phi;
   thetap = theta;
   statp  = stat;
   for (iy = 0; iy < ny; iy++, yp += sxy) {
      yr = prj->w[1]*(*yp + prj->y0);
      absy = fabs(yr);
d7612 3
a7614 12
      istat = 0;
      if (absy <= prj->w[5]) {
         /* Equatorial regime. */
         t = asind(yr/prj->w[3]);
         for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
            *thetap = t;
            *(statp++) = 0;
         }

      } else if (absy <= 90.0) {
         /* Polar regime. */
         offset = (prj->n || *yp > 0.0) ? 0 : 1;
d7616 1
a7616 1
         sigma = prj->w[4] - absy / prj->w[6];
d7618 3
a7620 3
         if (sigma == 0.0) {
            s = 1e9;
            t = 90.0;
d7622 13
a7634 13
         } else {
            t = 1.0 - sigma*sigma/prj->pv[2];
            if (t < -1.0) {
               s = 0.0;
               t = 0.0;
               istat  = 1;
               status = 3;
            } else {
               s = 1.0/sigma;
               t = asind(t);
            }
         }
         if (*yp < 0.0) t = -t;
d7636 26
a7661 10
         for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
            if (offset) {
               /* Offset the southern polar half-facets for even K. */
               h = (int)floor(*phip / prj->w[6]);
               if (h%2) {
                  *thetap -= prj->w[6];
               } else {
                  *thetap += prj->w[6];
               }
            }
d7663 10
a7672 26
            /* Recall that theta[] holds (x - x_c). */
            s *= *thetap;
            if ((fabs(s) - prj->w[6]) < tol) {
               if (s != 0.0) s -= *thetap;
               *phip += s;
               *thetap = t;
               *(statp++) = istat;
            } else {
               /* Out-of-bounds. */
               *phip   = 0.0;
               *thetap = 0.0;
               *(statp++) = 1;
               status = 3;
            }
         }

      } else {
         /* Beyond latitude range. */
         for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
            *phip   = 0.0;
            *thetap = 0.0;
            *(statp++) = 1;
         }
         status = 3;
      }
   }
d7674 1
a7674 1
   return status;
d7688 71
a7758 82
   int h, mphi, mtheta, offset, rowlen, rowoff;
   double abssin, eta, sigma, sinthe, t, xi;
   register int iphi, itheta, *statp;
   register const double *phip, *thetap;
   register double *xp, *yp;


   /* Initialize. */
   if (prj == 0x0) return 1;
   if (prj->flag != HPX) {
      if (hpxset(prj)) return 2;
   }

   if (ntheta > 0) {
      mphi   = nphi;
      mtheta = ntheta;
   } else {
      mphi   = 1;
      mtheta = 1;
      ntheta = nphi;
   }


   /* Do phi dependence. */
   phip = phi;
   rowoff = 0;
   rowlen = nphi*sxy;
   for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
      xi = prj->w[0] * (*phip) - prj->x0;
      t  = -180.0 + (2.0*floor((*phip+180.0) * prj->w[7]) + 1.0) * prj->w[6];
      t  = prj->w[0] * (*phip - t);

      xp = x + rowoff;
      yp = y + rowoff;
      for (itheta = 0; itheta < mtheta; itheta++) {
         /* y[] is used to hold an intermediate value. */
         *xp = xi;
         *yp = t;
         xp += rowlen;
         yp += rowlen;
      }
   }


   /* Do theta dependence. */
   thetap = theta;
   xp = x;
   yp = y;
   statp = stat;
   for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
      sinthe = sind(*thetap);
      abssin = fabs(sinthe);

      if (abssin <= prj->w[2]) {
         /* Equatorial regime. */
         eta = prj->w[8] * sinthe - prj->y0;
         for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
            *yp = eta;
            *(statp++) = 0;
         }

      } else {
         /* Polar regime. */
         offset = (prj->n || *thetap > 0.0) ? 0 : 1;

         sigma = sqrt(prj->pv[2]*(1.0 - abssin));
         xi = sigma - 1.0;

         eta = prj->w[9] * (prj->w[4] - sigma);
         if (*thetap < 0) eta = -eta;
         eta -= prj->y0;

         for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
            if (offset) {
               /* Offset the southern polar half-facets for even K. */
               h = (int)floor((*xp + prj->x0) / prj->w[9]);
               if (h%2) {
                  *yp -= prj->w[9];
               } else {
                  *yp += prj->w[9];
               }
            }
d7760 15
a7774 5
            /* Recall that y[] holds an intermediate value. */
            *xp += *yp * xi;
            *yp = eta;
            *(statp++) = 0;
         }
d7776 2
a7777 1
   }
d7779 1
a7779 1
   return 0;
@


4.3.1.1
log
@WCSLIB 4.3 development branch.
@
text
@d3 2
a4 2
    WCSLIB 4.4 - an implementation of the FITS WCS standard.
    Copyright (C) 1995-2008, Mark Calabretta
d31 1
a31 1
    $Id: prj.c,v 4.3 2007/12/27 05:41:36 cal103 Exp cal103 $
@


4.3.1.2
log
@Changed indentation.
@
text
@d3 2
a4 2
  WCSLIB 4.4 - an implementation of the FITS WCS standard.
  Copyright (C) 1995-2009, Mark Calabretta
d6 1
a6 1
  This file is part of WCSLIB.
d8 24
a31 24
  WCSLIB is free software: you can redistribute it and/or modify it under the
  terms of the GNU Lesser General Public License as published by the Free
  Software Foundation, either version 3 of the License, or (at your option)
  any later version.

  WCSLIB 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 Lesser General Public License for
  more details.

  You should have received a copy of the GNU Lesser General Public License
  along with WCSLIB.  If not, see <http://www.gnu.org/licenses/>.

  Correspondence concerning WCSLIB may be directed to:
    Internet email: mcalabre@@atnf.csiro.au
    Postal address: Dr. Mark Calabretta
                    Australia Telescope National Facility, CSIRO
                    PO Box 76
                    Epping NSW 1710
                    AUSTRALIA

  Author: Mark Calabretta, Australia Telescope National Facility
  http://www.atnf.csiro.au/~mcalabre/index.html
  $Id: prj.c,v 4.3.1.1 2007/12/27 13:23:47 cal103 Exp cal103 $
d54 2
a55 2
  {"undefined", "zenithal", "cylindrical", "pseudocylindrical",
  "conventional", "conic", "polyconic", "quadcube", "HEALPix"};
d61 3
a63 3
  {"AZP", "SZP", "TAN", "STG", "SIN", "ARC", "ZPN", "ZEA", "AIR", "CYP",
   "CEA", "CAR", "MER", "COP", "COE", "COD", "COO", "SFL", "PAR", "MOL",
   "AIT", "BON", "PCO", "TSC", "CSC", "QSC", "HPX"};
d96 5
a100 5
  "Success",
  "Null prjprm pointer passed",
  "Invalid projection parameters",
  "One or more of the (x,y) coordinates were invalid",
  "One or more of the (phi,theta) coordinates were invalid"};
d129 1
a129 1
  register int k;
d131 1
a131 1
  if (prj == 0x0) return 1;
d133 1
a133 1
  prj->flag = 0;
d135 23
a157 23
  strcpy(prj->code, "   ");
  prj->pv[0]  = 0.0;
  prj->pv[1]  = UNDEFINED;
  prj->pv[2]  = UNDEFINED;
  prj->pv[3]  = UNDEFINED;
  for (k = 4; k < PVN; prj->pv[k++] = 0.0);
  prj->r0     = 0.0;
  prj->phi0   = UNDEFINED;
  prj->theta0 = UNDEFINED;
  prj->bounds = 1;

  strcpy(prj->name, "undefined");
  prj->category  = 0;
  prj->pvrange   = 0;
  prj->simplezen = 0;
  prj->equiareal = 0;
  prj->conformal = 0;
  prj->global    = 0;
  prj->divergent = 0;
  prj->x0 = 0.0;
  prj->y0 = 0.0;
  for (k = 0; k < 10; prj->w[k++] = 0.0);
  prj->n = 0;
d159 1
a159 1
  return 0;
d169 1
a169 1
  int i, n;
d171 1
a171 1
  if (prj == 0x0) return 1;
d173 65
a237 65
  printf("       flag: %d\n",  prj->flag);
  printf("       code: \"%s\"\n",  prj->code);
  printf("         r0: %9f\n", prj->r0);
  printf("         pv:");
  if (prj->pvrange) {
    n = (prj->pvrange)%100;

    if (prj->pvrange/100) {
      printf(" (0)");
    } else {
      printf(" %- 11.5g", prj->pv[0]);
      n--;
    }

    for (i = 1; i <= n; i++) {
      if (i%5 == 1) {
        printf("\n           ");
      }

      if (undefined(prj->pv[i])) {
        printf("  UNDEFINED   ");
      } else {
        printf("  %- 11.5g", prj->pv[i]);
      }
    }
    printf("\n");
  } else {
    printf(" (not used)\n");
  }
  if (undefined(prj->phi0)) {
    printf("       phi0: UNDEFINED\n");
  } else {
    printf("       phi0: %9f\n", prj->phi0);
  }
  if (undefined(prj->theta0)) {
    printf("     theta0: UNDEFINED\n");
  } else {
    printf("     theta0: %9f\n", prj->theta0);
  }
  printf("     bounds: %d\n",  prj->bounds);

  printf("\n");
  printf("       name: \"%s\"\n", prj->name);
  printf("   category: %d (%s)\n", prj->category,
                                   prj_categories[prj->category]);
  printf("    pvrange: %d\n", prj->pvrange);
  printf("  simplezen: %d\n", prj->simplezen);
  printf("  equiareal: %d\n", prj->equiareal);
  printf("  conformal: %d\n", prj->conformal);
  printf("     global: %d\n", prj->global);
  printf("  divergent: %d\n", prj->divergent);
  printf("         x0: %f\n", prj->x0);
  printf("         y0: %f\n", prj->y0);
  printf("        w[]:");
  for (i = 0; i < 5; i++) {
    printf("  %- 11.5g", prj->w[i]);
  }
  printf("\n            ");
  for (i = 5; i < 10; i++) {
    printf("  %- 11.5g", prj->w[i]);
  }
  printf("\n");
  printf("          n: %d\n", prj->n);
  printf("     prjx2s: %p\n", (void *)prj->prjx2s);
  printf("     prjs2x: %p\n", (void *)prj->prjs2x);
d239 1
a239 1
  return 0;
d249 1
a249 1
  int status;
d251 1
a251 1
  if (prj == 0x0) return 1;
d253 60
a312 60
  /* Invoke the relevant initialization routine. */
  prj->code[3] = '\0';
  if (strcmp(prj->code, "AZP") == 0) {
    status = azpset(prj);
  } else if (strcmp(prj->code, "SZP") == 0) {
    status = szpset(prj);
  } else if (strcmp(prj->code, "TAN") == 0) {
    status = tanset(prj);
  } else if (strcmp(prj->code, "STG") == 0) {
    status = stgset(prj);
  } else if (strcmp(prj->code, "SIN") == 0) {
    status = sinset(prj);
  } else if (strcmp(prj->code, "ARC") == 0) {
    status = arcset(prj);
  } else if (strcmp(prj->code, "ZPN") == 0) {
    status = zpnset(prj);
  } else if (strcmp(prj->code, "ZEA") == 0) {
    status = zeaset(prj);
  } else if (strcmp(prj->code, "AIR") == 0) {
    status = airset(prj);
  } else if (strcmp(prj->code, "CYP") == 0) {
    status = cypset(prj);
  } else if (strcmp(prj->code, "CEA") == 0) {
    status = ceaset(prj);
  } else if (strcmp(prj->code, "CAR") == 0) {
    status = carset(prj);
  } else if (strcmp(prj->code, "MER") == 0) {
    status = merset(prj);
  } else if (strcmp(prj->code, "SFL") == 0) {
    status = sflset(prj);
  } else if (strcmp(prj->code, "PAR") == 0) {
    status = parset(prj);
  } else if (strcmp(prj->code, "MOL") == 0) {
    status = molset(prj);
  } else if (strcmp(prj->code, "AIT") == 0) {
    status = aitset(prj);
  } else if (strcmp(prj->code, "COP") == 0) {
    status = copset(prj);
  } else if (strcmp(prj->code, "COE") == 0) {
    status = coeset(prj);
  } else if (strcmp(prj->code, "COD") == 0) {
    status = codset(prj);
  } else if (strcmp(prj->code, "COO") == 0) {
    status = cooset(prj);
  } else if (strcmp(prj->code, "BON") == 0) {
    status = bonset(prj);
  } else if (strcmp(prj->code, "PCO") == 0) {
    status = pcoset(prj);
  } else if (strcmp(prj->code, "TSC") == 0) {
    status = tscset(prj);
  } else if (strcmp(prj->code, "CSC") == 0) {
    status = cscset(prj);
  } else if (strcmp(prj->code, "QSC") == 0) {
    status = qscset(prj);
  } else if (strcmp(prj->code, "HPX") == 0) {
    status = hpxset(prj);
  } else {
    /* Unrecognized projection code. */
    status = 2;
  }
d314 1
a314 1
  return status;
d328 5
a332 5
  /* Initialize. */
  if (prj == 0x0) return 1;
  if (prj->flag == 0) {
    if (prjset(prj)) return 2;
  }
d334 1
a334 1
  return prj->prjx2s(prj, nx, ny, sxy, spt, x, y, phi, theta, stat);
d348 5
a352 5
  /* Initialize. */
  if (prj == 0x0) return 1;
  if (prj->flag == 0) {
    if (prjset(prj)) return 2;
  }
d354 1
a354 1
  return prj->prjs2x(prj, nphi, ntheta, spt, sxy, phi, theta, x, y, stat);
d368 1
a368 1
  int    stat;
d370 1
a370 1
  if (prj == 0x0) return 1;
d372 4
a375 4
  if (undefined(prj->phi0) || undefined(prj->theta0)) {
    /* Set both to the projection-specific default if either undefined. */
    prj->phi0   = phi0;
    prj->theta0 = theta0;
d377 2
a378 2
    prj->x0 = 0.0;
    prj->y0 = 0.0;
d380 6
a385 6
  } else {
    if (prj->prjs2x(prj, 1, 1, 1, 1, &(prj->phi0), &(prj->theta0),
                    &(prj->x0), &(prj->y0), &stat)) {
      return 2;
    }
  }
d387 1
a387 1
  return 0;
d424 17
a440 1
  if (prj == 0x0) return 1;
d442 13
a454 2
  prj->flag = AZP;
  strcpy(prj->code, "AZP");
d456 5
a460 32
  if (undefined(prj->pv[1])) prj->pv[1] = 0.0;
  if (undefined(prj->pv[2])) prj->pv[2] = 0.0;
  if (prj->r0 == 0.0) prj->r0 = R2D;

  strcpy(prj->name, "zenithal/azimuthal perspective");
  prj->category  = ZENITHAL;
  prj->pvrange   = 102;
  prj->simplezen = prj->pv[2] == 0.0;
  prj->equiareal = 0;
  prj->conformal = 0;
  prj->global    = 0;
  prj->divergent = prj->pv[1] <= 1.0;

  prj->w[0] = prj->r0*(prj->pv[1] + 1.0);
  if (prj->w[0] == 0.0) {
    return 2;
  }

  prj->w[3] = cosd(prj->pv[2]);
  if (prj->w[3] == 0.0) {
    return 2;
  }

  prj->w[2] = 1.0/prj->w[3];
  prj->w[4] = sind(prj->pv[2]);
  prj->w[1] = prj->w[4] / prj->w[3];

  if (fabs(prj->pv[1]) > 1.0) {
    prj->w[5] = asind(-1.0/prj->pv[1]);
  } else {
    prj->w[5] = -90.0;
  }
d462 2
a463 2
  prj->w[6] = prj->pv[1] * prj->w[3];
  prj->w[7] = (fabs(prj->w[6]) < 1.0) ? 1.0 : 0.0;
d465 2
a466 2
  prj->prjx2s = azpx2s;
  prj->prjs2x = azps2x;
d468 1
a468 1
  return prjoff(prj, 0.0, 90.0);
d482 48
a529 62
  int mx, my, rowlen, rowoff, status;
  double a, b, q, r, s, t, xj, yj, yc, yc2;
  const double tol = 1.0e-13;
  register int ix, iy, *statp;
  register const double *xp, *yp;
  register double *phip, *thetap;


  /* Initialize. */
  if (prj == 0x0) return 1;
  if (prj->flag != AZP) {
    if (azpset(prj)) return 2;
  }

  if (ny > 0) {
    mx = nx;
    my = ny;
  } else {
    mx = 1;
    my = 1;
    ny = nx;
  }

  status = 0;


  /* Do x dependence. */
  xp = x;
  rowoff = 0;
  rowlen = nx*spt;
  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    xj = *xp + prj->x0;

    phip = phi + rowoff;
    for (iy = 0; iy < my; iy++) {
      *phip = xj;
      phip += rowlen;
    }
  }


  /* Do y dependence. */
  yp = y;
  phip   = phi;
  thetap = theta;
  statp  = stat;
  for (iy = 0; iy < ny; iy++, yp += sxy) {
    yj = *yp + prj->y0;

    yc  = yj*prj->w[3];
    yc2 = yc*yc;

    q = prj->w[0] + yj*prj->w[4];

    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
      xj = *phip;

      r = sqrt(xj*xj + yc2);
      if (r == 0.0) {
        *phip = 0.0;
        *thetap = 90.0;
        *(statp++) = 0;
d531 2
a532 2
      } else {
        *phip = atan2d(xj, -yc);
d534 1
a534 2
        s = r / q;
        t = s*prj->pv[1]/sqrt(s*s + 1.0);
d536 2
a537 1
        s = atan2d(1.0, s);
d539 25
a563 11
        if (fabs(t) > 1.0) {
          if (fabs(t) > 1.0+tol) {
            *thetap = 0.0;
            *(statp++) = 1;
            status = 3;
            continue;
          }
          t = copysign(90.0, t);
        } else {
          t = asind(t);
        }
d565 2
a566 2
        a = s - t;
        b = s + t + 180.0;
d568 2
a569 2
        if (a > 90.0) a -= 360.0;
        if (b > 90.0) b -= 360.0;
d571 3
a573 2
        *thetap = (a > b) ? a : b;
        *(statp++) = 0;
d575 1
a575 2
    }
  }
d577 1
a577 1
  return status;
d591 56
a646 56
  int mphi, mtheta, rowlen, rowoff, status;
  double a, b, cosphi, costhe, r, s, sinphi, sinthe, t;
  register int iphi, itheta, istat, *statp;
  register const double *phip, *thetap;
  register double *xp, *yp;


  /* Initialize. */
  if (prj == 0x0) return 1;
  if (prj->flag != AZP) {
    if (azpset(prj)) return 2;
  }

  if (ntheta > 0) {
    mphi   = nphi;
    mtheta = ntheta;
  } else {
    mphi   = 1;
    mtheta = 1;
    ntheta = nphi;
  }

  status = 0;


  /* Do phi dependence. */
  phip = phi;
  rowoff = 0;
  rowlen = nphi*sxy;
  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    sinphi = sind(*phip);
    cosphi = cosd(*phip);

    xp = x + rowoff;
    yp = y + rowoff;
    for (itheta = 0; itheta < mtheta; itheta++) {
      *xp = sinphi;
      *yp = cosphi;
      xp += rowlen;
      yp += rowlen;
    }
  }


  /* Do theta dependence. */
  thetap = theta;
  xp = x;
  yp = y;
  statp = stat;
  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    costhe = cosd(*thetap);
    sinthe = sind(*thetap);

    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
      s = prj->w[1]*(*yp);
      t = (prj->pv[1] + sinthe) + costhe*s;
d648 5
a652 5
      if (t == 0.0) {
        *xp = 0.0;
        *yp = 0.0;
        *(statp++) = 1;
        status = 4;
d654 2
a655 2
      } else {
        r = prj->w[0]*costhe/t;
d657 28
a684 7
        /* Bounds checking. */
        istat = 0;
        if (prj->bounds) {
          if (*thetap < prj->w[5]) {
            /* Overlap. */
            istat  = 1;
            status = 4;
d686 4
a689 24
          } else if (prj->w[7] > 0.0) {
            /* Divergence. */
            t = prj->pv[1] / sqrt(1.0 + s*s);

            if (fabs(t) <= 1.0) {
              s = atand(-s);
              t = asind(t);
              a = s - t;
              b = s + t + 180.0;

              if (a > 90.0) a -= 360.0;
              if (b > 90.0) b -= 360.0;

              if (*thetap < ((a > b) ? a : b)) {
                istat  = 1;
                status = 4;
              }
            }
          }
        }

        *xp =  r*(*xp) - prj->x0;
        *yp = -r*(*yp)*prj->w[2] - prj->y0;
        *(statp++) = istat;
d691 1
a691 2
    }
  }
d693 1
a693 1
  return status;
d735 18
a752 1
  if (prj == 0x0) return 1;
d754 1
a754 2
  prj->flag = SZP;
  strcpy(prj->code, "SZP");
d756 17
a772 33
  if (undefined(prj->pv[1])) prj->pv[1] =  0.0;
  if (undefined(prj->pv[2])) prj->pv[2] =  0.0;
  if (undefined(prj->pv[3])) prj->pv[3] = 90.0;
  if (prj->r0 == 0.0) prj->r0 = R2D;

  strcpy(prj->name, "slant zenithal perspective");
  prj->category  = ZENITHAL;
  prj->pvrange   = 103;
  prj->simplezen = prj->pv[3] == 90.0;
  prj->equiareal = 0;
  prj->conformal = 0;
  prj->global    = 0;
  prj->divergent = prj->pv[1] <= 1.0;

  prj->w[0] = 1.0/prj->r0;

  prj->w[3] = prj->pv[1] * sind(prj->pv[3]) + 1.0;
  if (prj->w[3] == 0.0) {
    return 2;
  }

  prj->w[1] = -prj->pv[1] * cosd(prj->pv[3]) * sind(prj->pv[2]);
  prj->w[2] =  prj->pv[1] * cosd(prj->pv[3]) * cosd(prj->pv[2]);
  prj->w[4] =  prj->r0 * prj->w[1];
  prj->w[5] =  prj->r0 * prj->w[2];
  prj->w[6] =  prj->r0 * prj->w[3];
  prj->w[7] =  (prj->w[3] - 1.0) * prj->w[3] - 1.0;

  if (fabs(prj->w[3] - 1.0) < 1.0) {
    prj->w[8] = asind(1.0 - prj->w[3]);
  } else {
    prj->w[8] = -90.0;
  }
d774 2
a775 2
  prj->prjx2s = szpx2s;
  prj->prjs2x = szps2x;
d777 1
a777 1
  return prjoff(prj, 0.0, 90.0);
d791 90
a880 61
  int mx, my, rowlen, rowoff, status;
  double a, b, c, d, r2, sinth1, sinth2, sinthe, t, x1, xr, xy, y1, yr, z;
  const double tol = 1.0e-13;
  register int ix, iy, *statp;
  register const double *xp, *yp;
  register double *phip, *thetap;


  /* Initialize. */
  if (prj == 0x0) return 1;
  if (prj->flag != SZP) {
    if (szpset(prj)) return 2;
  }

  if (ny > 0) {
    mx = nx;
    my = ny;
  } else {
    mx = 1;
    my = 1;
    ny = nx;
  }

  status = 0;


  /* Do x dependence. */
  xp = x;
  rowoff = 0;
  rowlen = nx*spt;
  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    xr = (*xp + prj->x0)*prj->w[0];

    phip = phi + rowoff;
    for (iy = 0; iy < my; iy++) {
      *phip = xr;
      phip += rowlen;
    }
  }


  /* Do y dependence. */
  yp = y;
  phip   = phi;
  thetap = theta;
  statp  = stat;
  for (iy = 0; iy < ny; iy++, yp += sxy) {
    yr = (*yp + prj->y0)*prj->w[0];

    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
      xr = *phip;
      r2 = xr*xr + yr*yr;

      x1 = (xr - prj->w[1])/prj->w[3];
      y1 = (yr - prj->w[2])/prj->w[3];
      xy = xr*x1 + yr*y1;

      if (r2 < 1.0e-10) {
        /* Use small angle formula. */
        z = r2/2.0;
        *thetap = 90.0 - R2D*sqrt(r2/(1.0 + xy));
d882 23
a904 52
      } else {
        t = x1*x1 + y1*y1;
        a = t + 1.0;
        b = xy - t;
        c = r2 - xy - xy + t - 1.0;
        d = b*b - a*c;

        /* Check for a solution. */
        if (d < 0.0) {
          *phip = 0.0;
          *thetap = 0.0;
          *(statp++) = 1;
          status = 3;
          continue;
        }
        d = sqrt(d);

        /* Choose solution closest to pole. */
        sinth1 = (-b + d)/a;
        sinth2 = (-b - d)/a;
        sinthe = (sinth1 > sinth2) ? sinth1 : sinth2;
        if (sinthe > 1.0) {
          if (sinthe-1.0 < tol) {
            sinthe = 1.0;
          } else {
            sinthe = (sinth1 < sinth2) ? sinth1 : sinth2;
          }
        }

        if (sinthe < -1.0) {
          if (sinthe+1.0 > -tol) {
            sinthe = -1.0;
          }
        }

        if (sinthe > 1.0 || sinthe < -1.0) {
          *phip   = 0.0;
          *thetap = 0.0;
          *(statp++) = 1;
          status = 3;
          continue;
        }

        *thetap = asind(sinthe);

        z = 1.0 - sinthe;
      }

      *phip = atan2d(xr - x1*z, -(yr - y1*z));
      *(statp++) = 0;
    }
  }
d906 1
a906 1
  return status;
d920 52
a971 52
  int mphi, mtheta, rowlen, rowoff, status;
  double a, b, cosphi, r, s, sinphi, t, u, v;
  register int iphi, itheta, istat, *statp;
  register const double *phip, *thetap;
  register double *xp, *yp;


  /* Initialize. */
  if (prj == 0x0) return 1;
  if (prj->flag != SZP) {
    if (szpset(prj)) return 2;
  }

  if (ntheta > 0) {
    mphi   = nphi;
    mtheta = ntheta;
  } else {
    mphi   = 1;
    mtheta = 1;
    ntheta = nphi;
  }

  status = 0;


  /* Do phi dependence. */
  phip = phi;
  rowoff = 0;
  rowlen = nphi*sxy;
  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    sinphi = sind(*phip);
    cosphi = cosd(*phip);

    xp = x + rowoff;
    yp = y + rowoff;
    for (itheta = 0; itheta < mtheta; itheta++) {
      *xp = sinphi;
      *yp = cosphi;
      xp += rowlen;
      yp += rowlen;
    }
  }


  /* Do theta dependence. */
  thetap = theta;
  xp = x;
  yp = y;
  statp = stat;
  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    s = 1.0 - sind(*thetap);
    t = prj->w[3] - s;
d973 6
a978 6
    if (t == 0.0) {
      for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
        *xp = 0.0;
        *yp = 0.0;
        *(statp++) = 1;
      }
d980 1
a980 1
      status = 4;
d982 35
a1016 13
    } else {
      r = prj->w[6]*cosd(*thetap)/t;
      u = prj->w[4]*s/t + prj->x0;
      v = prj->w[5]*s/t + prj->y0;

      for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
        /* Bounds checking. */
        istat = 0;
        if (prj->bounds) {
          if (*thetap < prj->w[8]) {
            /* Divergence. */
            istat  = 1;
            status = 4;
d1018 4
a1021 25
          } else if (fabs(prj->pv[1]) > 1.0) {
            /* Overlap. */
            s = prj->w[1]*(*xp) - prj->w[2]*(*yp);
            t = 1.0/sqrt(prj->w[7] + s*s);

            if (fabs(t) <= 1.0) {
              s = atan2d(s, prj->w[3] - 1.0);
              t = asind(t);
              a = s - t;
              b = s + t + 180.0;

              if (a > 90.0) a -= 360.0;
              if (b > 90.0) b -= 360.0;

              if (*thetap < ((a > b) ? a : b)) {
                istat  = 1;
                status = 4;
              }
            }
          }
        }

        *xp =  r*(*xp) - u;
        *yp = -r*(*yp) - v;
        *(statp++) = istat;
d1023 1
a1023 2
    }
  }
d1025 1
a1025 1
  return status;
d1051 1
a1051 1
  if (prj == 0x0) return 1;
d1053 2
a1054 2
  prj->flag = TAN;
  strcpy(prj->code, "TAN");
d1056 1
a1056 1
  if (prj->r0 == 0.0) prj->r0 = R2D;
d1058 8
a1065 8
  strcpy(prj->name, "gnomonic");
  prj->category  = ZENITHAL;
  prj->pvrange   = 0;
  prj->simplezen = 1;
  prj->equiareal = 0;
  prj->conformal = 0;
  prj->global    = 0;
  prj->divergent = 1;
d1067 2
a1068 2
  prj->prjx2s = tanx2s;
  prj->prjs2x = tans2x;
d1070 1
a1070 1
  return prjoff(prj, 0.0, 90.0);
d1084 59
a1142 55
  int mx, my, rowlen, rowoff;
  double r, xj, yj, yj2;
  register int ix, iy, *statp;
  register const double *xp, *yp;
  register double *phip, *thetap;


  /* Initialize. */
  if (prj == 0x0) return 1;
  if (prj->flag != TAN) {
    if (tanset(prj)) return 2;
  }

  if (ny > 0) {
    mx = nx;
    my = ny;
  } else {
    mx = 1;
    my = 1;
    ny = nx;
  }


  /* Do x dependence. */
  xp = x;
  rowoff = 0;
  rowlen = nx*spt;
  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    xj = *xp + prj->x0;

    phip = phi + rowoff;
    for (iy = 0; iy < my; iy++) {
      *phip = xj;
      phip += rowlen;
    }
  }


  /* Do y dependence. */
  yp = y;
  phip   = phi;
  thetap = theta;
  statp  = stat;
  for (iy = 0; iy < ny; iy++, yp += sxy) {
    yj  = *yp + prj->y0;
    yj2 = yj*yj;

    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
      xj = *phip;

      r = sqrt(xj*xj + yj2);
      if (r == 0.0) {
        *phip = 0.0;
      } else {
        *phip = atan2d(xj, -yj);
d1144 1
d1146 1
a1146 6
      *thetap = atan2d(prj->r0, r);
      *(statp++) = 0;
    }
  }

  return 0;
d1160 58
a1217 58
  int mphi, mtheta, rowlen, rowoff, status;
  double cosphi, r, s, sinphi;
  register int iphi, itheta, istat, *statp;
  register const double *phip, *thetap;
  register double *xp, *yp;


  /* Initialize. */
  if (prj == 0x0) return 1;
  if (prj->flag != TAN) {
    if (tanset(prj)) return 2;
  }

  if (ntheta > 0) {
    mphi   = nphi;
    mtheta = ntheta;
  } else {
    mphi   = 1;
    mtheta = 1;
    ntheta = nphi;
  }

  status = 0;


  /* Do phi dependence. */
  phip = phi;
  rowoff = 0;
  rowlen = nphi*sxy;
  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    sinphi = sind(*phip);
    cosphi = cosd(*phip);

    xp = x + rowoff;
    yp = y + rowoff;
    for (itheta = 0; itheta < mtheta; itheta++) {
      *xp = sinphi;
      *yp = cosphi;
      xp += rowlen;
      yp += rowlen;
    }
  }


  /* Do theta dependence. */
  thetap = theta;
  xp = x;
  yp = y;
  statp = stat;
  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    s = sind(*thetap);
    if (s == 0.0) {
      for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
        *xp = 0.0;
        *yp = 0.0;
        *(statp++) = 1;
      }
      status = 4;
d1219 2
a1220 2
    } else {
      r =  prj->r0*cosd(*thetap)/s;
d1222 5
a1226 5
      istat = 0;
      if (prj->bounds && s < 0.0) {
        istat  = 1;
        status = 4;
      }
d1228 5
a1232 4
      for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
        *xp =  r*(*xp) - prj->x0;
        *yp = -r*(*yp) - prj->y0;
        *(statp++) = istat;
d1234 1
a1234 2
    }
  }
d1236 1
a1236 1
  return status;
d1263 1
a1263 1
  if (prj == 0x0) return 1;
d1265 2
a1266 2
  prj->flag = STG;
  strcpy(prj->code, "STG");
d1268 17
a1284 17
  strcpy(prj->name, "stereographic");
  prj->category  = ZENITHAL;
  prj->pvrange   = 0;
  prj->simplezen = 1;
  prj->equiareal = 0;
  prj->conformal = 1;
  prj->global    = 0;
  prj->divergent = 1;

  if (prj->r0 == 0.0) {
    prj->r0 = R2D;
    prj->w[0] = 360.0/PI;
    prj->w[1] = PI/360.0;
  } else {
    prj->w[0] = 2.0*prj->r0;
    prj->w[1] = 1.0/prj->w[0];
  }
d1286 2
a1287 2
  prj->prjx2s = stgx2s;
  prj->prjs2x = stgs2x;
d1289 1
a1289 1
  return prjoff(prj, 0.0, 90.0);
d1303 59
a1361 55
  int mx, my, rowlen, rowoff;
  double r, xj, yj, yj2;
  register int ix, iy, *statp;
  register const double *xp, *yp;
  register double *phip, *thetap;


  /* Initialize. */
  if (prj == 0x0) return 1;
  if (prj->flag != STG) {
    if (stgset(prj)) return 2;
  }

  if (ny > 0) {
    mx = nx;
    my = ny;
  } else {
    mx = 1;
    my = 1;
    ny = nx;
  }


  /* Do x dependence. */
  xp = x;
  rowoff = 0;
  rowlen = nx*spt;
  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    xj = *xp + prj->x0;

    phip = phi + rowoff;
    for (iy = 0; iy < my; iy++) {
      *phip = xj;
      phip += rowlen;
    }
  }


  /* Do y dependence. */
  yp = y;
  phip   = phi;
  thetap = theta;
  statp  = stat;
  for (iy = 0; iy < ny; iy++, yp += sxy) {
    yj  = *yp + prj->y0;
    yj2 = yj*yj;

    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
      xj  = *phip;

      r = sqrt(xj*xj + yj2);
      if (r == 0.0) {
        *phip = 0.0;
      } else {
        *phip = atan2d(xj, -yj);
d1363 1
d1365 1
a1365 6
      *thetap = 90.0 - 2.0*atand(r*prj->w[1]);
      *(statp++) = 0;
    }
  }

  return 0;
d1379 58
a1436 58
  int mphi, mtheta, rowlen, rowoff, status;
  double cosphi, r, s, sinphi;
  register int iphi, itheta, *statp;
  register const double *phip, *thetap;
  register double *xp, *yp;


  /* Initialize. */
  if (prj == 0x0) return 1;
  if (prj->flag != STG) {
    if (stgset(prj)) return 2;
  }

  if (ntheta > 0) {
    mphi   = nphi;
    mtheta = ntheta;
  } else {
    mphi   = 1;
    mtheta = 1;
    ntheta = nphi;
  }

  status = 0;


  /* Do phi dependence. */
  phip = phi;
  rowoff = 0;
  rowlen = nphi*sxy;
  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    sinphi = sind(*phip);
    cosphi = cosd(*phip);

    xp = x + rowoff;
    yp = y + rowoff;
    for (itheta = 0; itheta < mtheta; itheta++) {
      *xp = sinphi;
      *yp = cosphi;
      xp += rowlen;
      yp += rowlen;
    }
  }


  /* Do theta dependence. */
  thetap = theta;
  xp = x;
  yp = y;
  statp = stat;
  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    s = 1.0 + sind(*thetap);
    if (s == 0.0) {
      for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
        *xp = 0.0;
        *yp = 0.0;
        *(statp++) = 1;
      }
      status = 4;
d1438 2
a1439 2
    } else {
      r = prj->w[0]*cosd(*thetap)/s;
d1441 5
a1445 4
      for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
        *xp =  r*(*xp) - prj->x0;
        *yp = -r*(*yp) - prj->y0;
        *(statp++) = 0;
d1447 1
a1447 2
    }
  }
d1449 1
a1449 1
  return status;
d1481 1
a1481 1
  if (prj == 0x0) return 1;
d1483 2
a1484 2
  prj->flag = SIN;
  strcpy(prj->code, "SIN");
d1486 17
a1502 17
  if (undefined(prj->pv[1])) prj->pv[1] = 0.0;
  if (undefined(prj->pv[2])) prj->pv[2] = 0.0;
  if (prj->r0 == 0.0) prj->r0 = R2D;

  strcpy(prj->name, "orthographic/synthesis");
  prj->category  = ZENITHAL;
  prj->pvrange   = 102;
  prj->simplezen = (prj->pv[1] == 0.0 && prj->pv[2] == 0.0);
  prj->equiareal = 0;
  prj->conformal = 0;
  prj->global    = 0;
  prj->divergent = 0;

  prj->w[0] = 1.0/prj->r0;
  prj->w[1] = prj->pv[1]*prj->pv[1] + prj->pv[2]*prj->pv[2];
  prj->w[2] = prj->w[1] + 1.0;
  prj->w[3] = prj->w[1] - 1.0;
d1504 2
a1505 2
  prj->prjx2s = sinx2s;
  prj->prjs2x = sins2x;
d1507 1
a1507 1
  return prjoff(prj, 0.0, 90.0);
d1521 127
a1647 58
  int mx, my, rowlen, rowoff, status;
  const double tol = 1.0e-13;
  double a, b, c, d, eta, r2, sinth1, sinth2, sinthe, x0, xi, x1, xy, y0, y02,
         y1, z;
  register int ix, iy, *statp;
  register const double *xp, *yp;
  register double *phip, *thetap;


  /* Initialize. */
  if (prj == 0x0) return 1;
  if (prj->flag != SIN) {
    if (sinset(prj)) return 2;
  }

  xi  = prj->pv[1];
  eta = prj->pv[2];

  if (ny > 0) {
    mx = nx;
    my = ny;
  } else {
    mx = 1;
    my = 1;
    ny = nx;
  }

  status = 0;


  /* Do x dependence. */
  xp = x;
  rowoff = 0;
  rowlen = nx*spt;
  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    x0 = (*xp + prj->x0)*prj->w[0];

    phip = phi + rowoff;
    for (iy = 0; iy < my; iy++) {
      *phip = x0;
      phip += rowlen;
    }
  }


  /* Do y dependence. */
  yp = y;
  phip   = phi;
  thetap = theta;
  statp  = stat;
  for (iy = 0; iy < ny; iy++, yp += sxy) {
    y0 = (*yp + prj->y0)*prj->w[0];
    y02 = y0*y0;

    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
      /* Compute intermediaries. */
      x0 = *phip;
      r2 = x0*x0 + y02;
d1649 3
a1651 17
      if (prj->w[1] == 0.0) {
        /* Orthographic projection. */
        if (r2 != 0.0) {
          *phip = atan2d(x0, -y0);
        } else {
          *phip = 0.0;
        }

        if (r2 < 0.5) {
          *thetap = acosd(sqrt(r2));
        } else if (r2 <= 1.0) {
          *thetap = asind(sqrt(1.0 - r2));
        } else {
          *(statp++) = 1;
          status = 3;
          continue;
        }
d1653 8
a1660 3
      } else {
        /* "Synthesis" projection. */
        xy = x0*xi + y0*eta;
d1662 3
a1664 63
        if (r2 < 1.0e-10) {
           /* Use small angle formula. */
           z = r2/2.0;
           *thetap = 90.0 - R2D*sqrt(r2/(1.0 + xy));

        } else {
           a = prj->w[2];
           b = xy - prj->w[1];
           c = r2 - xy - xy + prj->w[3];
           d = b*b - a*c;

           /* Check for a solution. */
           if (d < 0.0) {
             *phip = 0.0;
             *thetap = 0.0;
             *(statp++) = 1;
             status = 3;
             continue;
           }
           d = sqrt(d);

           /* Choose solution closest to pole. */
           sinth1 = (-b + d)/a;
           sinth2 = (-b - d)/a;
           sinthe = (sinth1 > sinth2) ? sinth1 : sinth2;
           if (sinthe > 1.0) {
             if (sinthe-1.0 < tol) {
               sinthe = 1.0;
             } else {
               sinthe = (sinth1 < sinth2) ? sinth1 : sinth2;
             }
           }

           if (sinthe < -1.0) {
             if (sinthe+1.0 > -tol) {
               sinthe = -1.0;
             }
           }

           if (sinthe > 1.0 || sinthe < -1.0) {
             *phip = 0.0;
             *thetap = 0.0;
             *(statp++) = 1;
             status = 3;
             continue;
           }

           *thetap = asind(sinthe);
           z = 1.0 - sinthe;
        }

        x1 = -y0 + eta*z;
        y1 =  x0 -  xi*z;
        if (x1 == 0.0 && y1 == 0.0) {
          *phip = 0.0;
        } else {
          *phip = atan2d(y1,x1);
        }
      }

      *(statp++) = 0;
    }
  }
d1666 1
a1666 1
  return status;
d1680 58
a1737 54
  int mphi, mtheta, rowlen, rowoff, status;
  double cosphi, costhe, sinphi, r, t, z, z1, z2;
  register int iphi, itheta, istat, *statp;
  register const double *phip, *thetap;
  register double *xp, *yp;


  /* Initialize. */
  if (prj == 0x0) return 1;
  if (prj->flag != SIN) {
    if (sinset(prj)) return 2;
  }

  if (ntheta > 0) {
    mphi   = nphi;
    mtheta = ntheta;
  } else {
    mphi   = 1;
    mtheta = 1;
    ntheta = nphi;
  }

  status = 0;


  /* Do phi dependence. */
  phip = phi;
  rowoff = 0;
  rowlen = nphi*sxy;
  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    sinphi = sind(*phip);
    cosphi = cosd(*phip);

    xp = x + rowoff;
    yp = y + rowoff;
    for (itheta = 0; itheta < mtheta; itheta++) {
      *xp = sinphi;
      *yp = cosphi;
      xp += rowlen;
      yp += rowlen;
    }
  }


  /* Do theta dependence. */
  thetap = theta;
  xp = x;
  yp = y;
  statp = stat;
  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    t = (90.0 - fabs(*thetap))*D2R;
    if (t < 1.0e-5) {
      if (*thetap > 0.0) {
         z = t*t/2.0;
d1739 2
a1740 1
         z = 2.0 - t*t/2.0;
d1742 1
a1742 6
      costhe = t;
    } else {
      z = 1.0 - sind(*thetap);
      costhe = cosd(*thetap);
    }
    r = prj->r0*costhe;
d1744 4
a1747 25
    if (prj->w[1] == 0.0) {
      /* Orthographic projection. */
      istat = 0;
      if (prj->bounds && *thetap < 0.0) {
        istat  = 1;
        status = 4;
      }

      for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
        *xp =  r*(*xp) - prj->x0;
        *yp = -r*(*yp) - prj->y0;
        *(statp++) = istat;
      }

    } else {
      /* "Synthesis" projection. */
      z *= prj->r0;
      z1 = prj->pv[1]*z - prj->x0;
      z2 = prj->pv[2]*z - prj->y0;

      for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
        istat = 0;
        if (prj->bounds) {
          t = -atand(prj->pv[1]*(*xp) - prj->pv[2]*(*yp));
          if (*thetap < t) {
d1750 1
a1750 2
          }
        }
d1752 26
a1777 3
        *xp =  r*(*xp) + z1;
        *yp = -r*(*yp) + z2;
        *(statp++) = istat;
d1779 1
a1779 2
    }
  }
d1781 1
a1781 1
  return status;
d1808 1
a1808 1
  if (prj == 0x0) return 1;
d1810 2
a1811 2
  prj->flag = ARC;
  strcpy(prj->code, "ARC");
d1813 17
a1829 17
  strcpy(prj->name, "zenithal/azimuthal equidistant");
  prj->category  = ZENITHAL;
  prj->pvrange   = 0;
  prj->simplezen = 1;
  prj->equiareal = 0;
  prj->conformal = 0;
  prj->global    = 1;
  prj->divergent = 0;

  if (prj->r0 == 0.0) {
    prj->r0 = R2D;
    prj->w[0] = 1.0;
    prj->w[1] = 1.0;
  } else {
    prj->w[0] = prj->r0*D2R;
    prj->w[1] = 1.0/prj->w[0];
  }
d1831 2
a1832 2
  prj->prjx2s = arcx2s;
  prj->prjs2x = arcs2x;
d1834 1
a1834 1
  return prjoff(prj, 0.0, 90.0);
d1848 60
a1907 57
  int mx, my, rowlen, rowoff;
  double r, xj, yj, yj2;
  register int ix, iy, *statp;
  register const double *xp, *yp;
  register double *phip, *thetap;


  /* Initialize. */
  if (prj == 0x0) return 1;
  if (prj->flag != ARC) {
    if (arcset(prj)) return 2;
  }

  if (ny > 0) {
    mx = nx;
    my = ny;
  } else {
    mx = 1;
    my = 1;
    ny = nx;
  }


  /* Do x dependence. */
  xp = x;
  rowoff = 0;
  rowlen = nx*spt;
  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    xj = *xp + prj->x0;

    phip = phi + rowoff;
    for (iy = 0; iy < my; iy++) {
      *phip = xj;
      phip += rowlen;
    }
  }


  /* Do y dependence. */
  yp = y;
  phip   = phi;
  thetap = theta;
  statp  = stat;
  for (iy = 0; iy < ny; iy++, yp += sxy) {
    yj  = *yp + prj->y0;
    yj2 = yj*yj;

    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
      xj = *phip;

      r = sqrt(xj*xj + yj2);
      if (r == 0.0) {
        *phip = 0.0;
        *thetap = 90.0;
      } else {
        *phip = atan2d(xj, -yj);
        *thetap = 90.0 - r*prj->w[1];
d1909 1
d1911 1
a1911 5
      *(statp++) = 0;
    }
  }

  return 0;
d1925 49
a1973 56
  int mphi, mtheta, rowlen, rowoff;
  double cosphi, r, sinphi;
  register int iphi, itheta, *statp;
  register const double *phip, *thetap;
  register double *xp, *yp;


  /* Initialize. */
  if (prj == 0x0) return 1;
  if (prj->flag != ARC) {
    if (arcset(prj)) return 2;
  }

  if (ntheta > 0) {
    mphi   = nphi;
    mtheta = ntheta;
  } else {
    mphi   = 1;
    mtheta = 1;
    ntheta = nphi;
  }


  /* Do phi dependence. */
  phip = phi;
  rowoff = 0;
  rowlen = nphi*sxy;
  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    sinphi = sind(*phip);
    cosphi = cosd(*phip);

    xp = x + rowoff;
    yp = y + rowoff;
    for (itheta = 0; itheta < mtheta; itheta++) {
      *xp = sinphi;
      *yp = cosphi;
      xp += rowlen;
      yp += rowlen;
    }
  }


  /* Do theta dependence. */
  thetap = theta;
  xp = x;
  yp = y;
  statp = stat;
  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    r =  prj->w[0]*(90.0 - *thetap);

    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
      *xp =  r*(*xp) - prj->x0;
      *yp = -r*(*yp) - prj->y0;
      *(statp++) = 0;
    }
  }
d1975 8
a1982 1
  return 0;
d2013 79
a2091 40
  int j, k, m;
  double d, d1, d2, r, zd, zd1, zd2;
  const double tol = 1.0e-13;

  if (prj == 0x0) return 1;

  strcpy(prj->code, "ZPN");
  prj->flag = ZPN;

  if (undefined(prj->pv[1])) prj->pv[1] = 0.0;
  if (undefined(prj->pv[2])) prj->pv[2] = 0.0;
  if (undefined(prj->pv[3])) prj->pv[3] = 0.0;
  if (prj->r0 == 0.0) prj->r0 = R2D;

  strcpy(prj->name, "zenithal/azimuthal polynomial");
  prj->category  = ZENITHAL;
  prj->pvrange   = 30;
  prj->simplezen = 1;
  prj->equiareal = 0;
  prj->conformal = 0;
  prj->global    = 0;
  prj->divergent = 0;

  /* Find the highest non-zero coefficient. */
  for (k = PVN-1; k >= 0 && prj->pv[k] == 0.0; k--);
  if (k < 0) return 2;

  prj->n = k;

  if (k < 2) {
    /* No point of inflection. */
    prj->w[0] = PI;

  } else {
    /* Find the point of inflection closest to the pole. */
    zd1 = 0.0;
    d1  = prj->pv[1];
    if (d1 <= 0.0) {
      return 2;
    }
d2093 7
a2099 46
    /* Find the point where the derivative first goes negative. */
    for (j = 0; j < 180; j++) {
      zd2 = j*D2R;
      d2  = 0.0;
      for (m = k; m > 0; m--) {
        d2 = d2*zd2 + m*prj->pv[m];
      }

      if (d2 <= 0.0) break;
      zd1 = zd2;
      d1  = d2;
    }

    if (j == 180) {
      /* No negative derivative -> no point of inflection. */
      zd = PI;
      prj->global = 1;
    } else {
      /* Find where the derivative is zero. */
      for (j = 1; j <= 10; j++) {
        zd = zd1 - d1*(zd2-zd1)/(d2-d1);

        d = 0.0;
        for (m = k; m > 0; m--) {
          d = d*zd + m*prj->pv[m];
        }

        if (fabs(d) < tol) break;

        if (d < 0.0) {
          zd2 = zd;
          d2  = d;
        } else {
          zd1 = zd;
          d1  = d;
        }
      }
    }

    r = 0.0;
    for (m = k; m >= 0; m--) {
      r = r*zd + prj->pv[m];
    }
    prj->w[0] = zd;
    prj->w[1] = r;
  }
d2101 2
a2102 2
  prj->prjx2s = zpnx2s;
  prj->prjs2x = zpns2x;
d2104 1
a2104 1
  return prjoff(prj, 0.0, 90.0);
d2118 54
a2171 61
  int j, k, m, mx, my, rowlen, rowoff, status;
  double a, b, c, d, lambda, r, r1, r2, rt, xj, yj, yj2, zd, zd1, zd2;
  const double tol = 1.0e-13;
  register int ix, iy, *statp;
  register const double *xp, *yp;
  register double *phip, *thetap;


  /* Initialize. */
  if (prj == 0x0) return 1;
  if (prj->flag != ZPN) {
    if (zpnset(prj)) return 2;
  }

  k = prj->n;

  if (ny > 0) {
    mx = nx;
    my = ny;
  } else {
    mx = 1;
    my = 1;
    ny = nx;
  }

  status = 0;


  /* Do x dependence. */
  xp = x;
  rowoff = 0;
  rowlen = nx*spt;
  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    xj = *xp + prj->x0;

    phip = phi + rowoff;
    for (iy = 0; iy < my; iy++) {
      *phip = xj;
      phip += rowlen;
    }
  }


  /* Do y dependence. */
  yp = y;
  phip   = phi;
  thetap = theta;
  statp  = stat;
  for (iy = 0; iy < ny; iy++, yp += sxy) {
    yj  = *yp + prj->y0;
    yj2 = yj*yj;

    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
      xj = *phip;

      r = sqrt(xj*xj + yj2)/prj->r0;
      if (r == 0.0) {
        *phip = 0.0;
      } else {
        *phip = atan2d(xj, -yj);
      }
d2173 27
a2199 49
      if (k < 1) {
        /* Constant - no solution. */
        return 2;
      } else if (k == 1) {
        /* Linear. */
        zd = (r - prj->pv[0])/prj->pv[1];
      } else if (k == 2) {
        /* Quadratic. */
        a = prj->pv[2];
        b = prj->pv[1];
        c = prj->pv[0] - r;

        d = b*b - 4.0*a*c;
        if (d < 0.0) {
          *thetap = 0.0;
          *(statp++) = 1;
          status = 3;
          continue;
        }
        d = sqrt(d);

        /* Choose solution closest to pole. */
        zd1 = (-b + d)/(2.0*a);
        zd2 = (-b - d)/(2.0*a);
        zd  = (zd1<zd2) ? zd1 : zd2;
        if (zd < -tol) zd = (zd1>zd2) ? zd1 : zd2;
        if (zd < 0.0) {
          if (zd < -tol) {
            *thetap = 0.0;
            *(statp++) = 1;
            status = 3;
            continue;
          }
          zd = 0.0;
        } else if (zd > PI) {
          if (zd > PI+tol) {
            *thetap = 0.0;
            *(statp++) = 1;
            status = 3;
            continue;
          }
          zd = PI;
        }
      } else {
        /* Higher order - solve iteratively. */
        zd1 = 0.0;
        r1  = prj->pv[0];
        zd2 = prj->w[0];
        r2  = prj->w[1];
d2201 45
a2245 37
        if (r < r1) {
          if (r < r1-tol) {
            *thetap = 0.0;
            *(statp++) = 1;
            status = 3;
            continue;
          }
          zd = zd1;
        } else if (r > r2) {
          if (r > r2+tol) {
            *thetap = 0.0;
            *(statp++) = 1;
            status = 3;
            continue;
          }
          zd = zd2;
        } else {
          /* Disect the interval. */
          for (j = 0; j < 100; j++) {
            lambda = (r2 - r)/(r2 - r1);
            if (lambda < 0.1) {
              lambda = 0.1;
            } else if (lambda > 0.9) {
              lambda = 0.9;
            }

            zd = zd2 - lambda*(zd2 - zd1);

            rt = 0.0;
            for (m = k; m >= 0; m--) {
              rt = (rt * zd) + prj->pv[m];
            }

            if (rt < r) {
              if (r-rt < tol) break;
              r1 = rt;
              zd1 = zd;
d2247 28
a2274 3
              if (rt-r < tol) break;
              r2 = rt;
              zd2 = zd;
d2276 1
d2278 2
a2279 3
            if (fabs(zd2-zd1) < tol) break;
          }
        }
d2281 1
d2283 1
a2283 6
      *thetap = 90.0 - zd*R2D;
      *(statp++) = 0;
    }
  }

  return status;
d2297 57
a2353 70
  int m, mphi, mtheta, rowlen, rowoff, status;
  double cosphi, r, s, sinphi;
  register int iphi, itheta, istat, *statp;
  register const double *phip, *thetap;
  register double *xp, *yp;


  /* Initialize. */
  if (prj == 0x0) return 1;
  if (prj->flag != ZPN) {
    if (zpnset(prj)) return 2;
  }

  if (ntheta > 0) {
    mphi   = nphi;
    mtheta = ntheta;
  } else {
    mphi   = 1;
    mtheta = 1;
    ntheta = nphi;
  }

  status = 0;


  /* Do phi dependence. */
  phip = phi;
  rowoff = 0;
  rowlen = nphi*sxy;
  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    sinphi = sind(*phip);
    cosphi = cosd(*phip);

    xp = x + rowoff;
    yp = y + rowoff;
    for (itheta = 0; itheta < mtheta; itheta++) {
      *xp = sinphi;
      *yp = cosphi;
      xp += rowlen;
      yp += rowlen;
    }
  }


  /* Do theta dependence. */
  thetap = theta;
  xp = x;
  yp = y;
  statp = stat;
  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    s = (90.0 - *thetap)*D2R;

    r = 0.0;
    for (m = prj->n; m >= 0; m--) {
      r = r*s + prj->pv[m];
    }
    r *= prj->r0;

    istat = 0;
    if (prj->bounds && s > prj->w[0]) {
      istat  = 1;
      status = 4;
    }

    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
      *xp =  r*(*xp) - prj->x0;
      *yp = -r*(*yp) - prj->y0;
      *(statp++) = istat;
    }
  }
d2355 14
a2368 1
  return status;
d2395 1
a2395 1
  if (prj == 0x0) return 1;
d2397 2
a2398 2
  prj->flag = ZEA;
  strcpy(prj->code, "ZEA");
d2400 17
a2416 17
  strcpy(prj->name, "zenithal/azimuthal equal area");
  prj->category  = ZENITHAL;
  prj->pvrange   = 0;
  prj->simplezen = 1;
  prj->equiareal = 1;
  prj->conformal = 0;
  prj->global    = 1;
  prj->divergent = 0;

  if (prj->r0 == 0.0) {
    prj->r0 = R2D;
    prj->w[0] = 360.0/PI;
    prj->w[1] = PI/360.0;
  } else {
    prj->w[0] = 2.0*prj->r0;
    prj->w[1] = 1.0/prj->w[0];
  }
d2418 2
a2419 2
  prj->prjx2s = zeax2s;
  prj->prjs2x = zeas2x;
d2421 1
a2421 1
  return prjoff(prj, 0.0, 90.0);
d2435 73
a2507 59
  int mx, my, rowlen, rowoff, status;
  double r, s, xj, yj, yj2;
  const double tol = 1.0e-12;
  register int ix, iy, *statp;
  register const double *xp, *yp;
  register double *phip, *thetap;


  /* Initialize. */
  if (prj == 0x0) return 1;
  if (prj->flag != ZEA) {
    if (zeaset(prj)) return 2;
  }

  if (ny > 0) {
    mx = nx;
    my = ny;
  } else {
    mx = 1;
    my = 1;
    ny = nx;
  }

  status = 0;


  /* Do x dependence. */
  xp = x;
  rowoff = 0;
  rowlen = nx*spt;
  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    xj = *xp + prj->x0;

    phip = phi + rowoff;
    for (iy = 0; iy < my; iy++) {
      *phip = xj;
      phip += rowlen;
    }
  }


  /* Do y dependence. */
  yp = y;
  phip   = phi;
  thetap = theta;
  statp  = stat;
  for (iy = 0; iy < ny; iy++, yp += sxy) {
    yj  = *yp + prj->y0;
    yj2 = yj*yj;

    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
      xj  = *phip;

      r = sqrt(xj*xj + yj2);
      if (r == 0.0) {
        *phip = 0.0;
      } else {
        *phip = atan2d(xj, -yj);
      }
d2509 1
a2509 12
      s = r*prj->w[1];
      if (fabs(s) > 1.0) {
        if (fabs(r - prj->w[0]) < tol) {
          *thetap = -90.0;
        } else {
          *thetap = 0.0;
          *(statp++) = 1;
          status = 3;
          continue;
        }
      } else {
        *thetap = 90.0 - 2.0*asind(s);
d2511 1
d2513 1
a2513 5
      *(statp++) = 0;
    }
  }

  return status;
d2527 49
a2575 56
  int mphi, mtheta, rowlen, rowoff;
  double cosphi, r, sinphi;
  register int iphi, itheta, *statp;
  register const double *phip, *thetap;
  register double *xp, *yp;


  /* Initialize. */
  if (prj == 0x0) return 1;
  if (prj->flag != ZEA) {
    if (zeaset(prj)) return 2;
  }

  if (ntheta > 0) {
    mphi   = nphi;
    mtheta = ntheta;
  } else {
    mphi   = 1;
    mtheta = 1;
    ntheta = nphi;
  }


  /* Do phi dependence. */
  phip = phi;
  rowoff = 0;
  rowlen = nphi*sxy;
  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    sinphi = sind(*phip);
    cosphi = cosd(*phip);

    xp = x + rowoff;
    yp = y + rowoff;
    for (itheta = 0; itheta < mtheta; itheta++) {
      *xp = sinphi;
      *yp = cosphi;
      xp += rowlen;
      yp += rowlen;
    }
  }


  /* Do theta dependence. */
  thetap = theta;
  xp = x;
  yp = y;
  statp = stat;
  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    r =  prj->w[0]*sind((90.0 - *thetap)/2.0);

    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
      *xp =  r*(*xp) - prj->x0;
      *yp = -r*(*yp) - prj->y0;
      *(statp++) = 0;
    }
  }
d2577 8
a2584 1
  return 0;
d2621 4
a2624 2
  const double tol = 1.0e-4;
  double cosxi;
d2626 2
a2627 1
  if (prj == 0x0) return 1;
d2629 23
a2651 2
  prj->flag = AIR;
  strcpy(prj->code, "AIR");
d2653 4
a2656 28
  if (undefined(prj->pv[1])) prj->pv[1] = 90.0;
  if (prj->r0 == 0.0) prj->r0 = R2D;

  strcpy(prj->name, "Airy's zenithal");
  prj->category  = ZENITHAL;
  prj->pvrange   = 101;
  prj->simplezen = 1;
  prj->equiareal = 0;
  prj->conformal = 0;
  prj->global    = 0;
  prj->divergent = 1;

  prj->w[0] = 2.0*prj->r0;
  if (prj->pv[1] == 90.0) {
    prj->w[1] = -0.5;
    prj->w[2] =  1.0;
  } else if (prj->pv[1] > -90.0) {
    cosxi = cosd((90.0 - prj->pv[1])/2.0);
    prj->w[1] = log(cosxi)*(cosxi*cosxi)/(1.0-cosxi*cosxi);
    prj->w[2] = 0.5 - prj->w[1];
  } else {
    return 2;
  }

  prj->w[3] = prj->w[0] * prj->w[2];
  prj->w[4] = tol;
  prj->w[5] = prj->w[2]*tol;
  prj->w[6] = R2D/prj->w[2];
d2658 2
a2659 2
  prj->prjx2s = airx2s;
  prj->prjs2x = airs2x;
d2661 1
a2661 1
  return prjoff(prj, 0.0, 90.0);
d2675 114
a2788 59
  int k, mx, my, rowlen, rowoff, status;
  double cosxi, lambda, r, r1, r2, rt, tanxi, x1, x2, xi, xj, yj, yj2;
  const double tol = 1.0e-12;
  register int ix, iy, *statp;
  register const double *xp, *yp;
  register double *phip, *thetap;


  /* Initialize. */
  if (prj == 0x0) return 1;
  if (prj->flag != AIR) {
    if (airset(prj)) return 2;
  }

  if (ny > 0) {
    mx = nx;
    my = ny;
  } else {
    mx = 1;
    my = 1;
    ny = nx;
  }

  status = 0;


  /* Do x dependence. */
  xp = x;
  rowoff = 0;
  rowlen = nx*spt;
  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    xj = *xp + prj->x0;

    phip = phi + rowoff;
    for (iy = 0; iy < my; iy++) {
      *phip = xj;
      phip += rowlen;
    }
  }


  /* Do y dependence. */
  yp = y;
  phip   = phi;
  thetap = theta;
  statp  = stat;
  for (iy = 0; iy < ny; iy++, yp += sxy) {
    yj  = *yp + prj->y0;
    yj2 = yj*yj;

    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
      xj = *phip;

      r = sqrt(xj*xj + yj2)/prj->w[0];
      if (r == 0.0) {
        *phip = 0.0;
      } else {
        *phip = atan2d(xj, -yj);
      }
d2790 2
d2793 4
a2796 61
      if (r == 0.0) {
        xi = 0.0;
      } else if (r < prj->w[5]) {
        xi = r*prj->w[6];
      } else {
        /* Find a solution interval. */
        x1 = x2 = 1.0;
        r1 = r2 = 0.0;
        for (k = 0; k < 30; k++) {
          x2 = x1/2.0;
          tanxi = sqrt(1.0-x2*x2)/x2;
          r2 = -(log(x2)/tanxi + prj->w[1]*tanxi);

          if (r2 >= r) break;
          x1 = x2;
          r1 = r2;
        }
        if (k == 30) {
          *thetap = 0.0;
          *(statp++) = 1;
          status = 3;
          continue;
        }

        for (k = 0; k < 100; k++) {
          /* Weighted division of the interval. */
          lambda = (r2-r)/(r2-r1);
          if (lambda < 0.1) {
            lambda = 0.1;
          } else if (lambda > 0.9) {
            lambda = 0.9;
          }
          cosxi = x2 - lambda*(x2-x1);

          tanxi = sqrt(1.0-cosxi*cosxi)/cosxi;
          rt = -(log(cosxi)/tanxi + prj->w[1]*tanxi);

          if (rt < r) {
            if (r-rt < tol) break;
            r1 = rt;
            x1 = cosxi;
          } else {
            if (rt-r < tol) break;
            r2 = rt;
            x2 = cosxi;
          }
        }
        if (k == 100) {
          *thetap = 0.0;
          *(statp++) = 1;
          status = 3;
          continue;
        }

        xi = acosd(cosxi);
      }

      *thetap = 90.0 - 2.0*xi;
      *(statp++) = 0;
    }
  }
d2798 1
a2798 1
  return status;
d2812 68
a2879 51
  int mphi, mtheta, rowlen, rowoff, status;
  double cosphi, cosxi, r, tanxi, xi, sinphi;
  register int iphi, itheta, istat, *statp;
  register const double *phip, *thetap;
  register double *xp, *yp;


  /* Initialize. */
  if (prj == 0x0) return 1;
  if (prj->flag != AIR) {
    if (airset(prj)) return 2;
  }

  if (ntheta > 0) {
    mphi   = nphi;
    mtheta = ntheta;
  } else {
    mphi   = 1;
    mtheta = 1;
    ntheta = nphi;
  }

  status = 0;


  /* Do phi dependence. */
  phip = phi;
  rowoff = 0;
  rowlen = nphi*sxy;
  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    sinphi = sind(*phip);
    cosphi = cosd(*phip);

    xp = x + rowoff;
    yp = y + rowoff;
    for (itheta = 0; itheta < mtheta; itheta++) {
      *xp = sinphi;
      *yp = cosphi;
      xp += rowlen;
      yp += rowlen;
    }
  }


  /* Do theta dependence. */
  thetap = theta;
  xp = x;
  yp = y;
  statp = stat;
  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    istat = 0;
d2881 4
a2884 10
    if (*thetap == 90.0) {
      r = 0.0;
    } else if (*thetap > -90.0) {
      xi = D2R*(90.0 - *thetap)/2.0;
      if (xi < prj->w[4]) {
        r = xi*prj->w[3];
      } else {
        cosxi = cosd((90.0 - *thetap)/2.0);
        tanxi = sqrt(1.0-cosxi*cosxi)/cosxi;
        r = -prj->w[0]*(log(cosxi)/tanxi + prj->w[1]*tanxi);
d2886 1
a2886 12
    } else {
      r = 0.0;
      istat  = 1;
      status = 4;
    }

    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
      *xp =  r*(*xp) - prj->x0;
      *yp = -r*(*yp) - prj->y0;
      *(statp++) = istat;
    }
  }
d2888 1
a2888 1
  return status;
d2923 1
a2923 1
  if (prj == 0x0) return 1;
d2925 2
a2926 2
  prj->flag = CYP;
  strcpy(prj->code, "CYP");
d2928 2
a2929 2
  if (undefined(prj->pv[1])) prj->pv[1] = 1.0;
  if (undefined(prj->pv[2])) prj->pv[2] = 1.0;
d2931 8
a2938 8
  strcpy(prj->name, "cylindrical perspective");
  prj->category  = CYLINDRICAL;
  prj->pvrange   = 102;
  prj->simplezen = 0;
  prj->equiareal = 0;
  prj->conformal = 0;
  prj->global    = prj->pv[1] < -1.0 || 0.0 < prj->pv[1];
  prj->divergent = !prj->global;
d2940 2
a2941 2
  if (prj->r0 == 0.0) {
    prj->r0 = R2D;
d2943 4
a2946 4
    prj->w[0] = prj->pv[2];
    if (prj->w[0] == 0.0) {
      return 2;
    }
d2948 1
a2948 1
    prj->w[1] = 1.0/prj->w[0];
d2950 4
a2953 4
    prj->w[2] = R2D*(prj->pv[1] + prj->pv[2]);
    if (prj->w[2] == 0.0) {
      return 2;
    }
d2955 6
a2960 6
    prj->w[3] = 1.0/prj->w[2];
  } else {
    prj->w[0] = prj->r0*prj->pv[2]*D2R;
    if (prj->w[0] == 0.0) {
      return 2;
    }
d2962 1
a2962 1
    prj->w[1] = 1.0/prj->w[0];
d2964 4
a2967 4
    prj->w[2] = prj->r0*(prj->pv[1] + prj->pv[2]);
    if (prj->w[2] == 0.0) {
      return 2;
    }
d2969 2
a2970 2
    prj->w[3] = 1.0/prj->w[2];
  }
d2972 2
a2973 2
  prj->prjx2s = cypx2s;
  prj->prjs2x = cyps2x;
d2975 1
a2975 1
  return prjoff(prj, 0.0, 0.0);
d2989 51
a3039 51
  int mx, my, rowlen, rowoff;
  double eta, s, t;
  register int ix, iy, *statp;
  register const double *xp, *yp;
  register double *phip, *thetap;


  /* Initialize. */
  if (prj == 0x0) return 1;
  if (prj->flag != CYP) {
    if (cypset(prj)) return 2;
  }

  if (ny > 0) {
    mx = nx;
    my = ny;
  } else {
    mx = 1;
    my = 1;
    ny = nx;
  }


  /* Do x dependence. */
  xp = x;
  rowoff = 0;
  rowlen = nx*spt;
  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    s = prj->w[1]*(*xp + prj->x0);

    phip = phi + rowoff;
    for (iy = 0; iy < my; iy++) {
      *phip = s;
      phip += rowlen;
    }
  }


  /* Do y dependence. */
  yp = y;
  thetap = theta;
  statp = stat;
  for (iy = 0; iy < ny; iy++, yp += sxy) {
    eta = prj->w[3]*(*yp + prj->y0);
    t = atan2d(eta,1.0) + asind(eta*prj->pv[1]/sqrt(eta*eta+1.0));

    for (ix = 0; ix < mx; ix++, thetap += spt) {
      *thetap = t;
      *(statp++) = 0;
    }
  }
d3041 1
a3041 1
  return 0;
d3055 62
a3116 62
  int mphi, mtheta, rowlen, rowoff, status;
  double eta, xi;
  register int iphi, itheta, istat, *statp;
  register const double *phip, *thetap;
  register double *xp, *yp;


  /* Initialize. */
  if (prj == 0x0) return 1;
  if (prj->flag != CYP) {
    if (cypset(prj)) return 2;
  }

  if (ntheta > 0) {
    mphi   = nphi;
    mtheta = ntheta;
  } else {
    mphi   = 1;
    mtheta = 1;
    ntheta = nphi;
  }

  status = 0;


  /* Do phi dependence. */
  phip = phi;
  rowoff = 0;
  rowlen = nphi*sxy;
  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    xi = prj->w[0]*(*phip) - prj->x0;

    xp = x + rowoff;
    for (itheta = 0; itheta < mtheta; itheta++) {
      *xp = xi;
      xp += rowlen;
    }
  }


  /* Do theta dependence. */
  thetap = theta;
  yp = y;
  statp = stat;
  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    eta = prj->pv[1] + cosd(*thetap);

    istat = 0;
    if (eta == 0.0) {
      istat  = 1;
      status = 4;

    } else {
      eta = prj->w[2]*sind(*thetap)/eta;
    }

    eta -= prj->y0;
    for (iphi = 0; iphi < mphi; iphi++, yp += sxy) {
      *yp = eta;
      *(statp++) = istat;
    }
  }
d3118 1
a3118 1
  return status;
d3151 1
a3151 1
  if (prj == 0x0) return 1;
d3153 2
a3154 2
  prj->flag = CEA;
  strcpy(prj->code, "CEA");
d3156 1
a3156 1
  if (undefined(prj->pv[1])) prj->pv[1] = 1.0;
d3158 27
a3184 27
  strcpy(prj->name, "cylindrical equal area");
  prj->category  = CYLINDRICAL;
  prj->pvrange   = 101;
  prj->simplezen = 0;
  prj->equiareal = 1;
  prj->conformal = 0;
  prj->global    = 1;
  prj->divergent = 0;

  if (prj->r0 == 0.0) {
    prj->r0 = R2D;
    prj->w[0] = 1.0;
    prj->w[1] = 1.0;
    if (prj->pv[1] <= 0.0 || prj->pv[1] > 1.0) {
      return 2;
    }
    prj->w[2] = prj->r0/prj->pv[1];
    prj->w[3] = prj->pv[1]/prj->r0;
  } else {
    prj->w[0] = prj->r0*D2R;
    prj->w[1] = R2D/prj->r0;
    if (prj->pv[1] <= 0.0 || prj->pv[1] > 1.0) {
      return 2;
    }
    prj->w[2] = prj->r0/prj->pv[1];
    prj->w[3] = prj->pv[1]/prj->r0;
  }
d3186 2
a3187 2
  prj->prjx2s = ceax2s;
  prj->prjs2x = ceas2x;
d3189 1
a3189 1
  return prjoff(prj, 0.0, 0.0);
d3203 57
a3259 54
  int mx, my, rowlen, rowoff, status;
  double s;
  const double tol = 1.0e-13;
  register int istat, ix, iy, *statp;
  register const double *xp, *yp;
  register double *phip, *thetap;


  /* Initialize. */
  if (prj == 0x0) return 1;
  if (prj->flag != CEA) {
    if (ceaset(prj)) return 2;
  }

  if (ny > 0) {
    mx = nx;
    my = ny;
  } else {
    mx = 1;
    my = 1;
    ny = nx;
  }

  status = 0;


  /* Do x dependence. */
  xp = x;
  rowoff = 0;
  rowlen = nx*spt;
  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    s = prj->w[1]*(*xp + prj->x0);

    phip = phi + rowoff;
    for (iy = 0; iy < my; iy++) {
      *phip = s;
      phip += rowlen;
    }
  }


  /* Do y dependence. */
  yp = y;
  thetap = theta;
  statp = stat;
  for (iy = 0; iy < ny; iy++, yp += sxy) {
    s = prj->w[3]*(*yp + prj->y0);

    istat = 0;
    if (fabs(s) > 1.0) {
      if (fabs(s) > 1.0+tol) {
        s = 0.0;
        istat  = 1;
        status = 3;
d3261 1
a3261 1
        s = copysign(90.0, s);
a3262 9
    } else {
      s = asind(s);
    }

    for (ix = 0; ix < mx; ix++, thetap += spt) {
      *thetap = s;
      *(statp++) = istat;
    }
  }
d3264 7
a3270 1
  return status;
d3284 50
a3333 50
  int mphi, mtheta, rowlen, rowoff;
  double eta, xi;
  register int iphi, itheta, *statp;
  register const double *phip, *thetap;
  register double *xp, *yp;


  /* Initialize. */
  if (prj == 0x0) return 1;
  if (prj->flag != CEA) {
    if (ceaset(prj)) return 2;
  }

  if (ntheta > 0) {
    mphi   = nphi;
    mtheta = ntheta;
  } else {
    mphi   = 1;
    mtheta = 1;
    ntheta = nphi;
  }


  /* Do phi dependence. */
  phip = phi;
  rowoff = 0;
  rowlen = nphi*sxy;
  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    xi = prj->w[0]*(*phip) - prj->x0;

    xp = x + rowoff;
    for (itheta = 0; itheta < mtheta; itheta++) {
      *xp = xi;
      xp += rowlen;
    }
  }


  /* Do theta dependence. */
  thetap = theta;
  yp = y;
  statp = stat;
  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    eta = prj->w[2]*sind(*thetap) - prj->y0;

    for (iphi = 0; iphi < mphi; iphi++, yp += sxy) {
      *yp = eta;
      *(statp++) = 0;
    }
  }
d3335 1
a3335 1
  return 0;
d3362 1
a3362 1
  if (prj == 0x0) return 1;
d3364 2
a3365 2
  prj->flag = CAR;
  strcpy(prj->code, "CAR");
d3367 17
a3383 17
  strcpy(prj->name, "plate caree");
  prj->category  = CYLINDRICAL;
  prj->pvrange   = 0;
  prj->simplezen = 0;
  prj->equiareal = 0;
  prj->conformal = 0;
  prj->global    = 1;
  prj->divergent = 0;

  if (prj->r0 == 0.0) {
    prj->r0 = R2D;
    prj->w[0] = 1.0;
    prj->w[1] = 1.0;
  } else {
    prj->w[0] = prj->r0*D2R;
    prj->w[1] = 1.0/prj->w[0];
  }
d3385 2
a3386 2
  prj->prjx2s = carx2s;
  prj->prjs2x = cars2x;
d3388 1
a3388 1
  return prjoff(prj, 0.0, 0.0);
d3402 50
a3451 50
  int mx, my, rowlen, rowoff;
  double s, t;
  register int ix, iy, *statp;
  register const double *xp, *yp;
  register double *phip, *thetap;


  /* Initialize. */
  if (prj == 0x0) return 1;
  if (prj->flag != CAR) {
    if (carset(prj)) return 2;
  }

  if (ny > 0) {
    mx = nx;
    my = ny;
  } else {
    mx = 1;
    my = 1;
    ny = nx;
  }


  /* Do x dependence. */
  xp = x;
  rowoff = 0;
  rowlen = nx*spt;
  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    s = prj->w[1]*(*xp + prj->x0);

    phip = phi + rowoff;
    for (iy = 0; iy < my; iy++) {
      *phip = s;
      phip += rowlen;
    }
  }


  /* Do y dependence. */
  yp = y;
  thetap = theta;
  statp = stat;
  for (iy = 0; iy < ny; iy++, yp += sxy) {
    t = prj->w[1]*(*yp + prj->y0);

    for (ix = 0; ix < mx; ix++, thetap += spt) {
      *thetap = t;
      *(statp++) = 0;
    }
  }
d3453 1
a3453 1
  return 0;
d3467 50
a3516 50
  int mphi, mtheta, rowlen, rowoff;
  double eta, xi;
  register int iphi, itheta, *statp;
  register const double *phip, *thetap;
  register double *xp, *yp;


  /* Initialize. */
  if (prj == 0x0) return 1;
  if (prj->flag != CAR) {
    if (carset(prj)) return 2;
  }

  if (ntheta > 0) {
    mphi   = nphi;
    mtheta = ntheta;
  } else {
    mphi   = 1;
    mtheta = 1;
    ntheta = nphi;
  }


  /* Do phi dependence. */
  phip = phi;
  rowoff = 0;
  rowlen = nphi*sxy;
  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    xi = prj->w[0]*(*phip) - prj->x0;

    xp = x + rowoff;
    for (itheta = 0; itheta < mtheta; itheta++) {
      *xp = xi;
      xp += rowlen;
    }
  }


  /* Do theta dependence. */
  thetap = theta;
  yp = y;
  statp = stat;
  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    eta = prj->w[0]*(*thetap) - prj->y0;

    for (iphi = 0; iphi < mphi; iphi++, yp += sxy) {
      *yp = eta;
      *(statp++) = 0;
    }
  }
d3518 1
a3518 1
  return 0;
d3545 1
a3545 1
  if (prj == 0x0) return 1;
d3547 2
a3548 2
  prj->flag = MER;
  strcpy(prj->code, "MER");
d3550 17
a3566 17
  strcpy(prj->name, "Mercator's");
  prj->category  = CYLINDRICAL;
  prj->pvrange   = 0;
  prj->simplezen = 0;
  prj->equiareal = 0;
  prj->conformal = 1;
  prj->global    = 0;
  prj->divergent = 1;

  if (prj->r0 == 0.0) {
    prj->r0 = R2D;
    prj->w[0] = 1.0;
    prj->w[1] = 1.0;
  } else {
    prj->w[0] = prj->r0*D2R;
    prj->w[1] = 1.0/prj->w[0];
  }
d3568 2
a3569 2
  prj->prjx2s = merx2s;
  prj->prjs2x = mers2x;
d3571 1
a3571 1
  return prjoff(prj, 0.0, 0.0);
d3585 50
a3634 50
  int mx, my, rowlen, rowoff;
  double s, t;
  register int ix, iy, *statp;
  register const double *xp, *yp;
  register double *phip, *thetap;


  /* Initialize. */
  if (prj == 0x0) return 1;
  if (prj->flag != MER) {
    if (merset(prj)) return 2;
  }

  if (ny > 0) {
    mx = nx;
    my = ny;
  } else {
    mx = 1;
    my = 1;
    ny = nx;
  }


  /* Do x dependence. */
  xp = x;
  rowoff = 0;
  rowlen = nx*spt;
  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    s = prj->w[1]*(*xp + prj->x0);

    phip = phi + rowoff;
    for (iy = 0; iy < my; iy++) {
      *phip = s;
      phip += rowlen;
    }
  }


  /* Do y dependence. */
  yp = y;
  thetap = theta;
  statp  = stat;
  for (iy = 0; iy < ny; iy++, yp += sxy) {
    t = 2.0*atand(exp((*yp + prj->y0)/prj->r0)) - 90.0;

    for (ix = 0; ix < mx; ix++, thetap += spt) {
      *thetap = t;
      *(statp++) = 0;
    }
  }
d3636 1
a3636 1
  return 0;
d3650 60
a3709 60
  int mphi, mtheta, rowlen, rowoff, status;
  double eta, xi;
  register int iphi, itheta, istat, *statp;
  register const double *phip, *thetap;
  register double *xp, *yp;


  /* Initialize. */
  if (prj == 0x0) return 1;
  if (prj->flag != MER) {
    if (merset(prj)) return 2;
  }

  if (ntheta > 0) {
    mphi   = nphi;
    mtheta = ntheta;
  } else {
    mphi   = 1;
    mtheta = 1;
    ntheta = nphi;
  }

  status = 0;


  /* Do phi dependence. */
  phip = phi;
  rowoff = 0;
  rowlen = nphi*sxy;
  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    xi  = prj->w[0]*(*phip) - prj->x0;

    xp = x + rowoff;
    for (itheta = 0; itheta < mtheta; itheta++) {
      *xp = xi;
      xp += rowlen;
    }
  }


  /* Do theta dependence. */
  thetap = theta;
  yp = y;
  statp = stat;
  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    istat = 0;

    if (*thetap <= -90.0 || *thetap >= 90.0) {
      eta = 0.0;
      istat  = 1;
      status = 4;
    } else {
      eta = prj->r0*log(tand((*thetap+90.0)/2.0)) - prj->y0;
    }

    for (iphi = 0; iphi < mphi; iphi++, yp += sxy) {
      *yp = eta;
      *(statp++) = istat;
    }
  }
d3711 1
a3711 1
  return status;
d3738 1
a3738 1
  if (prj == 0x0) return 1;
d3740 2
a3741 2
  prj->flag = SFL;
  strcpy(prj->code, "SFL");
d3743 17
a3759 17
  strcpy(prj->name, "Sanson-Flamsteed");
  prj->category  = PSEUDOCYLINDRICAL;
  prj->pvrange   = 0;
  prj->simplezen = 0;
  prj->equiareal = 1;
  prj->conformal = 0;
  prj->global    = 1;
  prj->divergent = 0;

  if (prj->r0 == 0.0) {
    prj->r0 = R2D;
    prj->w[0] = 1.0;
    prj->w[1] = 1.0;
  } else {
    prj->w[0] = prj->r0*D2R;
    prj->w[1] = 1.0/prj->w[0];
  }
d3761 2
a3762 2
  prj->prjx2s = sflx2s;
  prj->prjs2x = sfls2x;
d3764 1
a3764 1
  return prjoff(prj, 0.0, 0.0);
d3778 63
a3840 63
  int mx, my, rowlen, rowoff, status;
  double s, t, yj;
  register int istat, ix, iy, *statp;
  register const double *xp, *yp;
  register double *phip, *thetap;


  /* Initialize. */
  if (prj == 0x0) return 1;
  if (prj->flag != SFL) {
    if (sflset(prj)) return 2;
  }

  if (ny > 0) {
    mx = nx;
    my = ny;
  } else {
    mx = 1;
    my = 1;
    ny = nx;
  }


  /* Do x dependence. */
  xp = x;
  rowoff = 0;
  rowlen = nx*spt;
  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    s = prj->w[1]*(*xp + prj->x0);

    phip = phi + rowoff;
    for (iy = 0; iy < my; iy++) {
      *phip = s;
      phip += rowlen;
    }
  }


  /* Do y dependence. */
  yp = y;
  phip   = phi;
  thetap = theta;
  statp  = stat;
  for (iy = 0; iy < ny; iy++, yp += sxy) {
    yj = *yp + prj->y0;
    s = cos(yj/prj->r0);

    istat = 0;
    if (s == 0.0) {
      istat  = 1;
      status = 3;
    } else {
      s = 1.0/s;
    }

    t = prj->w[1]*yj;

    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
      *phip  *= s;
      *thetap = t;
      *(statp++) = 0;
    }
  }
d3842 1
a3842 1
  return 0;
d3856 53
a3908 53
  int mphi, mtheta, rowlen, rowoff;
  double eta, xi;
  register int iphi, itheta, *statp;
  register const double *phip, *thetap;
  register double *xp, *yp;


  /* Initialize. */
  if (prj == 0x0) return 1;
  if (prj->flag != SFL) {
    if (sflset(prj)) return 2;
  }

  if (ntheta > 0) {
    mphi   = nphi;
    mtheta = ntheta;
  } else {
    mphi   = 1;
    mtheta = 1;
    ntheta = nphi;
  }


  /* Do phi dependence. */
  phip = phi;
  rowoff = 0;
  rowlen = nphi*sxy;
  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    xi = prj->w[0]*(*phip);

    xp = x + rowoff;
    for (itheta = 0; itheta < mtheta; itheta++) {
      *xp = xi;
      xp += rowlen;
    }
  }


  /* Do theta dependence. */
  thetap = theta;
  xp = x;
  yp = y;
  statp = stat;
  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    xi  = cosd(*thetap);
    eta = prj->w[0]*(*thetap) - prj->y0;

    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
      *xp = xi*(*xp) - prj->x0;
      *yp = eta;
      *(statp++) = 0;
    }
  }
d3910 1
a3910 1
  return 0;
d3939 1
a3939 1
  if (prj == 0x0) return 1;
d3941 2
a3942 2
  prj->flag = PAR;
  strcpy(prj->code, "PAR");
d3944 21
a3964 21
  strcpy(prj->name, "parabolic");
  prj->category  = PSEUDOCYLINDRICAL;
  prj->pvrange   = 0;
  prj->simplezen = 0;
  prj->equiareal = 1;
  prj->conformal = 0;
  prj->global    = 1;
  prj->divergent = 0;

  if (prj->r0 == 0.0) {
    prj->r0 = R2D;
    prj->w[0] = 1.0;
    prj->w[1] = 1.0;
    prj->w[2] = 180.0;
    prj->w[3] = 1.0/prj->w[2];
  } else {
    prj->w[0] = prj->r0*D2R;
    prj->w[1] = 1.0/prj->w[0];
    prj->w[2] = PI*prj->r0;
    prj->w[3] = 1.0/prj->w[2];
  }
d3966 2
a3967 2
  prj->prjx2s = parx2s;
  prj->prjs2x = pars2x;
d3969 1
a3969 1
  return prjoff(prj, 0.0, 0.0);
d3983 53
a4035 60
  int mx, my, rowlen, rowoff, status;
  double r, s, t, xj;
  const double tol = 1.0e-13;
  register int istat, ix, iy, *statp;
  register const double *xp, *yp;
  register double *phip, *thetap;


  /* Initialize. */
  if (prj == 0x0) return 1;
  if (prj->flag != PAR) {
    if (parset(prj)) return 2;
  }

  if (ny > 0) {
    mx = nx;
    my = ny;
  } else {
    mx = 1;
    my = 1;
    ny = nx;
  }

  status = 0;


  /* Do x dependence. */
  xp = x;
  rowoff = 0;
  rowlen = nx*spt;
  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    xj = *xp + prj->x0;
    s = prj->w[1]*xj;
    t = fabs(xj) - tol;

    phip   = phi   + rowoff;
    thetap = theta + rowoff;
    for (iy = 0; iy < my; iy++) {
      *phip   = s;
      *thetap = t;
      phip   += rowlen;
      thetap += rowlen;
    }
  }


  /* Do y dependence. */
  yp = y;
  phip   = phi;
  thetap = theta;
  statp  = stat;
  for (iy = 0; iy < ny; iy++, yp += sxy) {
    r = prj->w[3]*(*yp + prj->y0);

    istat = 0;
    if (r > 1.0 || r < -1.0) {
      s = 0.0;
      t = 0.0;
      istat  = 1;
      status = 3;
d4037 17
a4053 7
    } else {
      s = 1.0 - 4.0*r*r;
      if (s == 0.0) {
        /* Deferred test. */
        istat = -1;
      } else {
        s = 1.0/s;
d4056 9
a4064 2
      t = 3.0*asind(r);
    }
d4066 2
a4067 8
    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
      if (istat < 0) {
        if (*thetap < 0.0) {
          *(statp++) = 0;
        } else {
          *(statp++) = 1;
          status = 3;
        }
d4069 1
d4071 1
a4071 6
      *phip  *= s;
      *thetap = t;
    }
  }

  return status;
d4085 47
a4131 54
  int mphi, mtheta, rowlen, rowoff;
  double eta, s, xi;
  register int iphi, itheta, *statp;
  register const double *phip, *thetap;
  register double *xp, *yp;


  /* Initialize. */
  if (prj == 0x0) return 1;
  if (prj->flag != PAR) {
    if (parset(prj)) return 2;
  }

  if (ntheta > 0) {
    mphi   = nphi;
    mtheta = ntheta;
  } else {
    mphi   = 1;
    mtheta = 1;
    ntheta = nphi;
  }


  /* Do phi dependence. */
  phip = phi;
  rowoff = 0;
  rowlen = nphi*sxy;
  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    xi = prj->w[0]*(*phip);

    xp = x + rowoff;
    for (itheta = 0; itheta < mtheta; itheta++) {
      *xp = xi;
      xp += rowlen;
    }
  }


  /* Do theta dependence. */
  thetap = theta;
  xp = x;
  yp = y;
  statp = stat;
  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    s = sind((*thetap)/3.0);
    xi = (1.0 - 4.0*s*s);
    eta = prj->w[2]*s - prj->y0;

    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
      *xp = xi*(*xp) - prj->x0;
      *yp = eta;
      *(statp++) = 0;
    }
  }
d4133 8
a4140 1
  return 0;
d4169 1
a4169 1
  if (prj == 0x0) return 1;
d4171 2
a4172 2
  prj->flag = MOL;
  strcpy(prj->code, "MOL");
d4174 1
a4174 1
  if (prj->r0 == 0.0) prj->r0 = R2D;
d4176 14
a4189 14
  strcpy(prj->name, "Mollweide's");
  prj->category  = PSEUDOCYLINDRICAL;
  prj->pvrange   = 0;
  prj->simplezen = 0;
  prj->equiareal = 1;
  prj->conformal = 0;
  prj->global    = 1;
  prj->divergent = 0;

  prj->w[0] = SQRT2*prj->r0;
  prj->w[1] = prj->w[0]/90.0;
  prj->w[2] = 1.0/prj->w[0];
  prj->w[3] = 90.0/prj->r0;
  prj->w[4] = 2.0/PI;
d4191 2
a4192 2
  prj->prjx2s = molx2s;
  prj->prjs2x = mols2x;
d4194 1
a4194 1
  return prjoff(prj, 0.0, 0.0);
d4208 69
a4276 61
  int mx, my, rowlen, rowoff, status;
  double r, s, t, xj, y0, yj, z;
  const double tol = 1.0e-12;
  register int istat, ix, iy, *statp;
  register const double *xp, *yp;
  register double *phip, *thetap;


  /* Initialize. */
  if (prj == 0x0) return 1;
  if (prj->flag != MOL) {
    if (molset(prj)) return 2;
  }

  if (ny > 0) {
    mx = nx;
    my = ny;
  } else {
    mx = 1;
    my = 1;
    ny = nx;
  }

  status = 0;


  /* Do x dependence. */
  xp = x;
  rowoff = 0;
  rowlen = nx*spt;
  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    xj = *xp + prj->x0;
    s = prj->w[3]*xj;
    t = fabs(xj) - tol;

    phip   = phi   + rowoff;
    thetap = theta + rowoff;
    for (iy = 0; iy < my; iy++) {
      *phip   = s;
      *thetap = t;
      phip   += rowlen;
      thetap += rowlen;
    }
  }


  /* Do y dependence. */
  yp = y;
  phip   = phi;
  thetap = theta;
  statp  = stat;
  for (iy = 0; iy < ny; iy++, yp += sxy) {
    yj = *yp + prj->y0;
    y0 = yj/prj->r0;
    r  = 2.0 - y0*y0;

    istat = 0;
    if (r <= tol) {
      if (r < -tol) {
        istat  = 1;
        status = 3;
d4278 2
a4279 2
        /* OK if fabs(x) < tol whence phi = 0.0. */
        istat = -1;
d4282 9
a4290 14
      r = 0.0;
      s = 0.0;

    } else {
      r = sqrt(r);
      s = 1.0/r;
    }

    z = yj*prj->w[2];
    if (fabs(z) > 1.0) {
      if (fabs(z) > 1.0+tol) {
        z = 0.0;
        istat  = 1;
        status = 3;
d4292 1
a4292 1
        z = copysign(1.0, z) + y0*r/PI;
d4294 9
a4302 11
    } else {
      z = asin(z)*prj->w[4] + y0*r/PI;
    }

    if (fabs(z) > 1.0) {
      if (fabs(z) > 1.0+tol) {
        z = 0.0;
        istat  = 1;
        status = 3;
      } else {
        z = copysign(1.0, z);
a4303 1
    }
d4305 1
a4305 1
    t = asind(z);
d4307 12
a4318 8
    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
      if (istat < 0) {
        if (*thetap < 0.0) {
          *(statp++) = 0;
        } else {
          *(statp++) = 1;
          status = 3;
        }
d4320 1
d4322 1
a4322 6
      *phip  *= s;
      *thetap = t;
    }
  }

  return status;
d4336 72
a4407 80
  int k, mphi, mtheta, rowlen, rowoff;
  double eta, gamma, resid, u, v, v0, v1, xi;
  const double tol = 1.0e-13;
  register int iphi, itheta, *statp;
  register const double *phip, *thetap;
  register double *xp, *yp;


  /* Initialize. */
  if (prj == 0x0) return 1;
  if (prj->flag != MOL) {
    if (molset(prj)) return 2;
  }

  if (ntheta > 0) {
    mphi   = nphi;
    mtheta = ntheta;
  } else {
    mphi   = 1;
    mtheta = 1;
    ntheta = nphi;
  }


  /* Do phi dependence. */
  phip = phi;
  rowoff = 0;
  rowlen = nphi*sxy;
  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    xi = prj->w[1]*(*phip);

    xp = x + rowoff;
    for (itheta = 0; itheta < mtheta; itheta++) {
      *xp = xi;
      xp += rowlen;
    }
  }


  /* Do theta dependence. */
  thetap = theta;
  xp = x;
  yp = y;
  statp = stat;
  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    if (fabs(*thetap) == 90.0) {
      xi  = 0.0;
      eta = copysign(prj->w[0], *thetap);
    } else if (*thetap == 0.0) {
      xi  = 1.0;
      eta = 0.0;
    } else {
      u  = PI*sind(*thetap);
      v0 = -PI;
      v1 =  PI;
      v  = u;
      for (k = 0; k < 100; k++) {
        resid = (v - u) + sin(v);
        if (resid < 0.0) {
          if (resid > -tol) break;
          v0 = v;
        } else {
          if (resid < tol) break;
          v1 = v;
        }
        v = (v0 + v1)/2.0;
      }

      gamma = v/2.0;
      xi  = cos(gamma);
      eta = prj->w[0]*sin(gamma);
    }

    eta -= prj->y0;
    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
      *xp = xi*(*xp) - prj->x0;
      *yp = eta;
      *(statp++) = 0;
    }
  }
d4409 9
a4417 1
  return 0;
d4446 1
a4446 1
  if (prj == 0x0) return 1;
d4448 2
a4449 2
  prj->flag = AIT;
  strcpy(prj->code, "AIT");
d4451 1
a4451 1
  if (prj->r0 == 0.0) prj->r0 = R2D;
d4453 13
a4465 13
  strcpy(prj->name, "Hammer-Aitoff");
  prj->category  = CONVENTIONAL;
  prj->pvrange   = 0;
  prj->simplezen = 0;
  prj->equiareal = 1;
  prj->conformal = 0;
  prj->global    = 1;
  prj->divergent = 0;

  prj->w[0] = 2.0*prj->r0*prj->r0;
  prj->w[1] = 1.0/(2.0*prj->w[0]);
  prj->w[2] = prj->w[1]/4.0;
  prj->w[3] = 1.0/(2.0*prj->r0);
d4467 2
a4468 2
  prj->prjx2s = aitx2s;
  prj->prjs2x = aits2x;
d4470 1
a4470 1
  return prjoff(prj, 0.0, 0.0);
d4484 54
a4537 54
  int mx, my, rowlen, rowoff, status;
  double s, t, x0, xj, y0, yj, yj2, z;
  const double tol = 1.0e-13;
  register int ix, iy, istat, *statp;
  register const double *xp, *yp;
  register double *phip, *thetap;


  /* Initialize. */
  if (prj == 0x0) return 1;
  if (prj->flag != AIT) {
    if (aitset(prj)) return 2;
  }

  if (ny > 0) {
    mx = nx;
    my = ny;
  } else {
    mx = 1;
    my = 1;
    ny = nx;
  }

  status = 0;


  /* Do x dependence. */
  xp = x;
  rowoff = 0;
  rowlen = nx*spt;
  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    xj = *xp + prj->x0;
    s  = 1.0 - xj*xj*prj->w[2];
    t  = xj*prj->w[3];

    phip   = phi   + rowoff;
    thetap = theta + rowoff;
    for (iy = 0; iy < my; iy++) {
      *phip   = s;
      *thetap = t;
      phip   += rowlen;
      thetap += rowlen;
    }
  }


  /* Do y dependence. */
  yp = y;
  phip   = phi;
  thetap = theta;
  statp  = stat;
  for (iy = 0; iy < ny; iy++, yp += sxy) {
    yj  = *yp + prj->y0;
    yj2 = yj*yj*prj->w[1];
d4539 9
a4547 2
    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
      s = *phip - yj2;
d4549 2
a4550 9
      istat = 0;
      if (s < 0.5) {
        if (s < 0.5-tol) {
          istat  = 1;
          status = 3;
        }

        s = 0.5;
      }
d4552 16
a4567 8
      z = sqrt(s);
      x0 = 2.0*z*z - 1.0;
      y0 = z*(*thetap);
      if (x0 == 0.0 && y0 == 0.0) {
        *phip = 0.0;
      } else {
        *phip = 2.0*atan2d(y0, x0);
      }
d4569 3
a4571 7
      t = z*yj/prj->r0;
      if (fabs(t) > 1.0) {
        if (fabs(t) > 1.0+tol) {
          istat  = 1;
          status = 3;
        }
        t = copysign(90.0, t);
d4573 2
a4574 2
      } else {
        t = asind(t);
d4576 1
d4578 1
a4578 6
      *thetap = t;
      *(statp++) = istat;
    }
  }

  return status;
d4592 51
a4642 59
  int mphi, mtheta, rowlen, rowoff;
  double cosphi, costhe, sinphi, sinthe, w;
  register int iphi, itheta, *statp;
  register const double *phip, *thetap;
  register double *xp, *yp;


  /* Initialize. */
  if (prj == 0x0) return 1;
  if (prj->flag != AIT) {
    if (aitset(prj)) return 2;
  }

  if (ntheta > 0) {
    mphi   = nphi;
    mtheta = ntheta;
  } else {
    mphi   = 1;
    mtheta = 1;
    ntheta = nphi;
  }


  /* Do phi dependence. */
  phip = phi;
  rowoff = 0;
  rowlen = nphi*sxy;
  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    w = (*phip)/2.0;
    sinphi = sind(w);
    cosphi = cosd(w);

    xp = x + rowoff;
    yp = y + rowoff;
    for (itheta = 0; itheta < mtheta; itheta++) {
      *xp = sinphi;
      *yp = cosphi;
      xp += rowlen;
      yp += rowlen;
    }
  }


  /* Do theta dependence. */
  thetap = theta;
  xp = x;
  yp = y;
  statp = stat;
  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    costhe = cosd(*thetap);
    sinthe = sind(*thetap);

    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
      w = sqrt(prj->w[0]/(1.0 + costhe*(*yp)));
      *xp = 2.0*w*costhe*(*xp) - prj->x0;
      *yp = w*sinthe - prj->y0;
      *(statp++) = 0;
    }
  }
d4644 9
a4652 1
  return 0;
d4688 19
a4706 1
  if (prj == 0x0) return 1;
d4708 11
a4718 2
  prj->flag = COP;
  strcpy(prj->code, "COP");
d4720 2
a4721 29
  if (undefined(prj->pv[1])) {
    return 2;
  }
  if (undefined(prj->pv[2])) prj->pv[2] = 0.0;
  if (prj->r0 == 0.0) prj->r0 = R2D;

  strcpy(prj->name, "conic perspective");
  prj->category  = CONIC;
  prj->pvrange   = 102;
  prj->simplezen = 0;
  prj->equiareal = 0;
  prj->conformal = 0;
  prj->global    = 0;
  prj->divergent = 1;

  prj->w[0] = sind(prj->pv[1]);
  if (prj->w[0] == 0.0) {
    return 2;
  }

  prj->w[1] = 1.0/prj->w[0];

  prj->w[3] = prj->r0*cosd(prj->pv[2]);
  if (prj->w[3] == 0.0) {
    return 2;
  }

  prj->w[4] = 1.0/prj->w[3];
  prj->w[5] = 1.0/tand(prj->pv[1]);
d4723 1
a4723 1
  prj->w[2] = prj->w[3]*prj->w[5];
d4725 2
a4726 2
  prj->prjx2s = copx2s;
  prj->prjs2x = cops2x;
d4728 1
a4728 1
  return prjoff(prj, 0.0, prj->pv[1]);
d4742 45
a4786 45
  int mx, my, rowlen, rowoff;
  double alpha, dy, dy2, r, xj;
  register int ix, iy, *statp;
  register const double *xp, *yp;
  register double *phip, *thetap;

  /* Initialize. */
  if (prj == 0x0) return 1;
  if (prj->flag != COP) {
    if (copset(prj)) return 2;
  }

  if (ny > 0) {
    mx = nx;
    my = ny;
  } else {
    mx = 1;
    my = 1;
    ny = nx;
  }


  /* Do x dependence. */
  xp = x;
  rowoff = 0;
  rowlen = nx*spt;
  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    xj = *xp + prj->x0;

    phip = phi + rowoff;
    for (iy = 0; iy < my; iy++) {
      *phip = xj;
      phip += rowlen;
    }
  }


  /* Do y dependence. */
  yp = y;
  phip   = phi;
  thetap = theta;
  statp  = stat;
  for (iy = 0; iy < ny; iy++, yp += sxy) {
    dy  = prj->w[2] - (*yp + prj->y0);
    dy2 = dy*dy;
d4788 5
a4792 2
    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
      xj = *phip;
d4794 5
a4798 2
      r = sqrt(xj*xj + dy2);
      if (prj->pv[1] < 0.0) r = -r;
d4800 3
a4802 4
      if (r == 0.0) {
        alpha = 0.0;
      } else {
        alpha = atan2d(xj/r, dy/r);
d4804 1
d4806 1
a4806 7
      *phip = alpha*prj->w[1];
      *thetap = prj->pv[1] + atand(prj->w[5] - r*prj->w[4]);
      *(statp++) = 0;
    }
  }

  return 0;
d4820 53
a4872 53
  int mphi, mtheta, rowlen, rowoff, status;
  double alpha, cosalpha, r, s, t, sinalpha, y0;
  register int iphi, itheta, istat, *statp;
  register const double *phip, *thetap;
  register double *xp, *yp;

  /* Initialize. */
  if (prj == 0x0) return 1;
  if (prj->flag != COP) {
    if (copset(prj)) return 2;
  }

  if (ntheta > 0) {
    mphi   = nphi;
    mtheta = ntheta;
  } else {
    mphi   = 1;
    mtheta = 1;
    ntheta = nphi;
  }

  status = 0;


  /* Do phi dependence. */
  phip = phi;
  rowoff = 0;
  rowlen = nphi*sxy;
  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    alpha = prj->w[0]*(*phip);
    sinalpha = sind(alpha);
    cosalpha = cosd(alpha);

    xp = x + rowoff;
    yp = y + rowoff;
    for (itheta = 0; itheta < mtheta; itheta++) {
      *xp = sinalpha;
      *yp = cosalpha;
      xp += rowlen;
      yp += rowlen;
    }
  }


  /* Do theta dependence. */
  thetap = theta;
  xp = x;
  yp = y;
  statp = stat;
  y0 = prj->y0 - prj->w[2];
  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    t = *thetap - prj->pv[1];
    s = cosd(t);
d4874 5
a4878 5
    istat = 0;
    if (s == 0.0) {
      r = 0.0;
      istat  = 1;
      status = 4;
d4880 2
a4881 2
    } else {
      r = prj->w[2] - prj->w[3]*sind(t)/s;
d4883 12
a4894 12
      if (prj->bounds && r*prj->w[0] < 0.0) {
        istat  = 1;
        status = 4;
      }
    }

    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
      *xp =  r*(*xp) - prj->x0;
      *yp = -r*(*yp) - y0;
      *(statp++) = istat;
    }
  }
d4896 1
a4896 1
  return status;
d4935 24
a4958 1
  double theta1, theta2;
d4960 4
a4963 1
  if (prj == 0x0) return 1;
d4965 1
a4965 2
  prj->flag = COE;
  strcpy(prj->code, "COE");
d4967 6
a4972 31
  if (undefined(prj->pv[1])) {
    return 2;
  }
  if (undefined(prj->pv[2])) prj->pv[2] = 0.0;
  if (prj->r0 == 0.0) prj->r0 = R2D;

  strcpy(prj->name, "conic equal area");
  prj->category  = CONIC;
  prj->pvrange   = 102;
  prj->simplezen = 0;
  prj->equiareal = 1;
  prj->conformal = 0;
  prj->global    = 1;
  prj->divergent = 0;

  theta1 = prj->pv[1] - prj->pv[2];
  theta2 = prj->pv[1] + prj->pv[2];

  prj->w[0] = (sind(theta1) + sind(theta2))/2.0;
  if (prj->w[0] == 0.0) {
    return 2;
  }

  prj->w[1] = 1.0/prj->w[0];

  prj->w[3] = prj->r0/prj->w[0];
  prj->w[4] = 1.0 + sind(theta1)*sind(theta2);
  prj->w[5] = 2.0*prj->w[0];
  prj->w[6] = prj->w[3]*prj->w[3]*prj->w[4];
  prj->w[7] = 1.0/(2.0*prj->r0*prj->w[3]);
  prj->w[8] = prj->w[3]*sqrt(prj->w[4] + prj->w[5]);
d4974 1
a4974 1
  prj->w[2] = prj->w[3]*sqrt(prj->w[4] - prj->w[5]*sind(prj->pv[1]));
d4976 2
a4977 2
  prj->prjx2s = coex2s;
  prj->prjs2x = coes2x;
d4979 1
a4979 1
  return prjoff(prj, 0.0, prj->pv[1]);
d4993 48
a5040 48
  int mx, my, rowlen, rowoff, status;
  double alpha, dy, dy2, r, t, w, xj;
  const double tol = 1.0e-12;
  register int ix, iy, istat, *statp;
  register const double *xp, *yp;
  register double *phip, *thetap;

  /* Initialize. */
  if (prj == 0x0) return 1;
  if (prj->flag != COE) {
    if (coeset(prj)) return 2;
  }

  if (ny > 0) {
    mx = nx;
    my = ny;
  } else {
    mx = 1;
    my = 1;
    ny = nx;
  }

  status = 0;


  /* Do x dependence. */
  xp = x;
  rowoff = 0;
  rowlen = nx*spt;
  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    xj = *xp + prj->x0;

    phip = phi + rowoff;
    for (iy = 0; iy < my; iy++) {
      *phip = xj;
      phip += rowlen;
    }
  }


  /* Do y dependence. */
  yp = y;
  phip   = phi;
  thetap = theta;
  statp  = stat;
  for (iy = 0; iy < ny; iy++, yp += sxy) {
    dy  = prj->w[2] - (*yp + prj->y0);
    dy2 = dy*dy;
d5042 2
a5043 2
    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
      xj = *phip;
d5045 2
a5046 2
      r = sqrt(xj*xj + dy2);
      if (prj->pv[1] < 0.0) r = -r;
d5048 5
a5052 5
      if (r == 0.0) {
        alpha = 0.0;
      } else {
        alpha = atan2d(xj/r, dy/r);
      }
d5054 2
a5055 9
      istat = 0;
      if (fabs(r - prj->w[8]) < tol) {
        t = -90.0;
      } else {
        w = (prj->w[6] - r*r)*prj->w[7];
        if (fabs(w) > 1.0) {
          if (fabs(w-1.0) < tol) {
            t = 90.0;
          } else if (fabs(w+1.0) < tol) {
d5057 20
a5076 8
          } else {
            t = 0.0;
            istat  = 1;
            status = 3;
          }
        } else {
          t = asind(w);
        }
d5078 1
d5080 1
a5080 7
      *phip = alpha*prj->w[1];
      *thetap = t;
      *(statp++) = istat;
    }
  }

  return status;
d5094 54
a5147 61
  int mphi, mtheta, rowlen, rowoff;
  double alpha, cosalpha, r, sinalpha, y0;
  register int iphi, itheta, *statp;
  register const double *phip, *thetap;
  register double *xp, *yp;

  /* Initialize. */
  if (prj == 0x0) return 1;
  if (prj->flag != COE) {
    if (coeset(prj)) return 2;
  }

  if (ntheta > 0) {
    mphi   = nphi;
    mtheta = ntheta;
  } else {
    mphi   = 1;
    mtheta = 1;
    ntheta = nphi;
  }


  /* Do phi dependence. */
  phip = phi;
  rowoff = 0;
  rowlen = nphi*sxy;
  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    alpha = prj->w[0]*(*phip);
    sinalpha = sind(alpha);
    cosalpha = cosd(alpha);

    xp = x + rowoff;
    yp = y + rowoff;
    for (itheta = 0; itheta < mtheta; itheta++) {
      *xp = sinalpha;
      *yp = cosalpha;
      xp += rowlen;
      yp += rowlen;
    }
  }


  /* Do theta dependence. */
  thetap = theta;
  xp = x;
  yp = y;
  statp = stat;
  y0 = prj->y0 - prj->w[2];
  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    if (*thetap == -90.0) {
      r = prj->w[8];
    } else {
      r = prj->w[3]*sqrt(prj->w[4] - prj->w[5]*sind(*thetap));
    }

    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
      *xp =  r*(*xp) - prj->x0;
      *yp = -r*(*yp) - y0;
      *(statp++) = 0;
    }
  }
d5149 8
a5156 1
  return 0;
d5190 1
a5190 1
  if (prj == 0x0) return 1;
d5192 2
a5193 2
  prj->flag = COD;
  strcpy(prj->code, "COD");
d5195 24
a5218 28
  if (undefined(prj->pv[1])) {
    return 2;
  }
  if (undefined(prj->pv[2])) prj->pv[2] = 0.0;
  if (prj->r0 == 0.0) prj->r0 = R2D;

  strcpy(prj->name, "conic equidistant");
  prj->category  = CONIC;
  prj->pvrange   = 102;
  prj->simplezen = 0;
  prj->equiareal = 0;
  prj->conformal = 0;
  prj->global    = 1;
  prj->divergent = 0;

  if (prj->pv[2] == 0.0) {
    prj->w[0] = prj->r0*sind(prj->pv[1])*D2R;
  } else {
    prj->w[0] = prj->r0*sind(prj->pv[1])*sind(prj->pv[2])/prj->pv[2];
  }

  if (prj->w[0] == 0.0) {
    return 2;
  }

  prj->w[1] = 1.0/prj->w[0];
  prj->w[2] = prj->r0*cosd(prj->pv[2])*cosd(prj->pv[1])/prj->w[0];
  prj->w[3] = prj->w[2] + prj->pv[1];
d5220 3
a5222 2
  prj->prjx2s = codx2s;
  prj->prjs2x = cods2x;
d5224 4
a5227 1
  return prjoff(prj, 0.0, prj->pv[1]);
d5241 48
a5288 45
  int mx, my, rowlen, rowoff;
  double alpha, dy, dy2, r, xj;
  register int ix, iy, *statp;
  register const double *xp, *yp;
  register double *phip, *thetap;

  /* Initialize. */
  if (prj == 0x0) return 1;
  if (prj->flag != COD) {
    if (codset(prj)) return 2;
  }

  if (ny > 0) {
    mx = nx;
    my = ny;
  } else {
    mx = 1;
    my = 1;
    ny = nx;
  }


  /* Do x dependence. */
  xp = x;
  rowoff = 0;
  rowlen = nx*spt;
  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    xj = *xp + prj->x0;

    phip = phi + rowoff;
    for (iy = 0; iy < my; iy++) {
      *phip = xj;
      phip += rowlen;
    }
  }


  /* Do y dependence. */
  yp = y;
  phip   = phi;
  thetap = theta;
  statp  = stat;
  for (iy = 0; iy < ny; iy++, yp += sxy) {
    dy  = prj->w[2] - (*yp + prj->y0);
    dy2 = dy*dy;
d5290 2
a5291 2
    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
      xj = *phip;
d5293 5
a5297 2
      r = sqrt(xj*xj + dy2);
      if (prj->pv[1] < 0.0) r = -r;
d5299 3
a5301 4
      if (r == 0.0) {
        alpha = 0.0;
      } else {
        alpha = atan2d(xj/r, dy/r);
d5303 1
d5305 1
a5305 7
      *phip = alpha*prj->w[1];
      *thetap = prj->w[3] - r;
      *(statp++) = 0;
    }
  }

  return 0;
d5319 57
a5375 57
  int mphi, mtheta, rowlen, rowoff;
  double alpha, cosalpha, r, sinalpha, y0;
  register int iphi, itheta, *statp;
  register const double *phip, *thetap;
  register double *xp, *yp;

  /* Initialize. */
  if (prj == 0x0) return 1;
  if (prj->flag != COD) {
    if (codset(prj)) return 2;
  }

  if (ntheta > 0) {
    mphi   = nphi;
    mtheta = ntheta;
  } else {
    mphi   = 1;
    mtheta = 1;
    ntheta = nphi;
  }


  /* Do phi dependence. */
  phip = phi;
  rowoff = 0;
  rowlen = nphi*sxy;
  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    alpha = prj->w[0]*(*phip);
    sinalpha = sind(alpha);
    cosalpha = cosd(alpha);

    xp = x + rowoff;
    yp = y + rowoff;
    for (itheta = 0; itheta < mtheta; itheta++) {
      *xp = sinalpha;
      *yp = cosalpha;
      xp += rowlen;
      yp += rowlen;
    }
  }


  /* Do theta dependence. */
  thetap = theta;
  xp = x;
  yp = y;
  statp = stat;
  y0 = prj->y0 - prj->w[2];
  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    r = prj->w[3] - *thetap;

    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
      *xp =  r*(*xp) - prj->x0;
      *yp = -r*(*yp) - y0;
      *(statp++) = 0;
    }
  }
d5377 1
a5377 1
  return 0;
d5414 1
a5414 1
  double cos1, cos2, tan1, tan2, theta1, theta2;
d5416 1
a5416 1
  if (prj == 0x0) return 1;
d5418 2
a5419 2
  prj->flag = COO;
  strcpy(prj->code, "COO");
d5421 31
a5451 40
  if (undefined(prj->pv[1])) {
    return 2;
  }
  if (undefined(prj->pv[2])) prj->pv[2] = 0.0;
  if (prj->r0 == 0.0) prj->r0 = R2D;

  strcpy(prj->name, "conic orthomorphic");
  prj->category  = CONIC;
  prj->pvrange   = 102;
  prj->simplezen = 0;
  prj->equiareal = 0;
  prj->conformal = 1;
  prj->global    = 0;
  prj->divergent = 1;

  theta1 = prj->pv[1] - prj->pv[2];
  theta2 = prj->pv[1] + prj->pv[2];

  tan1 = tand((90.0 - theta1)/2.0);
  cos1 = cosd(theta1);

  if (theta1 == theta2) {
    prj->w[0] = sind(theta1);
  } else {
    tan2 = tand((90.0 - theta2)/2.0);
    cos2 = cosd(theta2);
    prj->w[0] = log(cos2/cos1)/log(tan2/tan1);
  }
  if (prj->w[0] == 0.0) {
    return 2;
  }

  prj->w[1] = 1.0/prj->w[0];

  prj->w[3] = prj->r0*(cos1/prj->w[0])/pow(tan1,prj->w[0]);
  if (prj->w[3] == 0.0) {
    return 2;
  }
  prj->w[2] = prj->w[3]*pow(tand((90.0 - prj->pv[1])/2.0),prj->w[0]);
  prj->w[4] = 1.0/prj->w[3];
d5453 8
a5460 2
  prj->prjx2s = coox2s;
  prj->prjs2x = coos2x;
d5462 4
a5465 1
  return prjoff(prj, 0.0, prj->pv[1]);
d5479 47
a5525 47
  int mx, my, rowlen, rowoff, status;
  double alpha, dy, dy2, r, t, xj;
  register int ix, iy, istat, *statp;
  register const double *xp, *yp;
  register double *phip, *thetap;

  /* Initialize. */
  if (prj == 0x0) return 1;
  if (prj->flag != COO) {
    if (cooset(prj)) return 2;
  }

  if (ny > 0) {
    mx = nx;
    my = ny;
  } else {
    mx = 1;
    my = 1;
    ny = nx;
  }

  status = 0;


  /* Do x dependence. */
  xp = x;
  rowoff = 0;
  rowlen = nx*spt;
  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    xj = *xp + prj->x0;

    phip = phi + rowoff;
    for (iy = 0; iy < my; iy++) {
      *phip = xj;
      phip += rowlen;
    }
  }


  /* Do y dependence. */
  yp = y;
  phip   = phi;
  thetap = theta;
  statp  = stat;
  for (iy = 0; iy < ny; iy++, yp += sxy) {
    dy  = prj->w[2] - (*yp + prj->y0);
    dy2 = dy*dy;
d5527 2
a5528 2
    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
      xj = *phip;
d5530 2
a5531 2
      r = sqrt(xj*xj + dy2);
      if (prj->pv[1] < 0.0) r = -r;
d5533 18
a5550 5
      if (r == 0.0) {
        alpha = 0.0;
      } else {
        alpha = atan2d(xj/r, dy/r);
      }
d5552 3
a5554 11
      istat = 0;
      if (r == 0.0) {
        if (prj->w[0] < 0.0) {
          t = -90.0;
        } else {
          t = 0.0;
          istat  = 1;
          status = 3;
        }
      } else {
        t = 90.0 - 2.0*atand(pow(r*prj->w[4],prj->w[1]));
d5556 1
d5558 1
a5558 7
      *phip = alpha*prj->w[1];
      *thetap = t;
      *(statp++) = istat;
    }
  }

  return status;
d5572 62
a5633 52
  int mphi, mtheta, rowlen, rowoff, status;
  double alpha, cosalpha, r, sinalpha, y0;
  register int iphi, itheta, istat, *statp;
  register const double *phip, *thetap;
  register double *xp, *yp;

  /* Initialize. */
  if (prj == 0x0) return 1;
  if (prj->flag != COO) {
    if (cooset(prj)) return 2;
  }

  if (ntheta > 0) {
    mphi   = nphi;
    mtheta = ntheta;
  } else {
    mphi   = 1;
    mtheta = 1;
    ntheta = nphi;
  }

  status = 0;


  /* Do phi dependence. */
  phip = phi;
  rowoff = 0;
  rowlen = nphi*sxy;
  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    alpha = prj->w[0]*(*phip);
    sinalpha = sind(alpha);
    cosalpha = cosd(alpha);

    xp = x + rowoff;
    yp = y + rowoff;
    for (itheta = 0; itheta < mtheta; itheta++) {
      *xp = sinalpha;
      *yp = cosalpha;
      xp += rowlen;
      yp += rowlen;
    }
  }


  /* Do theta dependence. */
  thetap = theta;
  xp = x;
  yp = y;
  statp = stat;
  y0 = prj->y0 - prj->w[2];
  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    istat = 0;
d5635 6
a5640 16
    if (*thetap == -90.0) {
      r = 0.0;
      if (prj->w[0] >= 0.0) {
        istat  = 1;
        status = 4;
      }
    } else {
      r = prj->w[3]*pow(tand((90.0 - *thetap)/2.0),prj->w[0]);
    }

    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
      *xp =  r*(*xp) - prj->x0;
      *yp = -r*(*yp) - y0;
      *(statp++) = istat;
    }
  }
d5642 1
a5642 1
  return status;
d5672 4
a5675 1
  if (prj == 0x0) return 1;
d5677 3
a5679 2
  prj->flag = BON;
  strcpy(prj->code, "BON");
d5681 23
a5703 26
  if (undefined(prj->pv[1])) {
    return 2;
  }

  if (prj->pv[1] == 0.0) {
    /* Sanson-Flamsteed. */
    return sflset(prj);
  }

  strcpy(prj->name, "Bonne's");
  prj->category  = POLYCONIC;
  prj->pvrange   = 101;
  prj->simplezen = 0;
  prj->equiareal = 1;
  prj->conformal = 0;
  prj->global    = 1;
  prj->divergent = 0;

  if (prj->r0 == 0.0) {
    prj->r0 = R2D;
    prj->w[1] = 1.0;
    prj->w[2] = prj->r0*cosd(prj->pv[1])/sind(prj->pv[1]) + prj->pv[1];
  } else {
    prj->w[1] = prj->r0*D2R;
    prj->w[2] = prj->r0*(cosd(prj->pv[1])/sind(prj->pv[1]) + prj->pv[1]*D2R);
  }
d5705 2
a5706 2
  prj->prjx2s = bonx2s;
  prj->prjs2x = bons2x;
d5708 1
a5708 1
  return prjoff(prj, 0.0, 0.0);
d5722 51
a5772 51
  int mx, my, rowlen, rowoff;
  double alpha, dy, dy2, costhe, r, s, t, xj;
  register int ix, iy, *statp;
  register const double *xp, *yp;
  register double *phip, *thetap;


  /* Initialize. */
  if (prj == 0x0) return 1;
  if (prj->pv[1] == 0.0) {
    /* Sanson-Flamsteed. */
    return sflx2s(prj, nx, ny, sxy, spt, x, y, phi, theta, stat);
  }

  if (prj->flag != BON) {
    if (bonset(prj)) return 2;
  }

  if (ny > 0) {
    mx = nx;
    my = ny;
  } else {
    mx = 1;
    my = 1;
    ny = nx;
  }


  /* Do x dependence. */
  xp = x;
  rowoff = 0;
  rowlen = nx*spt;
  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    xj = *xp + prj->x0;

    phip = phi + rowoff;
    for (iy = 0; iy < my; iy++) {
      *phip = xj;
      phip += rowlen;
    }
  }


  /* Do y dependence. */
  yp = y;
  phip   = phi;
  thetap = theta;
  statp  = stat;
  for (iy = 0; iy < ny; iy++, yp += sxy) {
    dy  = prj->w[2] - (*yp + prj->y0);
    dy2 = dy*dy;
d5774 2
a5775 2
    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
      xj = *phip;
d5777 2
a5778 2
      r = sqrt(xj*xj + dy2);
      if (prj->pv[1] < 0.0) r = -r;
d5780 17
a5796 4
      if (r == 0.0) {
        alpha = 0.0;
      } else {
        alpha = atan2d(xj/r, dy/r);
d5798 1
d5800 1
a5800 15
      t = (prj->w[2] - r)/prj->w[1];
      costhe = cosd(t);
      if (costhe == 0.0) {
        s = 0.0;
      } else {
        s = alpha*(r/prj->r0)/costhe;
      }

      *phip = s;
      *thetap = t;
      *(statp++) = 0;
    }
  }

  return 0;
d5814 52
a5865 60
  int mphi, mtheta, rowlen, rowoff;
  double alpha, r, s, y0;
  register int iphi, itheta, *statp;
  register const double *phip, *thetap;
  register double *xp, *yp;

  /* Initialize. */
  if (prj == 0x0) return 1;
  if (prj->pv[1] == 0.0) {
    /* Sanson-Flamsteed. */
    return sfls2x(prj, nphi, ntheta, spt, sxy, phi, theta, x, y, stat);
  }

  if (prj->flag != BON) {
    if (bonset(prj)) return 2;
  }

  if (ntheta > 0) {
    mphi   = nphi;
    mtheta = ntheta;
  } else {
    mphi   = 1;
    mtheta = 1;
    ntheta = nphi;
  }

  y0 = prj->y0 - prj->w[2];


  /* Do phi dependence. */
  phip = phi;
  rowoff = 0;
  rowlen = nphi*sxy;
  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    s = prj->r0*(*phip);

    xp = x + rowoff;
    for (itheta = 0; itheta < mtheta; itheta++) {
      *xp = s;
      xp += rowlen;
    }
  }


  /* Do theta dependence. */
  thetap = theta;
  xp = x;
  yp = y;
  statp = stat;
  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    r = prj->w[2] - prj->w[1]*(*thetap);
    s = cosd(*thetap)/r;

    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
      alpha = s*(*xp);
      *xp =  r*sind(alpha) - prj->x0;
      *yp = -r*cosd(alpha) - y0;
      *(statp++) = 0;
    }
  }
d5867 9
a5875 1
  return 0;
d5903 1
a5903 1
  if (prj == 0x0) return 1;
d5905 2
a5906 2
  prj->flag = PCO;
  strcpy(prj->code, "PCO");
d5908 19
a5926 19
  strcpy(prj->name, "polyconic");
  prj->category  = POLYCONIC;
  prj->pvrange   = 0;
  prj->simplezen = 0;
  prj->equiareal = 0;
  prj->conformal = 0;
  prj->global    = 1;
  prj->divergent = 0;

  if (prj->r0 == 0.0) {
    prj->r0 = R2D;
    prj->w[0] = 1.0;
    prj->w[1] = 1.0;
    prj->w[2] = 360.0/PI;
  } else {
    prj->w[0] = prj->r0*D2R;
    prj->w[1] = 1.0/prj->w[0];
    prj->w[2] = 2.0*prj->r0;
  }
d5928 2
a5929 2
  prj->prjx2s = pcox2s;
  prj->prjs2x = pcos2x;
d5931 1
a5931 1
  return prjoff(prj, 0.0, 0.0);
d5945 68
a6012 59
  int mx, my, rowlen, rowoff;
  double f, fneg, fpos, lambda, tanthe, the, theneg, thepos, w, x1, xj, xx,
         yj, ymthe, y1;
  const double tol = 1.0e-12;
  register int ix, iy, k, *statp;
  register const double *xp, *yp;
  register double *phip, *thetap;


  /* Initialize. */
  if (prj == 0x0) return 1;
  if (prj->flag != PCO) {
    if (pcoset(prj)) return 2;
  }

  if (ny > 0) {
    mx = nx;
    my = ny;
  } else {
    mx = 1;
    my = 1;
    ny = nx;
  }


  /* Do x dependence. */
  xp = x;
  rowoff = 0;
  rowlen = nx*spt;
  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    xj = *xp + prj->x0;

    phip = phi + rowoff;
    for (iy = 0; iy < my; iy++) {
      *phip = xj;
      phip += rowlen;
    }
  }


  /* Do y dependence. */
  yp = y;
  phip   = phi;
  thetap = theta;
  statp  = stat;
  for (iy = 0; iy < ny; iy++, yp += sxy) {
    yj = *yp + prj->y0;
    w  = fabs(yj*prj->w[1]);

    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
      xj = *phip;

      if (w < tol) {
        *phip = xj*prj->w[1];
        *thetap = 0.0;

      } else if (fabs(w-90.0) < tol) {
        *phip = 0.0;
        *thetap = copysign(90.0, yj);
d6014 53
a6066 62
      } else {
        /* Iterative solution using weighted division of the interval. */
        if (yj > 0.0) {
          thepos =  90.0;
        } else {
          thepos = -90.0;
        }
        theneg = 0.0;

        xx = xj*xj;
        ymthe = yj - prj->w[0]*thepos;
        fpos = xx + ymthe*ymthe;
        fneg = -999.0;

        for (k = 0; k < 64; k++) {
          if (fneg < -100.0) {
            /* Equal division of the interval. */
            the = (thepos+theneg)/2.0;
          } else {
            /* Weighted division of the interval. */
            lambda = fpos/(fpos-fneg);
            if (lambda < 0.1) {
              lambda = 0.1;
            } else if (lambda > 0.9) {
              lambda = 0.9;
            }
            the = thepos - lambda*(thepos-theneg);
          }

          /* Compute the residue. */
          ymthe = yj - prj->w[0]*(the);
          tanthe = tand(the);
          f = xx + ymthe*(ymthe - prj->w[2]/tanthe);

          /* Check for convergence. */
          if (fabs(f) < tol) break;
          if (fabs(thepos-theneg) < tol) break;

          /* Redefine the interval. */
          if (f > 0.0) {
            thepos = the;
            fpos = f;
          } else {
            theneg = the;
            fneg = f;
          }
        }

        x1 = prj->r0 - ymthe*tanthe;
        y1 = xj*tanthe;
        if (x1 == 0.0 && y1 == 0.0) {
          *phip = 0.0;
        } else {
          *phip = atan2d(y1, x1)/sind(the);
        }

        *thetap = the;
      }

      *(statp++) = 0;
    }
  }
d6068 1
a6068 1
  return 0;
d6082 57
a6138 54
  int mphi, mtheta, rowlen, rowoff;
  double alpha, costhe, cotthe, sinthe, therad;
  register int iphi, itheta, *statp;
  register const double *phip, *thetap;
  register double *xp, *yp;

  /* Initialize. */
  if (prj == 0x0) return 1;
  if (prj->flag != PCO) {
    if (pcoset(prj)) return 2;
  }

  if (ntheta > 0) {
    mphi   = nphi;
    mtheta = ntheta;
  } else {
    mphi   = 1;
    mtheta = 1;
    ntheta = nphi;
  }


  /* Do phi dependence. */
  phip = phi;
  rowoff = 0;
  rowlen = nphi*sxy;
  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    xp = x + rowoff;
    for (itheta = 0; itheta < mtheta; itheta++) {
      *xp = *phip;
      xp += rowlen;
    }
  }


  /* Do theta dependence. */
  thetap = theta;
  xp = x;
  yp = y;
  statp = stat;
  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    therad = (*thetap)*D2R;
    costhe = cosd(*thetap);
    sinthe = sind(*thetap);

    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
      if (sinthe == 0.0) {
        *xp =  prj->w[0]*(*xp) - prj->x0;
        *yp = -prj->y0;
      } else {
        alpha  = (*xp)*sinthe;
        cotthe = costhe/sinthe;
        *xp = prj->r0*cotthe*sind(alpha) - prj->x0;
        *yp = prj->r0*(cotthe*(1.0 - cosd(alpha)) + therad) - prj->y0;
d6140 1
d6142 1
a6142 5
      *(statp++) = 0;
    }
  }

  return 0;
d6169 1
a6169 1
  if (prj == 0x0) return 1;
d6171 2
a6172 2
  prj->flag = TSC;
  strcpy(prj->code, "TSC");
d6174 17
a6190 17
  strcpy(prj->name, "tangential spherical cube");
  prj->category  = QUADCUBE;
  prj->pvrange   = 0;
  prj->simplezen = 0;
  prj->equiareal = 0;
  prj->conformal = 0;
  prj->global    = 1;
  prj->divergent = 0;

  if (prj->r0 == 0.0) {
    prj->r0 = R2D;
    prj->w[0] = 45.0;
    prj->w[1] = 1.0/45.0;
  } else {
    prj->w[0] = prj->r0*PI/4.0;
    prj->w[1] = 1.0/prj->w[0];
  }
d6192 2
a6193 2
  prj->prjx2s = tscx2s;
  prj->prjs2x = tscs2x;
d6195 1
a6195 1
  return prjoff(prj, 0.0, 0.0);
d6209 116
a6324 110
  int mx, my, rowlen, rowoff, status;
  double l, m, n, xf, yf;
  register int ix, iy, *statp;
  register const double *xp, *yp;
  register double *phip, *thetap;


  /* Initialize. */
  if (prj == 0x0) return 1;
  if (prj->flag != TSC) {
    if (tscset(prj)) return 2;
  }

  if (ny > 0) {
    mx = nx;
    my = ny;
  } else {
    mx = 1;
    my = 1;
    ny = nx;
  }

  status = 0;


  /* Do x dependence. */
  xp = x;
  rowoff = 0;
  rowlen = nx*spt;
  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    xf = (*xp + prj->x0)*prj->w[1];

    phip = phi + rowoff;
    for (iy = 0; iy < my; iy++) {
      *phip = xf;
      phip += rowlen;
    }
  }


  /* Do y dependence. */
  yp = y;
  phip   = phi;
  thetap = theta;
  statp  = stat;
  for (iy = 0; iy < ny; iy++, yp += sxy) {
    yf = (*yp + prj->y0)*prj->w[1];

    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
      xf = *phip;

      /* Check bounds. */
      if (fabs(xf) <= 1.0) {
        if (fabs(yf) > 3.0) {
          *phip = 0.0;
          *thetap = 0.0;
          *(statp++) = 1;
          status = 3;
          continue;
        }
      } else {
        if (fabs(xf) > 7.0 || fabs(yf) > 1.0) {
          *phip = 0.0;
          *thetap = 0.0;
          *(statp++) = 1;
          status = 3;
          continue;
        }
      }

      /* Map negative faces to the other side. */
      if (xf < -1.0) xf += 8.0;

      /* Determine the face. */
      if (xf > 5.0) {
        /* face = 4 */
        xf = xf - 6.0;
        m  = -1.0/sqrt(1.0 + xf*xf + yf*yf);
        l  = -m*xf;
        n  = -m*yf;
      } else if (xf > 3.0) {
        /* face = 3 */
        xf = xf - 4.0;
        l  = -1.0/sqrt(1.0 + xf*xf + yf*yf);
        m  =  l*xf;
        n  = -l*yf;
      } else if (xf > 1.0) {
        /* face = 2 */
        xf = xf - 2.0;
        m  =  1.0/sqrt(1.0 + xf*xf + yf*yf);
        l  = -m*xf;
        n  =  m*yf;
      } else if (yf > 1.0) {
        /* face = 0 */
        yf = yf - 2.0;
        n  = 1.0/sqrt(1.0 + xf*xf + yf*yf);
        l  = -n*yf;
        m  =  n*xf;
      } else if (yf < -1.0) {
        /* face = 5 */
        yf = yf + 2.0;
        n  = -1.0/sqrt(1.0 + xf*xf + yf*yf);
        l  = -n*yf;
        m  = -n*xf;
      } else {
        /* face = 1 */
        l  =  1.0/sqrt(1.0 + xf*xf + yf*yf);
        m  =  l*xf;
        n  =  l*yf;
      }
d6326 2
a6327 4
      if (l == 0.0 && m == 0.0) {
        *phip = 0.0;
      } else {
        *phip = atan2d(m, l);
d6329 1
d6331 1
a6331 6
      *thetap = asind(n);
      *(statp++) = 0;
    }
  }

  return status;
d6345 140
a6484 119
  int face, mphi, mtheta, rowlen, rowoff, status;
  double cosphi, costhe, l, m, n, sinphi, sinthe, x0, xf, y0, yf, zeta;
  const double tol = 1.0e-12;
  register int iphi, istat, itheta, *statp;
  register const double *phip, *thetap;
  register double *xp, *yp;

  /* Initialize. */
  if (prj == 0x0) return 1;
  if (prj->flag != TSC) {
    if (tscset(prj)) return 2;
  }

  if (ntheta > 0) {
    mphi   = nphi;
    mtheta = ntheta;
  } else {
    mphi   = 1;
    mtheta = 1;
    ntheta = nphi;
  }

  status = 0;


  /* Do phi dependence. */
  phip = phi;
  rowoff = 0;
  rowlen = nphi*sxy;
  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    cosphi = cosd(*phip);
    sinphi = sind(*phip);

    xp = x + rowoff;
    yp = y + rowoff;
    for (itheta = 0; itheta < mtheta; itheta++) {
      *xp = cosphi;
      *yp = sinphi;
      xp += rowlen;
      yp += rowlen;
    }
  }


  /* Do theta dependence. */
  thetap = theta;
  xp = x;
  yp = y;
  statp = stat;
  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    costhe = cosd(*thetap);
    sinthe = sind(*thetap);

    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
      l = costhe*(*xp);
      m = costhe*(*yp);
      n = sinthe;

      face = 0;
      zeta = n;
      if (l > zeta) {
        face = 1;
        zeta = l;
      }
      if (m > zeta) {
        face = 2;
        zeta = m;
      }
      if (-l > zeta) {
        face = 3;
        zeta = -l;
      }
      if (-m > zeta) {
        face = 4;
        zeta = -m;
      }
      if (-n > zeta) {
        face = 5;
        zeta = -n;
      }

      switch (face) {
      case 1:
        xf =  m/zeta;
        yf =  n/zeta;
        x0 =  0.0;
        y0 =  0.0;
        break;
      case 2:
        xf = -l/zeta;
        yf =  n/zeta;
        x0 =  2.0;
        y0 =  0.0;
        break;
      case 3:
        xf = -m/zeta;
        yf =  n/zeta;
        x0 =  4.0;
        y0 =  0.0;
        break;
      case 4:
        xf =  l/zeta;
        yf =  n/zeta;
        x0 =  6.0;
        y0 =  0.0;
        break;
      case 5:
        xf =  m/zeta;
        yf =  l/zeta;
        x0 =  0.0;
        y0 = -2.0;
        break;
      default:
        /* face == 0 */
        xf =  m/zeta;
        yf = -l/zeta;
        x0 =  0.0;
        y0 =  2.0;
        break;
d6486 1
d6488 1
a6488 23
      istat = 0;
      if (fabs(xf) > 1.0) {
        if (fabs(xf) > 1.0+tol) {
          istat  = 1;
          status = 4;
        }
        xf = copysign(1.0, xf);
      }
      if (fabs(yf) > 1.0) {
        if (fabs(yf) > 1.0+tol) {
          istat  = 1;
          status = 4;
        }
        yf = copysign(1.0, yf);
      }

      *xp = prj->w[0]*(xf + x0) - prj->x0;
      *yp = prj->w[0]*(yf + y0) - prj->y0;
      *(statp++) = istat;
    }
  }

  return status;
d6515 1
a6515 1
  if (prj == 0x0) return 1;
d6517 2
a6518 2
  prj->flag = CSC;
  strcpy(prj->code, "CSC");
d6520 17
a6536 17
  strcpy(prj->name, "COBE quadrilateralized spherical cube");
  prj->category  = QUADCUBE;
  prj->pvrange   = 0;
  prj->simplezen = 0;
  prj->equiareal = 0;
  prj->conformal = 0;
  prj->global    = 1;
  prj->divergent = 0;

  if (prj->r0 == 0.0) {
    prj->r0 = R2D;
    prj->w[0] = 45.0;
    prj->w[1] = 1.0/45.0;
  } else {
    prj->w[0] = prj->r0*PI/4.0;
    prj->w[1] = 1.0/prj->w[0];
  }
d6538 2
a6539 2
  prj->prjx2s = cscx2s;
  prj->prjs2x = cscs2x;
d6541 1
a6541 1
  return prjoff(prj, 0.0, 0.0);
d6555 98
a6652 121
  int face, mx, my, rowlen, rowoff, status;
  double l, m, n;
  register int ix, iy, *statp;
  register const double *xp, *yp;
  register double *phip, *thetap;

  float     chi, psi, xf, xx, yf, yy, z0, z1, z2, z3, z4, z5, z6;
  const float p00 = -0.27292696;
  const float p10 = -0.07629969;
  const float p20 = -0.22797056;
  const float p30 =  0.54852384;
  const float p40 = -0.62930065;
  const float p50 =  0.25795794;
  const float p60 =  0.02584375;
  const float p01 = -0.02819452;
  const float p11 = -0.01471565;
  const float p21 =  0.48051509;
  const float p31 = -1.74114454;
  const float p41 =  1.71547508;
  const float p51 = -0.53022337;
  const float p02 =  0.27058160;
  const float p12 = -0.56800938;
  const float p22 =  0.30803317;
  const float p32 =  0.98938102;
  const float p42 = -0.83180469;
  const float p03 = -0.60441560;
  const float p13 =  1.50880086;
  const float p23 = -0.93678576;
  const float p33 =  0.08693841;
  const float p04 =  0.93412077;
  const float p14 = -1.41601920;
  const float p24 =  0.33887446;
  const float p05 = -0.63915306;
  const float p15 =  0.52032238;
  const float p06 =  0.14381585;

  /* Initialize. */
  if (prj == 0x0) return 1;
  if (prj->flag != CSC) {
    if (cscset(prj)) return 2;
  }

  if (ny > 0) {
    mx = nx;
    my = ny;
  } else {
    mx = 1;
    my = 1;
    ny = nx;
  }

  status = 0;


  /* Do x dependence. */
  xp = x;
  rowoff = 0;
  rowlen = nx*spt;
  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    xf = (*xp + prj->x0)*prj->w[1];

    phip = phi + rowoff;
    for (iy = 0; iy < my; iy++) {
      *phip = xf;
      phip += rowlen;
    }
  }


  /* Do y dependence. */
  yp = y;
  phip   = phi;
  thetap = theta;
  statp  = stat;
  for (iy = 0; iy < ny; iy++, yp += sxy) {
    yf = (*yp + prj->y0)*prj->w[1];

    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
      xf = *phip;

      /* Check bounds. */
      if (fabs(xf) <= 1.0) {
        if (fabs(yf) > 3.0) {
          *phip = 0.0;
          *thetap = 0.0;
          *(statp++) = 1;
          status = 3;
          continue;
        }
      } else {
        if (fabs(xf) > 7.0 || fabs(yf) > 1.0) {
          *phip = 0.0;
          *thetap = 0.0;
          *(statp++) = 1;
          status = 3;
          continue;
        }
      }

      /* Map negative faces to the other side. */
      if (xf < -1.0) xf += 8.0;

      /* Determine the face. */
      if (xf > 5.0) {
        face = 4;
        xf = xf - 6.0;
      } else if (xf > 3.0) {
        face = 3;
        xf = xf - 4.0;
      } else if (xf > 1.0) {
        face = 2;
        xf = xf - 2.0;
      } else if (yf > 1.0) {
        face = 0;
        yf = yf - 2.0;
      } else if (yf < -1.0) {
        face = 5;
        yf = yf + 2.0;
      } else {
        face = 1;
      }
d6654 2
a6655 2
      xx  =  xf*xf;
      yy  =  yf*yf;
d6657 86
a6742 57
      z0 = p00 + xx*(p10 + xx*(p20 + xx*(p30 + xx*(p40 + xx*(p50 +
                 xx*(p60))))));
      z1 = p01 + xx*(p11 + xx*(p21 + xx*(p31 + xx*(p41 + xx*(p51)))));
      z2 = p02 + xx*(p12 + xx*(p22 + xx*(p32 + xx*(p42))));
      z3 = p03 + xx*(p13 + xx*(p23 + xx*(p33)));
      z4 = p04 + xx*(p14 + xx*(p24));
      z5 = p05 + xx*(p15);
      z6 = p06;

      chi = z0 + yy*(z1 + yy*(z2 + yy*(z3 + yy*(z4 + yy*(z5 + yy*z6)))));
      chi = xf + xf*(1.0 - xx)*chi;

      z0 = p00 + yy*(p10 + yy*(p20 + yy*(p30 + yy*(p40 + yy*(p50 +
                 yy*(p60))))));
      z1 = p01 + yy*(p11 + yy*(p21 + yy*(p31 + yy*(p41 + yy*(p51)))));
      z2 = p02 + yy*(p12 + yy*(p22 + yy*(p32 + yy*(p42))));
      z3 = p03 + yy*(p13 + yy*(p23 + yy*(p33)));
      z4 = p04 + yy*(p14 + yy*(p24));
      z5 = p05 + yy*(p15);
      z6 = p06;

      psi = z0 + xx*(z1 + xx*(z2 + xx*(z3 + xx*(z4 + xx*(z5 + xx*z6)))));
      psi = yf + yf*(1.0 - yy)*psi;

      switch (face) {
      case 1:
        l =  1.0/sqrt(chi*chi + psi*psi + 1.0);
        m =  chi*l;
        n =  psi*l;
        break;
      case 2:
        m =  1.0/sqrt(chi*chi + psi*psi + 1.0);
        l = -chi*m;
        n =  psi*m;
        break;
      case 3:
        l = -1.0/sqrt(chi*chi + psi*psi + 1.0);
        m =  chi*l;
        n = -psi*l;
        break;
      case 4:
        m = -1.0/sqrt(chi*chi + psi*psi + 1.0);
        l = -chi*m;
        n = -psi*m;
        break;
      case 5:
        n = -1.0/sqrt(chi*chi + psi*psi + 1.0);
        l = -psi*n;
        m = -chi*n;
        break;
      default:
        /* face == 0 */
        n =  1.0/sqrt(chi*chi + psi*psi + 1.0);
        l = -psi*n;
        m =  chi*n;
        break;
      }
d6744 2
a6745 4
      if (l == 0.0 && m == 0.0) {
        *phip = 0.0;
      } else {
        *phip = atan2d(m, l);
d6747 1
d6749 1
a6749 6
      *thetap = asind(n);
      *(statp++) = 0;
    }
  }

  return status;
d6763 67
a6829 150
  int face, mphi, mtheta, rowlen, rowoff, status;
  double cosphi, costhe, eta, l, m, n, sinphi, sinthe, xi, zeta;
  const float tol = 1.0e-7;
  register int iphi, istat, itheta, *statp;
  register const double *phip, *thetap;
  register double *xp, *yp;

  float chi, chi2, chi2psi2, chi4, chipsi, psi, psi2, psi4, chi2co, psi2co,
        x0, xf, y0, yf;
  const float gstar  =  1.37484847732;
  const float mm     =  0.004869491981;
  const float gamma  = -0.13161671474;
  const float omega1 = -0.159596235474;
  const float d0  =  0.0759196200467;
  const float d1  = -0.0217762490699;
  const float c00 =  0.141189631152;
  const float c10 =  0.0809701286525;
  const float c01 = -0.281528535557;
  const float c11 =  0.15384112876;
  const float c20 = -0.178251207466;
  const float c02 =  0.106959469314;


  /* Initialize. */
  if (prj == 0x0) return 1;
  if (prj->flag != CSC) {
    if (cscset(prj)) return 2;
  }

  if (ntheta > 0) {
    mphi   = nphi;
    mtheta = ntheta;
  } else {
    mphi   = 1;
    mtheta = 1;
    ntheta = nphi;
  }

  status = 0;


  /* Do phi dependence. */
  phip = phi;
  rowoff = 0;
  rowlen = nphi*sxy;
  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    cosphi = cosd(*phip);
    sinphi = sind(*phip);

    xp = x + rowoff;
    yp = y + rowoff;
    for (itheta = 0; itheta < mtheta; itheta++) {
      *xp = cosphi;
      *yp = sinphi;
      xp += rowlen;
      yp += rowlen;
    }
  }


  /* Do theta dependence. */
  thetap = theta;
  xp = x;
  yp = y;
  statp = stat;
  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    costhe = cosd(*thetap);
    sinthe = sind(*thetap);

    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
      l = costhe*(*xp);
      m = costhe*(*yp);
      n = sinthe;

      face = 0;
      zeta = n;
      if (l > zeta) {
        face = 1;
        zeta = l;
      }
      if (m > zeta) {
        face = 2;
        zeta = m;
      }
      if (-l > zeta) {
        face = 3;
        zeta = -l;
      }
      if (-m > zeta) {
        face = 4;
        zeta = -m;
      }
      if (-n > zeta) {
        face = 5;
        zeta = -n;
      }

      switch (face) {
      case 1:
        xi  =  m;
        eta =  n;
        x0  =  0.0;
        y0  =  0.0;
        break;
      case 2:
        xi  = -l;
        eta =  n;
        x0  =  2.0;
        y0  =  0.0;
        break;
      case 3:
        xi  = -m;
        eta =  n;
        x0  =  4.0;
        y0  =  0.0;
        break;
      case 4:
        xi  =  l;
        eta =  n;
        x0  =  6.0;
        y0  =  0.0;
        break;
      case 5:
        xi  =  m;
        eta =  l;
        x0  =  0.0;
        y0  = -2.0;
        break;
      default:
        /* face == 0 */
        xi  =  m;
        eta = -l;
        x0  =  0.0;
        y0  =  2.0;
        break;
      }

      chi =  xi/zeta;
      psi = eta/zeta;

      chi2 = chi*chi;
      psi2 = psi*psi;
      chi2co = 1.0 - chi2;
      psi2co = 1.0 - psi2;

      /* Avoid floating underflows. */
      chipsi = fabs(chi*psi);
      chi4   = (chi2 > 1.0e-16) ? chi2*chi2 : 0.0;
      psi4   = (psi2 > 1.0e-16) ? psi2*psi2 : 0.0;
      chi2psi2 = (chipsi > 1.0e-16) ? chi2*psi2 : 0.0;
d6831 83
a6913 1
      xf = chi*(chi2 + chi2co*(gstar + psi2*(gamma*chi2co + mm*chi2 +
d6916 1
a6916 1
       yf = psi*(psi2 + psi2co*(gstar + chi2*(gamma*psi2co + mm*psi2 +
d6920 21
a6940 21
      istat = 0;
      if (fabs(xf) > 1.0) {
        if (fabs(xf) > 1.0+tol) {
          istat  = 1;
          status = 4;
        }
        xf = copysign(1.0, xf);
      }
      if (fabs(yf) > 1.0) {
        if (fabs(yf) > 1.0+tol) {
          istat  = 1;
          status = 4;
        }
        yf = copysign(1.0, yf);
      }

      *xp = prj->w[0]*(xf + x0) - prj->x0;
      *yp = prj->w[0]*(yf + y0) - prj->y0;
      *(statp++) = istat;
    }
  }
d6942 1
a6942 1
  return status;
d6969 1
a6969 1
  if (prj == 0x0) return 1;
d6971 2
a6972 2
  prj->flag = QSC;
  strcpy(prj->code, "QSC");
d6974 17
a6990 17
  strcpy(prj->name, "quadrilateralized spherical cube");
  prj->category  = QUADCUBE;
  prj->pvrange   = 0;
  prj->simplezen = 0;
  prj->equiareal = 1;
  prj->conformal = 0;
  prj->global    = 1;
  prj->divergent = 0;

  if (prj->r0 == 0.0) {
    prj->r0 = R2D;
    prj->w[0] = 45.0;
    prj->w[1] = 1.0/45.0;
  } else {
    prj->w[0] = prj->r0*PI/4.0;
    prj->w[1] = 1.0/prj->w[0];
  }
d6992 2
a6993 2
  prj->prjx2s = qscx2s;
  prj->prjs2x = qscs2x;
d6995 1
a6995 1
  return prjoff(prj, 0.0, 0.0);
d7009 131
a7139 93
  int direct, face, mx, my, rowlen, rowoff, status;
  double l, m, n, omega, tau, xf, yf, w, zeco, zeta;
  const double tol = 1.0e-12;
  register int ix, iy, *statp;
  register const double *xp, *yp;
  register double *phip, *thetap;


  /* Initialize. */
  if (prj == 0x0) return 1;
  if (prj->flag != QSC) {
    if (qscset(prj)) return 2;
  }

  if (ny > 0) {
    mx = nx;
    my = ny;
  } else {
    mx = 1;
    my = 1;
    ny = nx;
  }

  status = 0;


  /* Do x dependence. */
  xp = x;
  rowoff = 0;
  rowlen = nx*spt;
  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    xf = (*xp + prj->x0)*prj->w[1];

    phip = phi + rowoff;
    for (iy = 0; iy < my; iy++) {
      *phip = xf;
      phip += rowlen;
    }
  }


  /* Do y dependence. */
  yp = y;
  phip   = phi;
  thetap = theta;
  statp  = stat;
  for (iy = 0; iy < ny; iy++, yp += sxy) {
    yf = (*yp + prj->y0)*prj->w[1];

    for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
      xf = *phip;

      /* Check bounds. */
      if (fabs(xf) <= 1.0) {
        if (fabs(yf) > 3.0) {
          *phip = 0.0;
          *thetap = 0.0;
          *(statp++) = 1;
          status = 3;
          continue;
        }
      } else {
        if (fabs(xf) > 7.0 || fabs(yf) > 1.0) {
          *phip = 0.0;
          *thetap = 0.0;
          *(statp++) = 1;
          status = 3;
          continue;
        }
      }

      /* Map negative faces to the other side. */
      if (xf < -1.0) xf += 8.0;

      /* Determine the face. */
      if (xf > 5.0) {
        face = 4;
        xf -= 6.0;
      } else if (xf > 3.0) {
        face = 3;
        xf -= 4.0;
      } else if (xf > 1.0) {
        face = 2;
        xf -= 2.0;
      } else if (yf > 1.0) {
        face = 0;
        yf -= 2.0;
      } else if (yf < -1.0) {
        face = 5;
        yf += 2.0;
      } else {
        face = 1;
      }
d7141 82
a7222 44
      direct = (fabs(xf) > fabs(yf));
      if (direct) {
        if (xf == 0.0) {
          omega = 0.0;
          tau  = 1.0;
          zeta = 1.0;
          zeco = 0.0;
        } else {
          w = 15.0*yf/xf;
          omega = sind(w)/(cosd(w) - SQRT2INV);
          tau  = 1.0 + omega*omega;
          zeco = xf*xf*(1.0 - 1.0/sqrt(1.0 + tau));
          zeta = 1.0 - zeco;
        }
      } else {
        if (yf == 0.0) {
          omega = 0.0;
          tau  = 1.0;
          zeta = 1.0;
          zeco = 0.0;
        } else {
          w = 15.0*xf/yf;
          omega = sind(w)/(cosd(w) - SQRT2INV);
          tau  = 1.0 + omega*omega;
          zeco = yf*yf*(1.0 - 1.0/sqrt(1.0 + tau));
          zeta = 1.0 - zeco;
        }
      }

      if (zeta < -1.0) {
        if (zeta < -1.0-tol) {
          *phip = 0.0;
          *thetap = 0.0;
          *(statp++) = 1;
          status = 3;
          continue;
        }

        zeta = -1.0;
        zeco =  2.0;
        w    =  0.0;
      } else {
        w = sqrt(zeco*(2.0-zeco)/tau);
      }
d7224 5
a7228 75
      switch (face) {
      case 1:
        l = zeta;
        if (direct) {
          m = w;
          if (xf < 0.0) m = -m;
          n = m*omega;
        } else {
          n = w;
          if (yf < 0.0) n = -n;
          m = n*omega;
        }
        break;
      case 2:
        m = zeta;
        if (direct) {
          l = w;
          if (xf > 0.0) l = -l;
          n = -l*omega;
        } else {
          n = w;
          if (yf < 0.0) n = -n;
          l = -n*omega;
        }
        break;
      case 3:
        l = -zeta;
        if (direct) {
          m = w;
          if (xf > 0.0) m = -m;
          n = -m*omega;
        } else {
          n = w;
          if (yf < 0.0) n = -n;
          m = -n*omega;
        }
        break;
      case 4:
        m = -zeta;
        if (direct) {
          l = w;
          if (xf < 0.0) l = -l;
          n = l*omega;
        } else {
          n = w;
          if (yf < 0.0) n = -n;
          l = n*omega;
        }
        break;
      case 5:
        n = -zeta;
        if (direct) {
          m = w;
          if (xf < 0.0) m = -m;
          l = m*omega;
        } else {
          l = w;
          if (yf < 0.0) l = -l;
          m = l*omega;
        }
        break;
      default:
        /* face == 0 */
        n = zeta;
        if (direct) {
          m = w;
          if (xf < 0.0) m = -m;
          l = -m*omega;
        } else {
          l = w;
          if (yf > 0.0) l = -l;
          m = -l*omega;
        }
        break;
      }
d7230 2
a7231 4
      if (l == 0.0 && m == 0.0) {
        *phip = 0.0;
      } else {
        *phip = atan2d(m, l);
d7233 1
d7235 1
a7235 6
      *thetap = asind(n);
      *(statp++) = 0;
    }
  }

  return status;
d7249 208
a7456 54
  int face, mphi, mtheta, rowlen, rowoff, status;
  double cosphi, costhe, eta, l, m, n, omega, p, sinphi, sinthe, t, tau, x0,
         xf, xi, y0, yf, zeco, zeta;
  const double tol = 1.0e-12;
  register int iphi, istat, itheta, *statp;
  register const double *phip, *thetap;
  register double *xp, *yp;


  /* Initialize. */
  if (prj == 0x0) return 1;
  if (prj->flag != QSC) {
    if (qscset(prj)) return 2;
  }

  if (ntheta > 0) {
    mphi   = nphi;
    mtheta = ntheta;
  } else {
    mphi   = 1;
    mtheta = 1;
    ntheta = nphi;
  }

  status = 0;


  /* Do phi dependence. */
  phip = phi;
  rowoff = 0;
  rowlen = nphi*sxy;
  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    cosphi = cosd(*phip);
    sinphi = sind(*phip);

    xp = x + rowoff;
    yp = y + rowoff;
    for (itheta = 0; itheta < mtheta; itheta++) {
      *xp = cosphi;
      *yp = sinphi;
      xp += rowlen;
      yp += rowlen;
    }
  }


  /* Do theta dependence. */
  thetap = theta;
  xp = x;
  yp = y;
  statp = stat;
  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    costhe = cosd(*thetap);
    sinthe = sind(*thetap);
d7458 3
a7460 136
    for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
      if (fabs(*thetap) == 90.0) {
        *xp = -prj->x0;
        *yp = copysign(2.0*prj->w[0], *thetap) - prj->y0;
        *(statp++) = 0;
        continue;
      }

      l = costhe*(*xp);
      m = costhe*(*yp);
      n = sinthe;

      face = 0;
      zeta = n;
      if (l > zeta) {
        face = 1;
        zeta = l;
      }
      if (m > zeta) {
        face = 2;
        zeta = m;
      }
      if (-l > zeta) {
        face = 3;
        zeta = -l;
      }
      if (-m > zeta) {
        face = 4;
        zeta = -m;
      }
      if (-n > zeta) {
        face = 5;
        zeta = -n;
      }

      zeco = 1.0 - zeta;

      switch (face) {
      case 1:
        xi  = m;
        eta = n;
        if (zeco < 1.0e-8) {
          /* Small angle formula. */
          t = (*thetap)*D2R;
          p = atan2(*yp, *xp);
          zeco = (p*p + t*t)/2.0;
        }
        x0 = 0.0;
        y0 = 0.0;
        break;
      case 2:
        xi  = -l;
        eta =  n;
        if (zeco < 1.0e-8) {
          /* Small angle formula. */
          t = (*thetap)*D2R;
          p = atan2(*yp, *xp) - PI/2.0;
          zeco = (p*p + t*t)/2.0;
        }
        x0 = 2.0;
        y0 = 0.0;
        break;
      case 3:
        xi  = -m;
        eta =  n;
        if (zeco < 1.0e-8) {
          /* Small angle formula. */
          t = (*thetap)*D2R;
          p = atan2(*yp, *xp);
          p -= copysign(PI, p);
          zeco = (p*p + t*t)/2.0;
        }
        x0 = 4.0;
        y0 = 0.0;
        break;
      case 4:
        xi  = l;
        eta = n;
        if (zeco < 1.0e-8) {
          /* Small angle formula. */
          t = (*thetap)*D2R;
          p = atan2(*yp, *xp) + PI/2.0;
          zeco = (p*p + t*t)/2.0;
        }
        x0 = 6;
        y0 = 0.0;
        break;
      case 5:
        xi  =  m;
        eta =  l;
        if (zeco < 1.0e-8) {
          /* Small angle formula. */
          t = (*thetap + 90.0)*D2R;
          zeco = t*t/2.0;
        }
        x0 =  0.0;
        y0 = -2;
         break;
      default:
        /* face == 0 */
        xi  =  m;
        eta = -l;
        if (zeco < 1.0e-8) {
          /* Small angle formula. */
          t = (90.0 - *thetap)*D2R;
          zeco = t*t/2.0;
        }
        x0 = 0.0;
        y0 = 2.0;
        break;
      }

      xf = 0.0;
      yf = 0.0;
      if (xi != 0.0 || eta != 0.0) {
        if (-xi > fabs(eta)) {
          omega = eta/xi;
          tau = 1.0 + omega*omega;
          xf  = -sqrt(zeco/(1.0 - 1.0/sqrt(1.0+tau)));
          yf  = (xf/15.0)*(atand(omega) - asind(omega/sqrt(tau+tau)));
        } else if (xi > fabs(eta)) {
          omega = eta/xi;
          tau = 1.0 + omega*omega;
          xf  =  sqrt(zeco/(1.0 - 1.0/sqrt(1.0+tau)));
          yf  = (xf/15.0)*(atand(omega) - asind(omega/sqrt(tau+tau)));
        } else if (-eta >= fabs(xi)) {
          omega = xi/eta;
          tau = 1.0 + omega*omega;
          yf  = -sqrt(zeco/(1.0 - 1.0/sqrt(1.0+tau)));
          xf  = (yf/15.0)*(atand(omega) - asind(omega/sqrt(tau+tau)));
        } else if (eta >= fabs(xi)) {
          omega = xi/eta;
          tau = 1.0 + omega*omega;
          yf  =  sqrt(zeco/(1.0 - 1.0/sqrt(1.0+tau)));
          xf  = (yf/15.0)*(atand(omega) - asind(omega/sqrt(tau+tau)));
        }
d7462 1
d7464 1
a7464 23
      istat = 0;
      if (fabs(xf) > 1.0) {
        if (fabs(xf) > 1.0+tol) {
          istat  = 1;
          status = 4;
        }
        xf = copysign(1.0, xf);
      }
      if (fabs(yf) > 1.0) {
        if (fabs(yf) > 1.0+tol) {
          istat  = 1;
          status = 4;
        }
        yf = copysign(1.0, yf);
      }

      *xp = prj->w[0]*(xf + x0) - prj->x0;
      *yp = prj->w[0]*(yf + y0) - prj->y0;
      *(statp++) = istat;
    }
  }

  return status;
d7504 1
a7504 1
  if (prj == 0x0) return 1;
d7506 2
a7507 2
  prj->flag = HPX;
  strcpy(prj->code, "HPX");
d7509 2
a7510 2
  if (undefined(prj->pv[1])) prj->pv[1] = 4.0;
  if (undefined(prj->pv[2])) prj->pv[2] = 3.0;
d7512 12
a7523 32
  strcpy(prj->name, "HEALPix");
  prj->category  = HEALPIX;
  prj->pvrange   = 102;
  prj->simplezen = 0;
  prj->equiareal = 1;
  prj->conformal = 0;
  prj->global    = 1;
  prj->divergent = 0;

  if (prj->pv[1] <= 0.0 || prj->pv[2] <= 0.0) {
    return 2;
  }

  prj->n = ((int)prj->pv[2])%2;

  if (prj->r0 == 0.0) {
    prj->r0 = R2D;
    prj->w[0] = 1.0;
    prj->w[1] = 1.0;
  } else {
    prj->w[0] = prj->r0*D2R;
    prj->w[1] = R2D/prj->r0;
  }

  prj->w[2] = (prj->pv[2] - 1.0) / prj->pv[2];
  prj->w[3] = 90.0 * prj->pv[2] / prj->pv[1];
  prj->w[4] = (prj->pv[2] + 1.0) / 2.0;
  prj->w[5] = 90.0 * (prj->pv[2] - 1.0) / prj->pv[1];
  prj->w[6] = 180.0 / prj->pv[1];
  prj->w[7] = prj->pv[1] / 360.0;
  prj->w[8] = prj->w[3] * prj->w[0];
  prj->w[9] = prj->w[6] * prj->w[0];
d7525 1
a7525 2
  prj->prjx2s = hpxx2s;
  prj->prjs2x = hpxs2x;
d7527 22
a7548 1
  return prjoff(prj, 0.0, 0.0);
d7562 74
a7635 64
  int h, mx, my, offset, rowlen, rowoff, status;
  double absy, s, sigma, t, yr;
  const double tol = 1.0e-12;
  register int istat, ix, iy, *statp;
  register const double *xp, *yp;
  register double *phip, *thetap;


  /* Initialize. */
  if (prj == 0x0) return 1;
  if (prj->flag != HPX) {
    if (hpxset(prj)) return 2;
  }

  if (ny > 0) {
    mx = nx;
    my = ny;
  } else {
    mx = 1;
    my = 1;
    ny = nx;
  }

  status = 0;


  /* Do x dependence. */
  xp = x;
  rowoff = 0;
  rowlen = nx*spt;
  for (ix = 0; ix < nx; ix++, rowoff += spt, xp += sxy) {
    s = prj->w[1] * (*xp + prj->x0);
    t = -180.0 + (2.0 * floor((*xp + 180.0) * prj->w[7]) + 1.0) * prj->w[6];
    t = prj->w[1] * (*xp - t);

    phip   = phi + rowoff;
    thetap = theta + rowoff;
    for (iy = 0; iy < my; iy++) {
      /* theta[] is used to hold (x - x_c). */
      *phip   = s;
      *thetap = t;
      phip   += rowlen;
      thetap += rowlen;
    }
  }


  /* Do y dependence. */
  yp = y;
  phip   = phi;
  thetap = theta;
  statp  = stat;
  for (iy = 0; iy < ny; iy++, yp += sxy) {
    yr = prj->w[1]*(*yp + prj->y0);
    absy = fabs(yr);

    istat = 0;
    if (absy <= prj->w[5]) {
      /* Equatorial regime. */
      t = asind(yr/prj->w[3]);
      for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
        *thetap = t;
        *(statp++) = 0;
      }
d7637 13
a7649 3
    } else if (absy <= 90.0) {
      /* Polar regime. */
      offset = (prj->n || *yp > 0.0) ? 0 : 1;
d7651 10
a7660 1
      sigma = prj->w[4] - absy / prj->w[6];
d7662 15
a7676 3
      if (sigma == 0.0) {
        s = 1e9;
        t = 90.0;
d7679 7
a7685 10
        t = 1.0 - sigma*sigma/prj->pv[2];
        if (t < -1.0) {
          s = 0.0;
          t = 0.0;
          istat  = 1;
          status = 3;
        } else {
          s = 1.0/sigma;
          t = asind(t);
        }
d7687 1
a7687 39
      if (*yp < 0.0) t = -t;

      for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
        if (offset) {
          /* Offset the southern polar half-facets for even K. */
          h = (int)floor(*phip / prj->w[6]);
          if (h%2) {
            *thetap -= prj->w[6];
          } else {
            *thetap += prj->w[6];
          }
        }

        /* Recall that theta[] holds (x - x_c). */
        s *= *thetap;
        if ((fabs(s) - prj->w[6]) < tol) {
          if (s != 0.0) s -= *thetap;
          *phip += s;
          *thetap = t;
          *(statp++) = istat;
        } else {
          /* Out-of-bounds. */
          *phip   = 0.0;
          *thetap = 0.0;
          *(statp++) = 1;
          status = 3;
        }
      }

    } else {
      /* Beyond latitude range. */
      for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
        *phip   = 0.0;
        *thetap = 0.0;
        *(statp++) = 1;
      }
      status = 3;
    }
  }
d7689 1
a7689 1
  return status;
d7703 82
a7784 64
  int h, mphi, mtheta, offset, rowlen, rowoff;
  double abssin, eta, sigma, sinthe, t, xi;
  register int iphi, itheta, *statp;
  register const double *phip, *thetap;
  register double *xp, *yp;


  /* Initialize. */
  if (prj == 0x0) return 1;
  if (prj->flag != HPX) {
    if (hpxset(prj)) return 2;
  }

  if (ntheta > 0) {
    mphi   = nphi;
    mtheta = ntheta;
  } else {
    mphi   = 1;
    mtheta = 1;
    ntheta = nphi;
  }


  /* Do phi dependence. */
  phip = phi;
  rowoff = 0;
  rowlen = nphi*sxy;
  for (iphi = 0; iphi < nphi; iphi++, rowoff += sxy, phip += spt) {
    xi = prj->w[0] * (*phip) - prj->x0;
    t  = -180.0 + (2.0*floor((*phip+180.0) * prj->w[7]) + 1.0) * prj->w[6];
    t  = prj->w[0] * (*phip - t);

    xp = x + rowoff;
    yp = y + rowoff;
    for (itheta = 0; itheta < mtheta; itheta++) {
      /* y[] is used to hold an intermediate value. */
      *xp = xi;
      *yp = t;
      xp += rowlen;
      yp += rowlen;
    }
  }


  /* Do theta dependence. */
  thetap = theta;
  xp = x;
  yp = y;
  statp = stat;
  for (itheta = 0; itheta < ntheta; itheta++, thetap += spt) {
    sinthe = sind(*thetap);
    abssin = fabs(sinthe);

    if (abssin <= prj->w[2]) {
      /* Equatorial regime. */
      eta = prj->w[8] * sinthe - prj->y0;
      for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
        *yp = eta;
        *(statp++) = 0;
      }

    } else {
      /* Polar regime. */
      offset = (prj->n || *thetap > 0.0) ? 0 : 1;
d7786 5
a7790 22
      sigma = sqrt(prj->pv[2]*(1.0 - abssin));
      xi = sigma - 1.0;

      eta = prj->w[9] * (prj->w[4] - sigma);
      if (*thetap < 0) eta = -eta;
      eta -= prj->y0;

      for (iphi = 0; iphi < mphi; iphi++, xp += sxy, yp += sxy) {
        if (offset) {
          /* Offset the southern polar half-facets for even K. */
          h = (int)floor((*xp + prj->x0) / prj->w[9]);
          if (h%2) {
            *yp -= prj->w[9];
          } else {
            *yp += prj->w[9];
          }
        }

        /* Recall that y[] holds an intermediate value. */
        *xp += *yp * xi;
        *yp = eta;
        *(statp++) = 0;
d7792 1
a7792 2
    }
  }
d7794 1
a7794 1
  return 0;
@


4.3.1.3
log
@Use sincosd() whereever possible for a 15% speedup - patches from
Michael Droettboom <mdroe@@stsci.edu>, 2009/06/09.
@
text
@d31 1
a31 1
  $Id: prj.c,v 4.3.1.2 2009/07/22 04:28:39 cal103 Exp cal103 $
d621 2
a622 1
    sincosd(*phip, &sinphi, &cosphi);
d641 2
a642 1
    sincosd(*thetap, &sinthe, &costhe);
d950 2
a951 1
    sincosd(*phip, &sinphi, &cosphi);
d1190 2
a1191 1
    sincosd(*phip, &sinphi, &cosphi);
d1409 2
a1410 1
    sincosd(*phip, &sinphi, &cosphi);
d1710 2
a1711 1
    sincosd(*phip, &sinphi, &cosphi);
d1953 2
a1954 1
    sincosd(*phip, &sinphi, &cosphi);
d2327 2
a2328 1
    sincosd(*phip, &sinphi, &cosphi);
d2555 2
a2556 1
    sincosd(*phip, &sinphi, &cosphi);
d2842 2
a2843 1
    sincosd(*phip, &sinphi, &cosphi);
d4621 2
a4622 1
    sincosd(w, &sinphi, &cosphi);
d4641 2
a4642 1
    sincosd(*thetap, &sinthe, &costhe);
d4850 2
a4851 1
    sincosd(alpha, &sinalpha, &cosalpha);
d5122 2
a5123 1
    sincosd(alpha, &sinalpha, &cosalpha);
d5347 2
a5348 1
    sincosd(alpha, &sinalpha, &cosalpha);
d5602 2
a5603 1
    sincosd(alpha, &sinalpha, &cosalpha);
d5814 1
a5814 1
  double alpha, cosalpha, r, s, sinalpha, y0;
d5868 2
a5869 3
      sincosd(alpha, &sinalpha, &cosalpha);
      *xp =  r*sinalpha - prj->x0;
      *yp = -r*cosalpha - y0;
d6123 2
a6124 1
    sincosd(*thetap, &sinthe, &costhe);
d6374 2
a6375 1
    sincosd(*phip, &sinphi, &cosphi);
d6394 2
a6395 1
    sincosd(*thetap, &sinthe, &costhe);
d6808 2
a6809 1
    sincosd(*phip, &sinphi, &cosphi);
d6828 2
a6829 1
    sincosd(*thetap, &sinthe, &costhe);
d7010 1
a7010 1
  double cosw, l, m, n, omega, sinw, tau, xf, yf, w, zeco, zeta;
d7125 1
a7125 2
          sincosd(w, &sinw, &cosw);
          omega = sinw/(cosw - SQRT2INV);
d7281 2
a7282 1
    sincosd(*phip, &sinphi, &cosphi);
d7301 2
a7302 1
    sincosd(*thetap, &sinthe, &costhe);
@


4.3.1.4
log
@Fixed a subtle and important bug in prjoff() - prj->x0 and prj->y0 must
not be specified as arguments to prjs2x() since they are used in the
computation, yet may be used as temporary storage by prjs2x().  Also,
prj->x0 and prj->y0 must be initialized to zero before invoking prjs2x().
@
text
@d31 1
a31 1
  $Id: prj.c,v 4.3.1.3 2009/07/27 06:05:48 cal103 Exp cal103 $
a368 1
  double x0, y0;
a371 3
  prj->x0 = 0.0;
  prj->y0 = 0.0;

d377 3
d381 2
a382 2
    if (prj->prjs2x(prj, 1, 1, 1, 1, &(prj->phi0), &(prj->theta0), &x0, &y0,
                    &stat)) {
a384 3

    prj->x0 = x0;
    prj->y0 = y0;
@


4.3.1.5
log
@In prjini(), null-fill prjprm::name and set prjprm::padding to zero for
tidiness when the struct is examined in the debugger.
@
text
@d31 1
a31 1
  $Id: prj.c,v 4.3.1.4 2009/07/28 07:34:19 cal103 Exp cal103 $
a146 1
  for (k = 9; k < 40; prj->name[k++] = '\0');
a157 1
  prj->padding = 0;
@


4.2
log
@WCSLIB 4.2
@
text
@d2 30
a31 29
*
*   WCSLIB 4.2 - an implementation of the FITS WCS standard.
*   Copyright (C) 1995-2005, Mark Calabretta
*
*   WCSLIB 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 of the License, or (at your option)
*   any later version.
*
*   WCSLIB 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 WCSLIB; if not, write to the Free Software Foundation, Inc.,
*   59 Temple Place, Suite 330, Boston, MA  02111-1307, USA
*
*   Correspondence concerning WCSLIB may be directed to:
*      Internet email: mcalabre@@atnf.csiro.au
*      Postal address: Dr. Mark Calabretta
*                      Australia Telescope National Facility, CSIRO
*                      PO Box 76
*                      Epping NSW 1710
*                      AUSTRALIA
*
*   Author: Mark Calabretta, Australia Telescope National Facility
*   http://www.atnf.csiro.au/~mcalabre/index.html
*   $Id: prj.c,v 4.1 2005/08/25 07:48:36 cal103 Exp cal103 $
a101 2
int prj_stat;

d146 1
a146 1
   strcpy(prj->name, "Undefined");
a158 2
   prj->p = prj->pv;

d236 2
a237 3
   printf("     prjx2s: 0x%x\n", (int)prj->prjx2s);
   printf("     prjs2x: 0x%x\n", (int)prj->prjs2x);
   printf("          p: 0x%x  (= pv)\n", (int)prj->p);
d249 2
d256 1
a256 1
      azpset(prj);
d258 1
a258 1
      szpset(prj);
d260 1
a260 1
      tanset(prj);
d262 1
a262 1
      stgset(prj);
d264 1
a264 1
      sinset(prj);
d266 1
a266 1
      arcset(prj);
d268 1
a268 1
      zpnset(prj);
d270 1
a270 1
      zeaset(prj);
d272 1
a272 1
      airset(prj);
d274 1
a274 1
      cypset(prj);
d276 1
a276 1
      ceaset(prj);
d278 1
a278 1
      carset(prj);
d280 1
a280 1
      merset(prj);
d282 1
a282 1
      sflset(prj);
d284 1
a284 1
      parset(prj);
d286 1
a286 1
      molset(prj);
d288 1
a288 1
      aitset(prj);
d290 1
a290 1
      copset(prj);
d292 1
a292 1
      coeset(prj);
d294 1
a294 1
      codset(prj);
d296 1
a296 1
      cooset(prj);
d298 1
a298 1
      bonset(prj);
d300 1
a300 1
      pcoset(prj);
d302 1
a302 1
      tscset(prj);
d304 1
a304 1
      cscset(prj);
d306 1
a306 1
      qscset(prj);
d308 1
a308 1
      hpxset(prj);
d311 1
a311 1
      return 2;
d314 1
a314 1
   return 0;
d433 1
a433 1
   strcpy(prj->name, "Zenithal/azimuthal perspective");
d745 1
a745 1
   strcpy(prj->name, "Slant zenithal perspective");
d1058 1
a1058 1
   strcpy(prj->name, "Gnomonic");
d1268 1
a1268 1
   strcpy(prj->name, "Stereographic");
d1490 1
a1490 1
   strcpy(prj->name, "Orthographic/synthesis");
d1813 1
a1813 1
   strcpy(prj->name, "Zenithal/azimuthal equidistant");
d2027 1
a2027 1
   strcpy(prj->name, "Zenithal/azimuthal polynomial");
d2400 1
a2400 1
   strcpy(prj->name, "Zenithal/azimuthal equal area");
d2931 1
a2931 1
   strcpy(prj->name, "Cylindrical perspective");
d3158 1
a3158 1
   strcpy(prj->name, "Cylindrical equal area");
d3367 1
a3367 1
   strcpy(prj->name, "Plate caree");
d3447 1
a3447 1
      for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
d3630 1
a3630 1
      for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
d3944 1
a3944 1
   strcpy(prj->name, "Parabolic");
d4699 1
a4699 1
   strcpy(prj->name, "Conic perspective");
d4948 1
a4948 1
   strcpy(prj->name, "Conic equal area");
d5201 1
a5201 1
   strcpy(prj->name, "Conic equidistant");
d5427 1
a5427 1
   strcpy(prj->name, "Conic orthomorphic");
d5908 1
a5908 1
   strcpy(prj->name, "Polyconic");
d6174 1
a6174 1
   strcpy(prj->name, "Tangential spherical cube");
d6974 1
a6974 1
   strcpy(prj->name, "Quadrilateralized spherical cube");
d7564 1
d7600 1
d7620 1
d7622 1
a7622 1
         for (ix = 0; ix < mx; ix++, thetap += spt) {
d7627 2
a7628 1
      } else {
d7634 1
a7634 1
            s = 0.0;
d7645 1
a7645 1
               s = 1.0/sigma - 1.0;
d7661 23
a7683 3
            *phip += *thetap * s;
            *thetap = t;
            *(statp++) = istat;
d7685 1
d7738 1
d7757 1
d7765 1
d7785 2
@


4.2.1.1
log
@WCSLIB 4.2 development branch.
@
text
@d3 1
a3 1
*   WCSLIB 4.3 - an implementation of the FITS WCS standard.
d30 1
a30 1
*   $Id: prj.c,v 4.2 2005/09/21 13:21:57 cal103 Exp cal103 $
@


4.2.1.2
log
@In prjprt(), use the "%p" printf conversion specifier to print addresses
rather than casting the pointer to int and using "%x".  The latter does not
work on 64-bit machines where sizeof(int) != sizeof(void*).
@
text
@d4 1
a4 1
*   Copyright (C) 1995-2006, Mark Calabretta
d30 1
a30 1
*   $Id: prj.c,v 4.2.1.1 2005/12/05 02:39:43 cal103 Exp cal103 $
d239 3
a241 3
   printf("     prjx2s: %p\n", prj->prjx2s);
   printf("     prjs2x: %p\n", prj->prjs2x);
   printf("          p: %p  (= pv)\n", prj->p);
@


4.2.1.3
log
@Bug fix in hpxx2s - in computing the y-dependence, phip was not incremented
in the loop for the equatorial regime where phi is not modified, but it was
subsequently misdirected in the polar case where it is; also added bounds
checking.  Minor efficiencies in carx2s and merx2s.
@
text
@d4 1
a4 1
*   Copyright (C) 1995-2007, Mark Calabretta
d30 1
a30 1
*   $Id: prj.c,v 4.2.1.2 2006/06/01 07:34:15 cal103 Exp cal103 $
d3449 1
a3449 1
      for (ix = 0; ix < mx; ix++, thetap += spt) {
d3632 1
a3632 1
      for (ix = 0; ix < mx; ix++, thetap += spt) {
a7600 1
         /* theta[] is used to hold (x - x_c). */
a7619 1
         /* Equatorial regime. */
d7621 1
a7621 1
         for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
d7626 1
a7626 2
      } else if (absy <= 90.0) {
         /* Polar regime. */
d7632 1
a7632 1
            s = 1e9;
d7643 1
a7643 1
               s = 1.0/sigma;
d7659 3
a7661 23

            /* Recall that theta[] holds (x - x_c). */
            s *= *thetap;
            if (fabs(s) <= prj->w[6]) {
               if (s != 0.0) s -= *thetap;
               *phip += s;
               *thetap = t;
               *(statp++) = istat;
            } else {
               /* Out-of-bounds. */
               *phip   = 0.0;
               *thetap = 0.0;
               *(statp++) = 1;
               status = 3;
            }
         }

      } else {
         /* Beyond latitude range. */
         for (ix = 0; ix < mx; ix++, phip += spt, thetap += spt) {
            *phip   = 0.0;
            *thetap = 0.0;
            *(statp++) = 1;
a7662 1
         status = 3;
a7714 1
         /* y[] is used to hold an intermediate value. */
a7732 1
         /* Equatorial regime. */
a7739 1
         /* Polar regime. */
a7758 2

            /* Recall that y[] holds an intermediate value. */
@


4.2.1.4
log
@Cast pointers to (void *) for %p formatting by printf() to avert a compiler
warning.
@
text
@d30 1
a30 1
*   $Id: prj.c,v 4.2.1.3 2007/06/29 01:45:55 cal103 Exp cal103 $
d239 3
a241 3
   printf("     prjx2s: %p\n", (void *)prj->prjx2s);
   printf("     prjs2x: %p\n", (void *)prj->prjs2x);
   printf("          p: %p  (= pv)\n", (void *)prj->p);
@


4.2.1.5
log
@prjset() must propagate the status value returned by the specific projection-
setting functions (Bill Pence email 2007/07/27).
@
text
@d30 1
a30 1
*   $Id: prj.c,v 4.2.1.4 2007/07/11 02:01:30 cal103 Exp cal103 $
a252 2
   int status;

d258 1
a258 1
      status = azpset(prj);
d260 1
a260 1
      status = szpset(prj);
d262 1
a262 1
      status = tanset(prj);
d264 1
a264 1
      status = stgset(prj);
d266 1
a266 1
      status = sinset(prj);
d268 1
a268 1
      status = arcset(prj);
d270 1
a270 1
      status = zpnset(prj);
d272 1
a272 1
      status = zeaset(prj);
d274 1
a274 1
      status = airset(prj);
d276 1
a276 1
      status = cypset(prj);
d278 1
a278 1
      status = ceaset(prj);
d280 1
a280 1
      status = carset(prj);
d282 1
a282 1
      status = merset(prj);
d284 1
a284 1
      status = sflset(prj);
d286 1
a286 1
      status = parset(prj);
d288 1
a288 1
      status = molset(prj);
d290 1
a290 1
      status = aitset(prj);
d292 1
a292 1
      status = copset(prj);
d294 1
a294 1
      status = coeset(prj);
d296 1
a296 1
      status = codset(prj);
d298 1
a298 1
      status = cooset(prj);
d300 1
a300 1
      status = bonset(prj);
d302 1
a302 1
      status = pcoset(prj);
d304 1
a304 1
      status = tscset(prj);
d306 1
a306 1
      status = cscset(prj);
d308 1
a308 1
      status = qscset(prj);
d310 1
a310 1
      status = hpxset(prj);
d313 1
a313 1
      status = 2;
d316 1
a316 1
   return status;
@


4.2.1.6
log
@Down-cased the first character of projection names that are not named for a
person - it is easier to capitalise them if required.
@
text
@d30 1
a30 1
*   $Id: prj.c,v 4.2.1.5 2007/07/27 00:44:21 cal103 Exp cal103 $
d147 1
a147 1
   strcpy(prj->name, "undefined");
d437 1
a437 1
   strcpy(prj->name, "zenithal/azimuthal perspective");
d749 1
a749 1
   strcpy(prj->name, "slant zenithal perspective");
d1062 1
a1062 1
   strcpy(prj->name, "gnomonic");
d1272 1
a1272 1
   strcpy(prj->name, "stereographic");
d1494 1
a1494 1
   strcpy(prj->name, "orthographic/synthesis");
d1817 1
a1817 1
   strcpy(prj->name, "zenithal/azimuthal equidistant");
d2031 1
a2031 1
   strcpy(prj->name, "zenithal/azimuthal polynomial");
d2404 1
a2404 1
   strcpy(prj->name, "zenithal/azimuthal equal area");
d2935 1
a2935 1
   strcpy(prj->name, "cylindrical perspective");
d3162 1
a3162 1
   strcpy(prj->name, "cylindrical equal area");
d3371 1
a3371 1
   strcpy(prj->name, "plate caree");
d3948 1
a3948 1
   strcpy(prj->name, "parabolic");
d4703 1
a4703 1
   strcpy(prj->name, "conic perspective");
d4952 1
a4952 1
   strcpy(prj->name, "conic equal area");
d5205 1
a5205 1
   strcpy(prj->name, "conic equidistant");
d5431 1
a5431 1
   strcpy(prj->name, "conic orthomorphic");
d5912 1
a5912 1
   strcpy(prj->name, "polyconic");
d6178 1
a6178 1
   strcpy(prj->name, "tangential spherical cube");
d6978 1
a6978 1
   strcpy(prj->name, "quadrilateralized spherical cube");
@


4.2.1.7
log
@Removed WCSLIB 2.x backwards-compatibility measures.
@
text
@d30 1
a30 1
*   $Id: prj.c,v 4.2.1.6 2007/07/27 05:50:38 cal103 Exp cal103 $
d101 2
d160 2
@


4.2.1.8
log
@Switched to LGPL 3.0.
@
text
@d2 29
a30 30

    WCSLIB 4.3 - an implementation of the FITS WCS standard.
    Copyright (C) 1995-2007, Mark Calabretta

    This file is part of WCSLIB.

    WCSLIB is free software: you can redistribute it and/or modify it under
    the terms of the GNU Lesser General Public License as published by the
    Free Software Foundation, either version 3 of the License, or (at your
    option) any later version.

    WCSLIB 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 Lesser General Public License for
    more details.

    You should have received a copy of the GNU Lesser General Public License
    along with WCSLIB.  If not, see <http://www.gnu.org/licenses/>.

    Correspondence concerning WCSLIB may be directed to:
       Internet email: mcalabre@@atnf.csiro.au
       Postal address: Dr. Mark Calabretta
                       Australia Telescope National Facility, CSIRO
                       PO Box 76
                       Epping NSW 1710
                       AUSTRALIA

    Author: Mark Calabretta, Australia Telescope National Facility
    http://www.atnf.csiro.au/~mcalabre/index.html
    $Id: prj.c,v 4.2.1.7 2007/08/08 07:20:03 cal103 Exp cal103 $
d237 1
@


4.2.1.9
log
@Fixed a floating point rounding problem in hpxx2s() introduced by bounds
checking.
@
text
@d31 1
a31 1
    $Id: prj.c,v 4.2.1.8 2007/12/03 05:02:17 cal103 Exp cal103 $
a7563 1
   const double tol = 1.0e-12;
d7663 1
a7663 1
            if ((fabs(s) - prj->w[6]) < tol) {
@


4.1
log
@WCSLIB 4.1: set prj_errmsg[0] to "success"; report parameters and
intermediate variables to an extra decimal place in prjprt().
@
text
@d3 1
a3 1
*   WCSLIB 4.1 - an implementation of the FITS WCS standard.
d30 1
a30 1
*   $Id: prj.c,v 4.0 2005/02/04 05:10:22 cal103 Exp cal103 $
@


4.0
log
@WCSLIB 4.0: changed from LGPL to GPL; added the HPX projection; macros for
UNDEFINED values moved to wcsmath.h; changed variable names in aitx2s() to
match Paper II.
@
text
@d3 1
a3 1
*   WCSLIB 4.0 - an implementation of the FITS WCS standard.
d30 1
a30 1
*   $Id: prj.c,v 3.6 2004/08/25 04:07:22 cal103 Exp cal103 $
d95 1
a95 1
   0,
d132 1
a132 1
   if (prj == 0) return 1;
d174 1
a174 1
   if (prj == 0) return 1;
d186 1
a186 1
         printf(" %- 11.4g", prj->pv[0]);
d198 1
a198 1
            printf("  %- 11.4g", prj->pv[i]);
d231 1
a231 1
      printf("  %- 11.4g", prj->w[i]);
d235 1
a235 1
      printf("  %- 11.4g", prj->w[i]);
d253 1
a253 1
   if (prj == 0) return 1;
d331 1
a331 1
   if (prj == 0) return 1;
d351 1
a351 1
   if (prj == 0) return 1;
d372 1
a372 1
   if (prj == 0) return 1;
d426 1
a426 1
   if (prj == 0) return 1;
d493 1
a493 1
   if (prj == 0) return 1;
d601 1
a601 1
   if (prj == 0) return 1;
d737 1
a737 1
   if (prj == 0) return 1;
d802 1
a802 1
   if (prj == 0) return 1;
d930 1
a930 1
   if (prj == 0) return 1;
d1053 1
a1053 1
   if (prj == 0) return 1;
d1094 1
a1094 1
   if (prj == 0) return 1;
d1170 1
a1170 1
   if (prj == 0) return 1;
d1265 1
a1265 1
   if (prj == 0) return 1;
d1313 1
a1313 1
   if (prj == 0) return 1;
d1389 1
a1389 1
   if (prj == 0) return 1;
d1483 1
a1483 1
   if (prj == 0) return 1;
d1533 1
a1533 1
   if (prj == 0) return 1;
d1690 1
a1690 1
   if (prj == 0) return 1;
d1810 1
a1810 1
   if (prj == 0) return 1;
d1858 1
a1858 1
   if (prj == 0) return 1;
d1935 1
a1935 1
   if (prj == 0) return 1;
d2019 1
a2019 1
   if (prj == 0) return 1;
d2129 1
a2129 1
   if (prj == 0) return 1;
d2307 1
a2307 1
   if (prj == 0) return 1;
d2397 1
a2397 1
   if (prj == 0) return 1;
d2446 1
a2446 1
   if (prj == 0) return 1;
d2537 1
a2537 1
   if (prj == 0) return 1;
d2626 1
a2626 1
   if (prj == 0) return 1;
d2686 1
a2686 1
   if (prj == 0) return 1;
d2822 1
a2822 1
   if (prj == 0) return 1;
d2925 1
a2925 1
   if (prj == 0) return 1;
d2999 1
a2999 1
   if (prj == 0) return 1;
d3065 1
a3065 1
   if (prj == 0) return 1;
d3153 1
a3153 1
   if (prj == 0) return 1;
d3214 1
a3214 1
   if (prj == 0) return 1;
d3294 1
a3294 1
   if (prj == 0) return 1;
d3364 1
a3364 1
   if (prj == 0) return 1;
d3412 1
a3412 1
   if (prj == 0) return 1;
d3477 1
a3477 1
   if (prj == 0) return 1;
d3547 1
a3547 1
   if (prj == 0) return 1;
d3595 1
a3595 1
   if (prj == 0) return 1;
d3660 1
a3660 1
   if (prj == 0) return 1;
d3740 1
a3740 1
   if (prj == 0) return 1;
d3788 1
a3788 1
   if (prj == 0) return 1;
d3866 1
a3866 1
   if (prj == 0) return 1;
d3941 1
a3941 1
   if (prj == 0) return 1;
d3994 1
a3994 1
   if (prj == 0) return 1;
d4095 1
a4095 1
   if (prj == 0) return 1;
d4171 1
a4171 1
   if (prj == 0) return 1;
d4219 1
a4219 1
   if (prj == 0) return 1;
d4347 1
a4347 1
   if (prj == 0) return 1;
d4448 1
a4448 1
   if (prj == 0) return 1;
d4495 1
a4495 1
   if (prj == 0) return 1;
d4602 1
a4602 1
   if (prj == 0) return 1;
d4690 1
a4690 1
   if (prj == 0) return 1;
d4751 1
a4751 1
   if (prj == 0) return 1;
d4829 1
a4829 1
   if (prj == 0) return 1;
d4939 1
a4939 1
   if (prj == 0) return 1;
d5003 1
a5003 1
   if (prj == 0) return 1;
d5103 1
a5103 1
   if (prj == 0) return 1;
d5192 1
a5192 1
   if (prj == 0) return 1;
d5250 1
a5250 1
   if (prj == 0) return 1;
d5328 1
a5328 1
   if (prj == 0) return 1;
d5418 1
a5418 1
   if (prj == 0) return 1;
d5488 1
a5488 1
   if (prj == 0) return 1;
d5581 1
a5581 1
   if (prj == 0) return 1;
d5674 1
a5674 1
   if (prj == 0) return 1;
d5732 1
a5732 1
   if (prj == 0) return 1;
d5823 1
a5823 1
   if (prj == 0) return 1;
d5905 1
a5905 1
   if (prj == 0) return 1;
d5957 1
a5957 1
   if (prj == 0) return 1;
d6091 1
a6091 1
   if (prj == 0) return 1;
d6171 1
a6171 1
   if (prj == 0) return 1;
d6219 1
a6219 1
   if (prj == 0) return 1;
d6355 1
a6355 1
   if (prj == 0) return 1;
d6517 1
a6517 1
   if (prj == 0) return 1;
d6594 1
a6594 1
   if (prj == 0) return 1;
d6788 1
a6788 1
   if (prj == 0) return 1;
d6971 1
a6971 1
   if (prj == 0) return 1;
d7020 1
a7020 1
   if (prj == 0) return 1;
d7261 1
a7261 1
   if (prj == 0) return 1;
d7506 1
a7506 1
   if (prj == 0) return 1;
d7572 1
a7572 1
   if (prj == 0) return 1;
d7688 1
a7688 1
   if (prj == 0) return 1;
@


3.6
log
@WCSLIB 3.6: "error status/code/number" is now referred to consistently as the
"status return value".
@
text
@d3 2
a4 2
*   WCSLIB 3.6 - an implementation of the FITS WCS convention.
*   Copyright (C) 1995-2004, Mark Calabretta
d6 13
a18 13
*   This library is free software; you can redistribute it and/or modify it
*   under the terms of the GNU Library General Public License as published
*   by the Free Software Foundation; either version 2 of the License, or (at
*   your option) any later version.
*
*   This library 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 Library
*   General Public License for more details.
*
*   You should have received a copy of the GNU Library General Public License
*   along with this library; if not, write to the Free Software Foundation,
*   Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
d30 1
a30 1
*   $Id: prj.c,v 3.5 2004/06/28 02:06:59 mcalabre Exp mcalabre $
d50 1
d52 1
a52 1
const char prj_categories[8][32] =
d54 1
a54 1
       "conventional", "conic", "polyconic", "quadcube"};
d58 2
a59 2
const int  prj_ncode = 26;
const char prj_codes[26][4] =
d62 1
a62 1
       "AIT", "BON", "PCO", "TSC", "CSC", "QSC"};
d90 1
a105 3
#define UNDEFINED 987654321.0e99
#define undefined(value) (value == UNDEFINED)

d309 2
d4487 1
a4487 1
   double s, t, u, x0, xj, y0, yj, yj2;
d4542 1
a4542 1
         u = *phip - yj2;
d4545 2
a4546 2
         if (u < 0.5) {
            if (u < 0.5-tol) {
d4551 1
a4551 1
            u = 0.5;
d4554 3
a4556 3
         s = sqrt(u);
         x0 = 2.0*s*s - 1.0;
         y0 = s*(*thetap);
d4563 1
a4563 1
         t = s*yj/prj->r0;
d7467 300
@


3.5
log
@WCSLIB 3.5: minor tidy up of output formatting in prjprt(); changed the name
of helper routine offset() to prjoff() to reduce the likelihood of global
namespace conflicts; in zpnset(), set prj.w[0] for polynomials of degree
N < 3 (zpns2x() uses this for bounds checking); modified bonset() to
recognize the equatorial case of Bonne's projection as Sanson-Flamsteed;
changed some variable names in tscs2x(), cscx2s(), cscs2x(), qscx2s(), and
qscs2x() to match Paper II, and likewise changed some inequality tests in
qscs2x() without changing the results.
@
text
@d3 1
a3 1
*   WCSLIB 3.5 - an implementation of the FITS WCS convention.
d30 1
a30 1
*   $Id: prj.c,v 3.4 2004/02/11 00:15:03 mcalabre Exp mcalabre $
d91 1
a91 1
/* Map error number to error message for each function. */
@


3.4
log
@WCSLIB 3.4: in aitx2s(), apply the boundary condition 0.5 <= Z^2 <= 1 given
after Eq. (109) in WCS Paper II to detect outlying pixels.
@
text
@d3 1
a3 1
*   WCSLIB 3.4 - an implementation of the FITS WCS convention.
d29 2
a30 1
*   $Id: prj.c,v 3.3 2003/10/21 08:52:49 mcalabre Exp mcalabre $
d113 2
d173 1
a173 1
   int i, j;
d182 7
a188 2
      for (j = 0; j < prj->pvrange/100; j++) {
         printf("   (0)        ");
d190 7
a196 2
      for (i = 0; i < (prj->pvrange)%100; i++, j++) {
         if (undefined(prj->pv[prj->pvrange/100 + i])) {
d199 1
a199 1
            printf("  %- 11.4g", prj->pv[prj->pvrange/100 + i]);
a200 3
         if (j && j%5 == 0) {
            printf("\n            ");
         }
d359 1
a359 1
* Internal helper routine used by the *set() routines which forces
d363 1
a363 1
int offset(prj, phi0, theta0)
d469 1
a469 1
   return offset(prj, 0.0, 90.0);
d778 1
a778 1
   return offset(prj, 0.0, 90.0);
d1071 1
a1071 1
   return offset(prj, 0.0, 90.0);
d1290 1
a1290 1
   return offset(prj, 0.0, 90.0);
d1508 1
a1508 1
   return offset(prj, 0.0, 90.0);
d1835 1
a1835 1
   return offset(prj, 0.0, 90.0);
d2003 2
a2004 2
*      prj->w[0]    Co-latitude of the first point of inflection (N > 2).
*      prj->w[1]    Radius of the first point of inflection (N > 2).
d2043 5
a2047 1
   if (k >= 3) {
d2105 1
a2105 1
   return offset(prj, 0.0, 90.0);
d2422 1
a2422 1
   return offset(prj, 0.0, 90.0);
d2662 1
a2662 1
   return offset(prj, 0.0, 90.0);
d2976 1
a2976 1
   return offset(prj, 0.0, 0.0);
d3190 1
a3190 1
   return offset(prj, 0.0, 0.0);
d3389 1
a3389 1
   return offset(prj, 0.0, 0.0);
d3572 1
a3572 1
   return offset(prj, 0.0, 0.0);
d3765 1
a3765 1
   return offset(prj, 0.0, 0.0);
d3970 1
a3970 1
   return offset(prj, 0.0, 0.0);
d4195 1
a4195 1
   return offset(prj, 0.0, 0.0);
d4471 1
a4471 1
   return offset(prj, 0.0, 0.0);
d4729 1
a4729 1
   return offset(prj, 0.0, prj->pv[1]);
d4980 1
a4980 1
   return offset(prj, 0.0, prj->pv[1]);
d5228 1
a5228 1
   return offset(prj, 0.0, prj->pv[1]);
d5466 1
a5466 1
   return offset(prj, 0.0, prj->pv[1]);
d5682 5
d5709 1
a5709 1
   return offset(prj, 0.0, 0.0);
d5932 1
a5932 1
   return offset(prj, 0.0, 0.0);
d6196 1
a6196 1
   return offset(prj, 0.0, 0.0);
d6347 1
a6347 2
   double cosphi, costhe, l, m, n, rho, sinphi, sinthe, x0, xf,
          y0, yf;
d6405 2
a6406 2
         rho  = n;
         if (l > rho) {
d6408 1
a6408 1
            rho  = l;
d6410 1
a6410 1
         if (m > rho) {
d6412 1
a6412 1
            rho  = m;
d6414 1
a6414 1
         if (-l > rho) {
d6416 1
a6416 1
            rho  = -l;
d6418 1
a6418 1
         if (-m > rho) {
d6420 1
a6420 1
            rho  = -m;
d6422 1
a6422 1
         if (-n > rho) {
d6424 1
a6424 1
            rho  = -n;
d6429 2
a6430 2
            xf =  m/rho;
            yf =  n/rho;
d6435 2
a6436 2
            xf = -l/rho;
            yf =  n/rho;
d6441 2
a6442 2
            xf = -m/rho;
            yf =  n/rho;
d6447 2
a6448 2
            xf =  l/rho;
            yf =  n/rho;
d6453 2
a6454 2
            xf =  m/rho;
            yf =  l/rho;
d6460 2
a6461 2
            xf =  m/rho;
            yf = -l/rho;
d6542 1
a6542 1
   return offset(prj, 0.0, 0.0);
d6562 1
a6562 1
   float     a, b, xf, xx, yf, yy, z0, z1, z2, z3, z4, z5, z6;
d6690 2
a6691 2
         a = z0 + yy*(z1 + yy*(z2 + yy*(z3 + yy*(z4 + yy*(z5 + yy*z6)))));
         a = xf + xf*(1.0 - xx)*a;
d6702 2
a6703 2
         b = z0 + xx*(z1 + xx*(z2 + xx*(z3 + xx*(z4 + xx*(z5 + xx*z6)))));
         b = yf + yf*(1.0 - yy)*b;
d6707 3
a6709 3
            l =  1.0/sqrt(a*a + b*b + 1.0);
            m =  a*l;
            n =  b*l;
d6712 3
a6714 3
            m =  1.0/sqrt(a*a + b*b + 1.0);
            l = -a*m;
            n =  b*m;
d6717 3
a6719 3
            l = -1.0/sqrt(a*a + b*b + 1.0);
            m =  a*l;
            n = -b*l;
d6722 3
a6724 3
            m = -1.0/sqrt(a*a + b*b + 1.0);
            l = -a*m;
            n = -b*m;
d6727 3
a6729 3
            n = -1.0/sqrt(a*a + b*b + 1.0);
            l = -b*n;
            m = -a*n;
d6733 3
a6735 3
            n =  1.0/sqrt(a*a + b*b + 1.0);
            l = -b*n;
            m =  a*n;
d6765 1
a6765 1
   double cosphi, costhe, eta, l, m, n, rho, sinphi, sinthe, xi;
d6771 1
a6771 1
   float a, a2, a2b2, a4, ab, b, b2, b4, ca2, cb2, x0, xf, y0, yf;
d6838 2
a6839 2
         rho  = n;
         if (l > rho) {
d6841 1
a6841 1
            rho  = l;
d6843 1
a6843 1
         if (m > rho) {
d6845 1
a6845 1
            rho  = m;
d6847 1
a6847 1
         if (-l > rho) {
d6849 1
a6849 1
            rho  = -l;
d6851 1
a6851 1
         if (-m > rho) {
d6853 1
a6853 1
            rho  = -m;
d6855 1
a6855 1
         if (-n > rho) {
d6857 1
a6857 1
            rho  = -n;
d6900 2
a6901 2
         a =  xi/rho;
         b = eta/rho;
d6903 4
a6906 4
         a2 = a*a;
         b2 = b*b;
         ca2 = 1.0 - a2;
         cb2 = 1.0 - b2;
d6909 11
a6919 11
         ab   = fabs(a*b);
         a4   = (a2 > 1.0e-16) ? a2*a2 : 0.0;
         b4   = (b2 > 1.0e-16) ? b2*b2 : 0.0;
         a2b2 = (ab > 1.0e-16) ? a2*b2 : 0.0;

         xf = a*(a2 + ca2*(gstar + b2*(gamma*ca2 + mm*a2 +
                cb2*(c00 + c10*a2 + c01*b2 + c11*a2b2 + c20*a4 + c02*b4)) +
                a2*(omega1 - ca2*(d0 + d1*a2))));
         yf = b*(b2 + cb2*(gstar + a2*(gamma*cb2 + mm*b2 +
                ca2*(c00 + c10*b2 + c01*a2 + c11*a2b2 + c20*b4 + c02*a4)) +
                b2*(omega1 - cb2*(d0 + d1*b2))));
d6996 1
a6996 1
   return offset(prj, 0.0, 0.0);
d7011 1
a7011 1
   double l, m, n, omega, rho, rhu, tau, xf, yf, w;
d7108 3
a7110 3
               tau = 1.0;
               rho = 1.0;
               rhu = 0.0;
d7114 3
a7116 3
               tau = 1.0 + omega*omega;
               rhu = xf*xf*(1.0 - 1.0/sqrt(1.0 + tau));
               rho = 1.0 - rhu;
d7121 3
a7123 3
               tau = 1.0;
               rho = 1.0;
               rhu = 0.0;
d7127 3
a7129 3
               tau = 1.0 + omega*omega;
               rhu = yf*yf*(1.0 - 1.0/sqrt(1.0 + tau));
               rho = 1.0 - rhu;
d7133 2
a7134 2
         if (rho < -1.0) {
            if (rho < -1.0-tol) {
d7142 3
a7144 3
            rho = -1.0;
            rhu =  2.0;
            w   =  0.0;
d7146 1
a7146 1
            w = sqrt(rhu*(2.0-rhu)/tau);
d7151 1
a7151 1
            l = rho;
d7163 1
a7163 1
            m = rho;
d7175 1
a7175 1
            l = -rho;
d7187 1
a7187 1
            m = -rho;
d7199 1
a7199 1
            n = -rho;
d7212 1
a7212 1
            n = rho;
d7251 2
a7252 2
   double cosphi, costhe, eta, l, m, n, omega, p, rho, rhu, sinphi,
          sinthe, t, tau, x0, xf, xi, y0, yf;
d7318 2
a7319 2
         rho  = n;
         if (l > rho) {
d7321 1
a7321 1
            rho  = l;
d7323 1
a7323 1
         if (m > rho) {
d7325 1
a7325 1
            rho  = m;
d7327 1
a7327 1
         if (-l > rho) {
d7329 1
a7329 1
            rho  = -l;
d7331 1
a7331 1
         if (-m > rho) {
d7333 1
a7333 1
            rho  = -m;
d7335 1
a7335 1
         if (-n > rho) {
d7337 1
a7337 1
            rho  = -n;
d7340 1
a7340 1
         rhu = 1.0 - rho;
d7346 1
a7346 1
            if (rhu < 1.0e-8) {
d7350 1
a7350 1
               rhu = (p*p + t*t)/2.0;
d7358 1
a7358 1
            if (rhu < 1.0e-8) {
d7362 1
a7362 1
               rhu = (p*p + t*t)/2.0;
d7370 1
a7370 1
            if (rhu < 1.0e-8) {
d7375 1
a7375 1
               rhu = (p*p + t*t)/2.0;
d7383 1
a7383 1
            if (rhu < 1.0e-8) {
d7387 1
a7387 1
               rhu = (p*p + t*t)/2.0;
d7395 1
a7395 1
            if (rhu < 1.0e-8) {
d7398 1
a7398 1
               rhu = t*t/2.0;
d7407 1
a7407 1
            if (rhu < 1.0e-8) {
d7410 1
a7410 1
               rhu = t*t/2.0;
d7420 1
a7420 1
            if (-xi >= fabs(eta)) {
d7423 1
a7423 1
               xf  = -sqrt(rhu/(1.0-1.0/sqrt(1.0+tau)));
d7425 1
a7425 1
            } else if (xi >= fabs(eta)) {
d7428 1
a7428 1
               xf  =  sqrt(rhu/(1.0-1.0/sqrt(1.0+tau)));
d7430 1
a7430 1
            } else if (-eta > fabs(xi)) {
d7433 1
a7433 1
               yf  = -sqrt(rhu/(1.0-1.0/sqrt(1.0+tau)));
d7435 1
a7435 1
            } else if (eta > fabs(xi)) {
d7438 1
a7438 1
               yf  =  sqrt(rhu/(1.0-1.0/sqrt(1.0+tau)));
@


3.3
log
@WCSLIB 3.3
@
text
@d3 2
a4 2
*   WCSLIB 3.3 - an implementation of the FITS WCS convention.
*   Copyright (C) 1995-2003, Mark Calabretta
d29 1
a29 1
*   $Id: prj.c,v 3.2 2003/09/09 04:04:04 mcalabre Exp mcalabre $
d4530 2
a4531 2
         if (u < 0.0) {
            if (u < -tol) {
d4536 1
a4536 1
            u = 0.0;
@


3.2
log
@WCSLIB 3.2: test for null prjprm pointer given as function argument;
rationalized function return codes and messages.
@
text
@d3 1
a3 1
*   WCSLIB 3.2 - an implementation of the FITS WCS convention.
d29 1
a29 1
*   $Id: prj.c,v 3.1 2003/04/28 03:50:41 mcalabre Exp $
@


3.1
log
@WCSLIB 3.1
In prjprt(), print undefined values as "UNDEFINED"; set the new "global" and
"divergent" prjprm struct members.
@
text
@d3 1
a3 1
*   WCSLIB 3.1 - an implementation of the FITS WCS convention.
d29 1
a29 1
*   $Id: prj.c,v 3.0 2003/04/01 04:10:53 mcalabre Exp mcalabre $
d91 1
a91 1
const char *prjset_errmsg[] = {
d93 1
a93 9
   "Invalid projection parameters"};

const char *prjx2s_errmsg[] = {
   0,
   "Invalid projection parameters",
   "Invalid value of (x,y)"};

const char *prjs2x_errmsg[] = {
   0,
d95 2
a96 1
   "Invalid value of (phi,theta)"};
d98 1
a98 9
const char *prjrev_errmsg[] = {
   0,
   "Invalid projection parameters",
   "Invalid value of (x,y)"};

const char *prjfwd_errmsg[] = {
   0,
   "Invalid projection parameters",
   "Invalid value of (phi,theta)"};
d130 2
d244 2
d302 1
a302 1
      return 1;
d320 1
d322 1
a322 1
      if (prjset(prj)) return 1;
d340 1
d342 1
a342 1
      if (prjset(prj)) return 1;
d361 2
d374 1
a374 1
         return 1;
d415 2
d435 1
a435 1
      return 1;
d440 1
a440 1
      return 1;
d482 1
d484 1
a484 1
      if (azpset(prj)) return 1;
d534 1
a534 1
            *(statp++)  = 0;
d548 1
a548 1
                  status = 2;
d563 1
a563 1
            *(statp++)  = 0;
d590 1
d592 1
a592 1
      if (azpset(prj)) return 1;
d643 1
a643 1
            status = 2;
d654 1
a654 1
                  status = 2;
d671 1
a671 1
                        status = 2;
d726 2
d749 1
a749 1
      return 1;
d789 1
d791 1
d793 1
a793 1
      if (szpset(prj)) return 1;
d856 1
a856 1
               status = 2;
d883 1
a883 1
               status = 2;
d917 3
d921 1
a921 1
      if (szpset(prj)) return 1;
d971 1
a971 1
         status = 2;
d985 1
a985 1
                  status = 2;
d1003 1
a1003 1
                        status = 2;
d1042 2
d1083 1
d1085 1
a1085 1
      if (tanset(prj)) return 1;
d1159 1
d1161 1
a1161 1
      if (tanset(prj)) return 1;
d1208 1
a1208 1
         status = 2;
d1216 1
a1216 1
            status = 2;
d1254 2
d1302 1
d1304 1
a1304 1
      if (stgset(prj)) return 1;
d1378 1
d1380 1
a1380 1
      if (stgset(prj)) return 1;
d1427 1
a1427 1
         status = 2;
d1472 2
d1522 1
d1524 1
a1524 1
      if (sinset(prj)) return 1;
d1585 1
a1585 1
               status = 2;
d1609 1
a1609 1
                  status = 2;
d1636 1
a1636 1
                  status = 2;
d1679 1
d1681 1
a1681 1
      if (sinset(prj)) return 1;
d1740 1
a1740 1
            status = 2;
d1761 1
a1761 1
                  status = 2;
d1799 2
d1847 1
d1849 1
a1849 1
      if (arcset(prj)) return 1;
d1924 1
d1926 1
a1926 1
      if (arcset(prj)) return 1;
d2008 2
d2029 1
a2029 1
   if (k < 0) return 1;
d2038 1
a2038 1
         return 1;
d2114 1
d2116 1
a2116 1
      if (zpnset(prj)) return 1;
d2169 1
a2169 1
            return 1;
d2183 1
a2183 1
               status = 2;
d2197 1
a2197 1
                  status = 2;
d2205 1
a2205 1
                  status = 2;
d2221 1
a2221 1
                  status = 2;
d2229 1
a2229 1
                  status = 2;
d2292 1
d2294 1
a2294 1
      if (zpnset(prj)) return 1;
d2345 1
a2345 1
         status = 2;
d2382 2
d2431 1
d2433 1
a2433 1
      if (zeaset(prj)) return 1;
d2489 1
a2489 1
               status = 2;
d2522 1
d2524 1
a2524 1
      if (zeaset(prj)) return 1;
d2611 2
d2637 1
a2637 1
      return 1;
d2671 1
d2673 1
a2673 1
      if (airset(prj)) return 1;
d2743 1
a2743 1
               status = 2;
d2773 1
a2773 1
               status = 2;
d2807 1
d2809 1
a2809 1
      if (airset(prj)) return 1;
d2865 1
a2865 1
         status = 2;
d2910 2
d2932 1
a2932 1
         return 1;
d2939 1
a2939 1
         return 1;
d2946 1
a2946 1
         return 1;
d2953 1
a2953 1
         return 1;
d2984 1
d2986 1
a2986 1
      if (cypset(prj)) return 1;
d3024 1
a3024 1
         *(statp++)  = 0;
d3050 1
d3052 1
a3052 1
      if (cypset(prj)) return 1;
d3092 1
a3092 1
         status = 2;
d3138 2
d3159 1
a3159 1
         return 1;
d3167 1
a3167 1
         return 1;
d3199 1
d3201 1
a3201 1
      if (ceaset(prj)) return 1;
d3243 1
a3243 1
            status = 2;
d3253 1
a3253 1
         *(statp++)  = istat;
d3279 1
d3281 1
a3281 1
      if (ceaset(prj)) return 1;
d3349 2
d3397 1
d3399 1
a3399 1
      if (carset(prj)) return 1;
d3462 1
d3464 1
a3464 1
      if (carset(prj)) return 1;
d3532 2
d3580 1
d3582 1
a3582 1
      if (merset(prj)) return 1;
d3619 1
a3619 1
         *(statp++)  = 0;
d3645 1
d3647 1
a3647 1
      if (merset(prj)) return 1;
d3687 1
a3687 1
         status = 2;
d3725 2
d3773 1
d3775 1
a3775 1
      if (sflset(prj)) return 1;
d3815 1
a3815 1
         status = 2;
d3825 1
a3825 1
         *(statp++)  = 0;
d3851 1
d3853 1
a3853 1
      if (sflset(prj)) return 1;
d3926 2
d3979 1
d3981 1
a3981 1
      if (parset(prj)) return 1;
d4029 1
a4029 1
         status = 2;
d4035 1
a4035 1
            istat  = -1;
d4049 1
a4049 1
               status = 2;
d4080 1
d4082 1
a4082 1
      if (parset(prj)) return 1;
d4156 2
d4204 1
d4206 1
a4206 1
      if (molset(prj)) return 1;
d4255 1
a4255 1
            status = 2;
d4274 1
a4274 1
            status = 2;
d4286 1
a4286 1
            status = 2;
d4300 1
a4300 1
               status = 2;
d4332 1
d4334 1
a4334 1
      if (molset(prj)) return 1;
d4433 2
d4480 1
d4482 1
a4482 1
      if (aitset(prj)) return 1;
d4533 1
a4533 1
               status = 2;
d4552 1
a4552 1
               status = 2;
d4561 1
a4561 1
         *(statp++)  = istat;
d4587 1
d4589 1
a4589 1
      if (aitset(prj)) return 1;
d4675 2
d4681 1
a4681 1
      return 1;
d4697 1
a4697 1
      return 1;
d4704 1
a4704 1
      return 1;
d4736 1
d4738 1
a4738 1
      if (copset(prj)) return 1;
d4789 1
a4789 1
         *(statp++)  = 0;
d4814 1
d4816 1
a4816 1
      if (copset(prj)) return 1;
d4865 1
a4865 1
         status = 2;
d4872 1
a4872 1
            status = 2;
d4924 2
d4930 1
a4930 1
      return 1;
d4949 1
a4949 1
      return 1;
d4988 1
d4990 1
a4990 1
      if (coeset(prj)) return 1;
d5054 1
a5054 1
                  status = 2;
d5063 1
a5063 1
         *(statp++)  = istat;
d5088 1
d5090 1
a5090 1
      if (coeset(prj)) return 1;
d5177 2
d5183 1
a5183 1
      return 1;
d5204 1
a5204 1
      return 1;
d5235 1
d5237 1
a5237 1
      if (codset(prj)) return 1;
d5288 1
a5288 1
         *(statp++)  = 0;
d5313 1
d5315 1
a5315 1
      if (codset(prj)) return 1;
d5403 2
d5409 1
a5409 1
      return 1;
d5437 1
a5437 1
      return 1;
d5444 1
a5444 1
      return 1;
d5473 1
d5475 1
a5475 1
      if (cooset(prj)) return 1;
d5533 1
a5533 1
               status = 2;
d5566 1
d5568 1
a5568 1
      if (cooset(prj)) return 1;
d5616 1
a5616 1
            status = 2;
d5659 2
d5665 1
a5665 1
      return 1;
d5712 1
d5719 1
a5719 1
      if (bonset(prj)) return 1;
d5778 1
a5778 1
         *(statp++)  = 0;
d5803 1
d5810 1
a5810 1
      if (bonset(prj)) return 1;
d5885 2
d5937 1
d5939 1
a5939 1
      if (pcoset(prj)) return 1;
d6071 1
d6073 1
a6073 1
      if (pcoset(prj)) return 1;
d6151 2
d6199 1
d6201 1
a6201 1
      if (tscset(prj)) return 1;
d6247 2
a6248 2
               *(statp++)  = 1;
               status = 2;
d6255 2
a6256 2
               *(statp++)  = 1;
               status = 2;
d6309 1
a6309 1
         *(statp++)  = 0;
d6336 1
d6338 1
a6338 1
      if (tscset(prj)) return 1;
d6453 1
a6453 1
               status = 2;
d6460 1
a6460 1
               status = 2;
d6498 2
a6543 2

   /* Initialize. */
d6574 2
d6577 1
a6577 1
      if (cscset(prj)) return 1;
d6623 2
a6624 2
               *(statp++)  = 1;
               status = 2;
d6631 2
a6632 2
               *(statp++)  = 1;
               status = 2;
d6728 1
a6728 1
         *(statp++)  = 0;
a6752 1
   /* Initialize. */
d6767 3
d6771 1
a6771 1
      if (cscset(prj)) return 1;
d6907 1
a6907 1
               status = 2;
d6914 1
a6914 1
               status = 2;
d6952 2
d7001 1
d7003 1
a7003 1
      if (qscset(prj)) return 1;
d7049 2
a7050 2
               *(statp++)  = 1;
               status = 2;
d7057 2
a7058 2
               *(statp++)  = 1;
               status = 2;
d7119 2
a7120 2
               *(statp++)  = 1;
               status = 2;
d7240 1
d7242 1
a7242 1

d7244 1
a7244 1
      if (qscset(prj)) return 1;
d7429 1
a7429 1
               status = 2;
d7436 1
a7436 1
               status = 2;
@


3.0
log
@WCSLIB 3.0 (renamed from proj.c).
@
text
@d3 1
a3 1
*   WCSLIB 3.0 - an implementation of the FITS WCS convention.
d29 1
a29 1
*   $Id: proj.c,v 2.19 2001/11/16 02:58:31 mcalabre Exp $
d164 2
d196 5
a200 1
         printf("  %- 11.4g", prj->pv[prj->pvrange/100 + i]);
d209 10
a218 2
   printf("       phi0: %9f\n", prj->phi0);
   printf("     theta0: %9f\n", prj->theta0);
d229 2
d435 2
d743 2
d1049 2
d1255 2
d1473 2
d1792 2
d2002 2
d2035 1
d2367 2
d2595 2
d2890 2
d3113 2
d3318 2
d3497 2
d3686 2
d3883 2
d4111 2
d4384 2
d4626 2
d4871 2
d5120 2
d5342 2
d5592 2
d5810 2
d6072 2
d6415 2
d6865 2
@


2.20
log
@Updated date in copyright notice.
@
text
@d3 2
a4 2
*   WCSLIB - an implementation of the FITS WCS proposal.
*   Copyright (C) 1995-2002, Mark Calabretta
d22 4
a25 4
*      Postal address: Dr. Mark Calabretta,
*                      Australia Telescope National Facility,
*                      P.O. Box 76,
*                      Epping, NSW, 2121,
a27 203
*=============================================================================
*
*   C implementation of the spherical map projections recognized by the FITS
*   "World Coordinate System" (WCS) convention.
*
*   Summary of routines
*   -------------------
*   Each projection is implemented via separate functions for the forward,
*   *fwd(), and reverse, *rev(), transformation.
*
*   Initialization routines, *set(), compute intermediate values from the
*   projection parameters but need not be called explicitly - see the
*   explanation of prj.flag below.
*
*      prjset prjfwd prjrev   Driver routines (see below).
*
*      azpset azpfwd azprev   AZP: zenithal/azimuthal perspective
*      szpset szpfwd szprev   SZP: slant zenithal perspective
*      tanset tanfwd tanrev   TAN: gnomonic
*      stgset stgfwd stgrev   STG: stereographic
*      sinset sinfwd sinrev   SIN: orthographic/synthesis
*      arcset arcfwd arcrev   ARC: zenithal/azimuthal equidistant
*      zpnset zpnfwd zpnrev   ZPN: zenithal/azimuthal polynomial
*      zeaset zeafwd zearev   ZEA: zenithal/azimuthal equal area
*      airset airfwd airrev   AIR: Airy
*      cypset cypfwd cyprev   CYP: cylindrical perspective
*      ceaset ceafwd cearev   CEA: cylindrical equal area
*      carset carfwd carrev   CAR: Cartesian
*      merset merfwd merrev   MER: Mercator
*      sflset sflfwd sflrev   SFL: Sanson-Flamsteed
*      parset parfwd parrev   PAR: parabolic
*      molset molfwd molrev   MOL: Mollweide
*      aitset aitfwd aitrev   AIT: Hammer-Aitoff
*      copset copfwd coprev   COP: conic perspective
*      coeset coefwd coerev   COE: conic equal area
*      codset codfwd codrev   COD: conic equidistant
*      cooset coofwd coorev   COO: conic orthomorphic
*      bonset bonfwd bonrev   BON: Bonne
*      pcoset pcofwd pcorev   PCO: polyconic
*      tscset tscfwd tscrev   TSC: tangential spherical cube
*      cscset cscfwd cscrev   CSC: COBE quadrilateralized spherical cube
*      qscset qscfwd qscrev   QSC: quadrilateralized spherical cube
*
*
*   Driver routines; prjset(), prjfwd() & prjrev()
*   ----------------------------------------------
*   A set of driver routines are available for use as a generic interface to
*   the specific projection routines.  The interfaces to prjfwd() and prjrev()
*   are the same as those of the forward and reverse transformation routines
*   for the specific projections (see below).
*
*   The interface to prjset() differs slightly from that of the initialization
*   routines for the specific projections and unlike them it must be invoked
*   explicitly to use prjfwd() and prjrev().
*
*   Given:
*      pcode[4] const char
*                        WCS projection code.
*
*   Given and/or returned:
*      prj      prjprm*  Projection parameters (see below).
*
*   Function return value:
*               int      Error status
*                           0: Success.
*
*
*   Initialization routine; *set()
*   ------------------------------
*   Initializes members of a prjprm data structure which hold intermediate
*   values.  Note that this routine need not be called directly; it will be
*   invoked by prjfwd() and prjrev() if the "flag" structure member is
*   anything other than a predefined magic value.
*
*   Given and/or returned:
*      prj      prjprm*  Projection parameters (see below).
*
*   Function return value:
*               int      Error status
*                           0: Success.
*                           1: Invalid projection parameters.
*
*   Forward transformation; *fwd()
*   -----------------------------
*   Compute (x,y) coordinates in the plane of projection from native spherical
*   coordinates (phi,theta).
*
*   Given:
*      phi,     const double
*      theta             Longitude and latitude of the projected point in
*                        native spherical coordinates, in degrees.
*
*   Given and returned:
*      prj      prjprm*  Projection parameters (see below).
*
*   Returned:
*      x,y      double*  Projected coordinates.
*
*   Function return value:
*               int      Error status
*                           0: Success.
*                           1: Invalid projection parameters.
*                           2: Invalid value of (phi,theta).
*
*   Reverse transformation; *rev()
*   -----------------------------
*   Compute native spherical coordinates (phi,theta) from (x,y) coordinates in
*   the plane of projection.
*
*   Given:
*      x,y      const double
*                        Projected coordinates.
*
*   Given and returned:
*      prj      prjprm*  Projection parameters (see below).
*
*   Returned:
*      phi,     double*  Longitude and latitude of the projected point in
*      theta             native spherical coordinates, in degrees.
*
*   Function return value:
*               int      Error status
*                           0: Success.
*                           1: Invalid projection parameters.
*                           2: Invalid value of (x,y).
*                           1: Invalid projection parameters.
*
*   Projection parameters
*   ---------------------
*   The prjprm struct consists of the following:
*
*      int flag
*         This flag must be set to zero whenever any of p[10] or r0 are set
*         or changed.  This signals the initialization routine to recompute
*         intermediaries.  flag may also be set to -1 to disable strict bounds
*         checking for the AZP, SZP, TAN, SIN, ZPN, and COP projections.
*
*      double r0
*         r0; The radius of the generating sphere for the projection, a linear
*         scaling parameter.  If this is zero, it will be reset to the default
*         value of 180/pi (the value for FITS WCS).
*
*      double p[10]
*         The first 10 elements contain projection parameters which correspond
*         to the PROJPn keywords in FITS, so p[0] is PROJP0, and p[9] is
*         PROJP9.  Many projections use p[1] (PROJP1) and some also use p[2]
*         (PROJP2).  ZPN is the only projection which uses any of the others.
*
*   The remaining members of the prjprm struct are maintained by the
*   initialization routines and should not be modified.  This is done for the
*   sake of efficiency and to allow an arbitrary number of contexts to be
*   maintained simultaneously.
*
*      char code[4]
*         Three-letter projection code.
*
*      double phi0, theta0
*         Native longitude and latitude of the reference point, in degrees.
*
*      double w[10]
*      int n
*         Intermediate values derived from the projection parameters.
*
*      int (*prjfwd)()
*      int (*prjrev)()
*         Pointers to the forward and reverse projection routines.
*
*   Usage of the p[] array as it applies to each projection is described in
*   the prologue to each trio of projection routines.
*
*   Argument checking
*   -----------------
*   Forward routines:
*
*      The values of phi and theta (the native longitude and latitude)
*      normally lie in the range [-180,180] for phi, and [-90,90] for theta.
*      However, all forward projections will accept any value of phi and will
*      not normalize it.
*
*      The forward projection routines do not explicitly check that theta lies
*      within the range [-90,90].  They do check for any value of theta which
*      produces an invalid argument to the projection equations (e.g. leading
*      to division by zero).  The forward routines for AZP, SZP, TAN, SIN,
*      ZPN, and COP also return error 2 if (phi,theta) corresponds to the
*      overlapped (far) side of the projection but also return the
*      corresponding value of (x,y).  This strict bounds checking may be
*      relaxed by setting prj->flag to -1 (rather than 0) when these
*      projections are initialized.
*
*   Reverse routines:
*
*      Error checking on the projected coordinates (x,y) is limited to that
*      required to ascertain whether a solution exists.  Where a solution does
*      exist no check is made that the value of phi and theta obtained lie
*      within the ranges [-180,180] for phi, and [-90,90] for theta.
*
*   Accuracy
*   --------
*   Closure to a precision of at least 1E-10 degree of longitude and latitude
*   has been verified for typical projection parameters on the 1 degree grid
*   of native longitude and latitude (to within 5 degrees of any latitude
*   where the projection may diverge).
*
d29 1
a29 1
*   $Id: proj.c,v 2.19 2001/11/16 02:58:31 mcalabre Exp mcalabre $
d33 3
d38 2
a39 1
#include "proj.h"
d41 17
a57 2
int  npcode = 26;
char pcodes[26][4] =
d89 1
d95 6
a100 1
const char *prjfwd_errmsg[] = {
d110 5
a115 1
#ifdef COPYSIGN
d117 3
a119 1
#endif
d122 53
d176 1
a176 1
/*==========================================================================*/
d178 1
a178 1
int prjset(pcode, prj)
d180 58
a237 1
const char pcode[4];
d241 3
a243 2
   /* Set pointers to the forward and reverse projection routines. */
   if (strcmp(pcode, "AZP") == 0) {
d245 1
a245 1
   } else if (strcmp(pcode, "SZP") == 0) {
d247 1
a247 1
   } else if (strcmp(pcode, "TAN") == 0) {
d249 1
a249 1
   } else if (strcmp(pcode, "STG") == 0) {
d251 1
a251 1
   } else if (strcmp(pcode, "SIN") == 0) {
d253 1
a253 1
   } else if (strcmp(pcode, "ARC") == 0) {
d255 1
a255 1
   } else if (strcmp(pcode, "ZPN") == 0) {
d257 1
a257 1
   } else if (strcmp(pcode, "ZEA") == 0) {
d259 1
a259 1
   } else if (strcmp(pcode, "AIR") == 0) {
d261 1
a261 1
   } else if (strcmp(pcode, "CYP") == 0) {
d263 1
a263 1
   } else if (strcmp(pcode, "CEA") == 0) {
d265 1
a265 1
   } else if (strcmp(pcode, "CAR") == 0) {
d267 1
a267 1
   } else if (strcmp(pcode, "MER") == 0) {
d269 1
a269 1
   } else if (strcmp(pcode, "SFL") == 0) {
d271 1
a271 1
   } else if (strcmp(pcode, "PAR") == 0) {
d273 1
a273 1
   } else if (strcmp(pcode, "MOL") == 0) {
d275 1
a275 1
   } else if (strcmp(pcode, "AIT") == 0) {
d277 1
a277 1
   } else if (strcmp(pcode, "COP") == 0) {
d279 1
a279 1
   } else if (strcmp(pcode, "COE") == 0) {
d281 1
a281 1
   } else if (strcmp(pcode, "COD") == 0) {
d283 1
a283 1
   } else if (strcmp(pcode, "COO") == 0) {
d285 1
a285 1
   } else if (strcmp(pcode, "BON") == 0) {
d287 1
a287 1
   } else if (strcmp(pcode, "PCO") == 0) {
d289 1
a289 1
   } else if (strcmp(pcode, "TSC") == 0) {
d291 1
a291 1
   } else if (strcmp(pcode, "CSC") == 0) {
d293 1
a293 1
   } else if (strcmp(pcode, "QSC") == 0) {
d305 1
a305 1
int prjfwd(phi, theta, prj, x, y)
a306 1
const double phi, theta;
d308 4
a311 1
double *x, *y;
d314 6
a319 1
   return prj->prjfwd(phi, theta, prj, x, y);
d324 23
a346 1
int prjrev(x, y, prj, phi, theta)
a347 1
const double x, y;
d349 1
a349 1
double *phi, *theta;
d352 18
a369 1
   return prj->prjrev(x, y, prj, phi, theta);
d376 2
a377 2
*      prj->p[1]    Distance parameter, mu in units of r0.
*      prj->p[2]    Tilt angle, gamma in degrees.
d380 3
a382 2
*      prj->flag    AZP, or -AZP if prj->flag is given < 0.
*      prj->r0      r0; reset to 180/pi if 0.
d385 1
d387 2
a388 2
*      prj->phi0     0.0
*      prj->theta0  90.0
d397 2
a398 2
*      prj->prjfwd  Pointer to azpfwd().
*      prj->prjrev  Pointer to azprev().
d406 1
a407 3
   prj->flag   = copysign(AZP, prj->flag);
   prj->phi0   =  0.0;
   prj->theta0 = 90.0;
d409 2
d413 8
a420 1
   prj->w[0] = prj->r0*(prj->p[1] + 1.0);
d425 1
a425 1
   prj->w[3] = cosd(prj->p[2]);
d431 1
a431 1
   prj->w[4] = sind(prj->p[2]);
d434 2
a435 2
   if (fabs(prj->p[1]) > 1.0) {
      prj->w[5] = asind(-1.0/prj->p[1]);
d440 1
a440 1
   prj->w[6] = prj->p[1] * prj->w[3];
d443 2
a444 2
   prj->prjfwd = azpfwd;
   prj->prjrev = azprev;
d446 1
a446 1
   return 0;
d451 1
a451 1
int azpfwd(phi, theta, prj, x, y)
a452 1
const double phi, theta;
d454 4
a457 1
double *x, *y;
d460 6
a465 1
   double a, b, cphi, cthe, r, s, t;
d467 3
a469 1
   if (abs(prj->flag) != AZP) {
d473 11
a483 2
   cphi = cosd(phi);
   cthe = cosd(theta);
d485 12
a496 4
   s = prj->w[1]*cphi;
   t = (prj->p[1] + sind(theta)) + cthe*s;
   if (t == 0.0) {
      return 2;
a498 3
   r  =  prj->w[0]*cthe/t;
   *x =  r*sind(phi);
   *y = -r*cphi*prj->w[2];
d500 29
a528 6
   /* Bounds checking. */
   if (prj->flag > 0) {
      /* Overlap. */
      if (theta < prj->w[5]) {
         return 2;
      }
d530 11
a540 3
      /* Divergence. */
      if (prj->w[7] > 0.0) {
         t = prj->p[1] / sqrt(1.0 + s*s);
a541 3
         if (fabs(t) <= 1.0) {
            s = atand(-s);
            t = asind(t);
d548 2
a549 3
            if (theta < ((a > b) ? a : b)) {
               return 2;
            }
d554 1
a554 1
   return 0;
d559 1
a559 1
int azprev(x, y, prj, phi, theta)
a560 1
const double x, y;
d562 4
a565 1
double *phi, *theta;
d568 6
a573 2
   double a, b, r, s, t, ycosg;
   const double tol = 1.0e-13;
d575 2
a576 1
   if (abs(prj->flag) != AZP) {
d580 30
a609 1
   ycosg = y*prj->w[3];
d611 18
a628 6
   r = sqrt(x*x + ycosg*ycosg);
   if (r == 0.0) {
      *phi   =  0.0;
      *theta = 90.0;
   } else {
      *phi = atan2d(x, -ycosg);
d630 2
a631 2
      s = r / (prj->w[0] + y*prj->w[4]);
      t = s*prj->p[1]/sqrt(s*s + 1.0);
d633 28
a660 1
      s = atan2d(1.0, s);
d662 3
a664 4
      if (fabs(t) > 1.0) {
         t = copysign(90.0,t);
         if (fabs(t) > 1.0+tol) {
            return 2;
a665 2
      } else {
         t = asind(t);
a666 8

      a = s - t;
      b = s + t + 180.0;

      if (a > 90.0) a -= 360.0;
      if (b > 90.0) b -= 360.0;

      *theta = (a > b) ? a : b;
d669 1
a669 1
   return 0;
d676 1
a676 1
*      prj->p[1]    Distance of the point of projection from the centre of the
d678 2
a679 2
*      prj->p[2]    Native longitude, phi_c, and ...
*      prj->p[3]    Native latitude, theta_c, on the planewards side of the
d684 3
a686 2
*      prj->flag    SZP, or -SZP if prj->flag is given < 0.
*      prj->r0      r0; reset to 180/pi if 0.
d689 1
d691 2
a692 2
*      prj->phi0     0.0
*      prj->theta0  90.0
d702 2
a703 2
*      prj->prjfwd  Pointer to szpfwd().
*      prj->prjrev  Pointer to szprev().
d711 1
a712 3
   prj->flag   = copysign(SZP, prj->flag);
   prj->phi0   =  0.0;
   prj->theta0 = 90.0;
d714 3
d719 7
d728 1
a728 1
   prj->w[3] = prj->p[1] * sind(prj->p[3]) + 1.0;
d733 2
a734 2
   prj->w[1] = -prj->p[1] * cosd(prj->p[3]) * sind(prj->p[2]);
   prj->w[2] =  prj->p[1] * cosd(prj->p[3]) * cosd(prj->p[2]);
d746 2
a747 2
   prj->prjfwd = szpfwd;
   prj->prjrev = szprev;
d749 1
a749 1
   return 0;
d754 1
a754 1
int szpfwd(phi, theta, prj, x, y)
a755 1
const double phi, theta;
d757 4
a760 1
double *x, *y;
d763 6
a768 1
   double a, b, cphi, cthe, s, sphi, t;
d770 2
a771 1
   if (abs(prj->flag) != SZP) {
d775 10
a784 4
   cphi = cosd(phi);
   sphi = sind(phi);
   cthe = cosd(theta);
   s = 1.0 - sind(theta);
d786 13
a798 3
   t = prj->w[3] - s;
   if (t == 0.0) {
      return 2;
d801 12
a812 2
   *x =  (prj->w[6]*cthe*sphi - prj->w[4]*s)/t;
   *y = -(prj->w[6]*cthe*cphi + prj->w[5]*s)/t;
d814 15
a828 6
   /* Bounds checking. */
   if (prj->flag > 0) {
      /* Divergence. */
      if (theta < prj->w[8]) {
         return 2;
      }
d830 9
a838 4
      /* Overlap. */
      if (fabs(prj->p[1]) > 1.0) {
         s = prj->w[1]*sphi - prj->w[2]*cphi;
         t = 1.0/sqrt(prj->w[7] + s*s);
d840 11
a850 5
         if (fabs(t) <= 1.0) {
            s = atan2d(s, prj->w[3] - 1.0);
            t = asind(t);
            a = s - t;
            b = s + t + 180.0;
d852 5
a856 2
            if (a > 90.0) a -= 360.0;
            if (b > 90.0) b -= 360.0;
d858 6
a863 2
            if (theta < ((a > b) ? a : b)) {
               return 2;
d865 4
d870 3
d876 1
a876 1
   return 0;
d881 1
a881 1
int szprev(x, y, prj, phi, theta)
a882 1
const double x, y;
d884 4
a887 1
double *phi, *theta;
d890 5
a894 2
   double a, b, c, d, r2, sth1, sth2, sthe, sxy, t, x1, xp, y1, yp, z;
   const double tol = 1.0e-13;
d896 1
a896 1
   if (abs(prj->flag) != SZP) {
d900 29
a928 3
   xp = x*prj->w[0];
   yp = y*prj->w[0];
   r2 = xp*xp + yp*yp;
a929 3
   x1 = (xp - prj->w[1])/prj->w[3];
   y1 = (yp - prj->w[2])/prj->w[3];
   sxy = xp*x1 + yp*y1;
d931 15
a945 4
   if (r2 < 1.0e-10) {
      /* Use small angle formula. */
      z = r2/2.0;
      *theta = 90.0 - R2D*sqrt(r2/(1.0 + sxy));
d947 1
a947 6
   } else {
      t = x1*x1 + y1*y1;
      a = t + 1.0;
      b = sxy - t;
      c = r2 - sxy - sxy + t - 1.0;
      d = b*b - a*c;
d949 35
a983 17
      /* Check for a solution. */
      if (d < 0.0) {
         return 2;
      }
      d = sqrt(d);

      /* Choose solution closest to pole. */
      sth1 = (-b + d)/a;
      sth2 = (-b - d)/a;
      sthe = (sth1 > sth2) ? sth1 : sth2;
      if (sthe > 1.0) {
         if (sthe-1.0 < tol) {
            sthe = 1.0;
         } else {
            sthe = (sth1 < sth2) ? sth1 : sth2;
         }
      }
d985 3
a987 3
      if (sthe < -1.0) {
         if (sthe+1.0 > -tol) {
            sthe = -1.0;
a989 8

      if (sthe > 1.0 || sthe < -1.0) {
         return 2;
      }

      *theta = asind(sthe);

      z = 1.0 - sthe;
d992 2
a993 1
   *phi = atan2d(xp - x1*z, -(yp - y1*z));
a994 2
   return 0;
}
d1000 3
a1002 2
*      prj->flag    TAN, or -TAN if prj->flag is given < 0.
*      prj->r0      r0; reset to 180/pi if 0.
d1005 1
d1007 4
a1010 4
*      prj->phi0     0.0
*      prj->theta0  90.0
*      prj->prjfwd  Pointer to tanfwd().
*      prj->prjrev  Pointer to tanrev().
d1018 1
a1019 3
   prj->flag   = copysign(TAN, prj->flag);
   prj->phi0   =  0.0;
   prj->theta0 = 90.0;
d1023 9
a1031 2
   prj->prjfwd = tanfwd;
   prj->prjrev = tanrev;
d1033 1
a1033 1
   return 0;
d1038 1
a1038 1
int tanfwd(phi, theta, prj, x, y)
a1039 1
const double phi, theta;
d1041 4
a1044 1
double *x, *y;
d1047 6
a1052 1
   double r, s;
d1054 12
a1065 2
   if (abs(prj->flag) != TAN) {
      if(tanset(prj)) return 1;
d1068 13
a1080 3
   s = sind(theta);
   if (s == 0.0) {
      return 2;
d1083 12
a1094 3
   r =  prj->r0*cosd(theta)/s;
   *x =  r*sind(phi);
   *y = -r*cosd(phi);
d1096 10
a1105 2
   if (prj->flag > 0 && s < 0.0) {
      return 2;
d1113 1
a1113 1
int tanrev(x, y, prj, phi, theta)
a1114 1
const double x, y;
d1116 4
a1119 1
double *phi, *theta;
d1122 6
a1127 1
   double r;
d1129 2
a1130 1
   if (abs(prj->flag) != TAN) {
d1134 61
a1194 5
   r = sqrt(x*x + y*y);
   if (r == 0.0) {
      *phi = 0.0;
   } else {
      *phi = atan2d(x, -y);
a1195 1
   *theta = atan2d(prj->r0, r);
d1197 1
a1197 1
   return 0;
d1204 3
a1206 1
*      prj->r0      r0; reset to 180/pi if 0.
d1209 1
d1211 2
a1212 3
*      prj->flag     STG
*      prj->phi0     0.0
*      prj->theta0  90.0
d1215 2
a1216 2
*      prj->prjfwd  Pointer to stgfwd().
*      prj->prjrev  Pointer to stgrev().
d1224 1
d1226 7
a1232 3
   prj->flag   =  STG;
   prj->phi0   =  0.0;
   prj->theta0 = 90.0;
d1243 2
a1244 2
   prj->prjfwd = stgfwd;
   prj->prjrev = stgrev;
d1246 1
a1246 1
   return 0;
d1251 1
a1251 1
int stgfwd(phi, theta, prj, x, y)
a1252 1
const double phi, theta;
d1254 4
a1257 1
double *x, *y;
d1260 5
a1264 1
   double r, s;
d1266 2
d1272 22
a1293 3
   s = 1.0 + sind(theta);
   if (s == 0.0) {
      return 2;
a1295 3
   r =  prj->w[0]*cosd(theta)/s;
   *x =  r*sind(phi);
   *y = -r*cosd(phi);
d1297 24
d1326 1
a1326 1
int stgrev(x, y, prj, phi, theta)
a1327 1
const double x, y;
d1329 4
a1332 1
double *phi, *theta;
d1335 6
a1340 1
   double r;
d1342 1
d1347 55
a1401 5
   r = sqrt(x*x + y*y);
   if (r == 0.0) {
      *phi = 0.0;
   } else {
      *phi = atan2d(x, -y);
a1402 1
   *theta = 90.0 - 2.0*atand(r*prj->w[1]);
d1404 1
a1404 1
   return 0;
d1411 1
a1411 1
*      prj->p[1:2]  Obliqueness parameters, xi and eta.
d1414 3
a1416 2
*      prj->flag    SIN, or -SIN if prj->flag is given < 0.
*      prj->r0      r0; reset to 180/pi if 0.
d1419 1
d1421 2
a1422 2
*      prj->phi0     0.0
*      prj->theta0  90.0
d1427 2
a1428 2
*      prj->prjfwd  Pointer to sinfwd().
*      prj->prjrev  Pointer to sinrev().
d1436 1
a1437 3
   prj->flag   = copysign(SIN, prj->flag);
   prj->phi0   =  0.0;
   prj->theta0 = 90.0;
d1439 2
d1443 7
d1451 1
a1451 1
   prj->w[1] = prj->p[1]*prj->p[1] + prj->p[2]*prj->p[2];
d1455 2
a1456 2
   prj->prjfwd = sinfwd;
   prj->prjrev = sinrev;
d1458 1
a1458 1
   return 0;
d1463 1
a1463 1
int sinfwd(phi, theta, prj, x, y)
a1464 1
const double phi, theta;
d1466 4
a1469 1
double *x, *y;
d1472 7
a1478 1
   double cphi, cthe, sphi, t, z;
d1480 3
a1482 1
   if (abs(prj->flag) != SIN) {
d1486 26
a1511 6
   t = (90.0 - fabs(theta))*D2R;
   if (t < 1.0e-5) {
      if (theta > 0.0) {
         z = t*t/2.0;
      } else {
         z = 2.0 - t*t/2.0;
a1512 4
      cthe = t;
   } else {
      z =  1.0 - sind(theta);
      cthe = cosd(theta);
d1515 87
a1601 4
   cphi = cosd(phi);
   sphi = sind(phi);
   *x =  prj->r0*(cthe*sphi + prj->p[1]*z);
   *y = -prj->r0*(cthe*cphi - prj->p[2]*z);
d1603 7
a1609 6
   /* Validate this solution. */
   if (prj->flag > 0) {
      if (prj->w[1] == 0.0) {
         /* Orthographic projection. */
         if (theta < 0.0) {
            return 2;
d1611 2
a1612 6
      } else {
         /* "Synthesis" projection. */
         t = -atand(prj->p[1]*sphi - prj->p[2]*cphi);
         if (theta < t) {
            return 2;
         }
d1616 1
a1616 1
   return 0;
d1621 1
a1621 1
int sinrev (x, y, prj, phi, theta)
a1622 1
const double x, y;
d1624 4
a1627 1
double *phi, *theta;
d1630 6
a1635 2
   const double tol = 1.0e-13;
   double a, b, c, d, r2, sth1, sth2, sthe, sxy, x0, x1, xp, y0, y1, yp, z;
d1637 2
a1638 1
   if (abs(prj->flag) != SIN) {
d1642 27
a1668 11
   /* Compute intermediaries. */
   x0 = x*prj->w[0];
   y0 = y*prj->w[0];
   r2 = x0*x0 + y0*y0;

   if (prj->w[1] == 0.0) {
      /* Orthographic projection. */
      if (r2 != 0.0) {
         *phi = atan2d(x0, -y0);
      } else {
         *phi = 0.0;
d1670 2
d1673 14
a1686 4
      if (r2 < 0.5) {
         *theta = acosd(sqrt(r2));
      } else if (r2 <= 1.0) {
         *theta = asind(sqrt(1.0 - r2));
d1688 2
a1689 1
         return 2;
d1691 1
d1693 7
a1699 5
   } else {
      /* "Synthesis" projection. */
      x1 = prj->p[1];
      y1 = prj->p[2];
      sxy = x0*x1 + y0*y1;
d1701 5
a1705 4
      if (r2 < 1.0e-10) {
         /* Use small angle formula. */
         z = r2/2.0;
         *theta = 90.0 - R2D*sqrt(r2/(1.0 + sxy));
d1708 13
a1720 20
         a = prj->w[2];
         b = sxy - prj->w[1];
         c = r2 - sxy - sxy + prj->w[3];
         d = b*b - a*c;

         /* Check for a solution. */
         if (d < 0.0) {
            return 2;
         }
         d = sqrt(d);

         /* Choose solution closest to pole. */
         sth1 = (-b + d)/a;
         sth2 = (-b - d)/a;
         sthe = (sth1 > sth2) ? sth1 : sth2;
         if (sthe > 1.0) {
            if (sthe-1.0 < tol) {
               sthe = 1.0;
            } else {
               sthe = (sth1 < sth2) ? sth1 : sth2;
a1721 7
         }

         if (sthe < -1.0) {
            if (sthe+1.0 > -tol) {
               sthe = -1.0;
            }
         }
d1723 3
a1725 2
         if (sthe > 1.0 || sthe < -1.0) {
            return 2;
a1726 3

         *theta = asind(sthe);
         z = 1.0 - sthe;
a1727 8

      xp = -y0 + prj->p[2]*z;
      yp =  x0 - prj->p[1]*z;
      if (xp == 0.0 && yp == 0.0) {
         *phi = 0.0;
      } else {
         *phi = atan2d(yp,xp);
      }
d1730 1
a1730 1
   return 0;
d1737 3
a1739 1
*      prj->r0      r0; reset to 180/pi if 0.
d1742 1
d1744 2
a1745 3
*      prj->flag     ARC
*      prj->phi0     0.0
*      prj->theta0  90.0
d1748 2
a1749 2
*      prj->prjfwd  Pointer to arcfwd().
*      prj->prjrev  Pointer to arcrev().
d1757 1
d1759 7
a1765 3
   prj->flag   =  ARC;
   prj->phi0   =  0.0;
   prj->theta0 = 90.0;
d1776 2
a1777 2
   prj->prjfwd = arcfwd;
   prj->prjrev = arcrev;
d1779 1
a1779 1
   return 0;
d1784 1
a1784 1
int arcfwd(phi, theta, prj, x, y)
a1785 1
const double phi, theta;
d1787 4
a1790 1
double *x, *y;
d1793 6
a1798 1
   double r;
d1800 1
d1805 36
a1840 3
   r =  prj->w[0]*(90.0 - theta);
   *x =  r*sind(phi);
   *y = -r*cosd(phi);
d1842 13
d1860 1
a1860 1
int arcrev(x, y, prj, phi, theta)
a1861 1
const double x, y;
d1863 4
a1866 1
double *phi, *theta;
d1869 6
a1874 1
   double r;
d1876 1
d1881 42
a1922 5
   r = sqrt(x*x + y*y);
   if (r == 0.0) {
      *phi = 0.0;
   } else {
      *phi = atan2d(x, -y);
a1923 1
   *theta = 90.0 - r*prj->w[1];
d1932 1
a1932 1
*      prj->p[0:9]  Polynomial coefficients.
d1935 3
a1937 2
*      prj->flag    ZPN, or -ZPN if prj->flag is given < 0.
*      prj->r0      r0; reset to 180/pi if 0.
d1940 1
d1942 2
a1943 2
*      prj->phi0     0.0
*      prj->theta0  90.0
d1947 2
a1948 2
*      prj->prjfwd  Pointer to zpnfwd().
*      prj->prjrev  Pointer to zpnrev().
d1956 1
a1956 1
   int   i, j, k;
d1961 1
a1961 3
   prj->flag   = copysign(ZPN, prj->flag);
   prj->phi0   =  0.0;
   prj->theta0 = 90.0;
d1963 3
d1968 7
d1976 1
a1976 1
   for (k = 9; k >= 0 && prj->p[k] == 0.0; k--);
d1984 1
a1984 1
      d1  = prj->p[1];
d1990 2
a1991 2
      for (i = 0; i < 180; i++) {
         zd2 = i*D2R;
d1993 2
a1994 2
         for (j = k; j > 0; j--) {
            d2 = d2*zd2 + j*prj->p[j];
d2002 1
a2002 1
      if (i == 180) {
d2007 1
a2007 1
         for (i = 1; i <= 10; i++) {
d2011 2
a2012 2
            for (j = k; j > 0; j--) {
               d = d*zd + j*prj->p[j];
d2028 2
a2029 2
      for (j = k; j >= 0; j--) {
         r = r*zd + prj->p[j];
d2035 2
a2036 2
   prj->prjfwd = zpnfwd;
   prj->prjrev = zpnrev;
d2038 1
a2038 1
   return 0;
d2043 1
a2043 1
int zpnfwd(phi, theta, prj, x, y)
a2044 1
const double phi, theta;
d2046 4
a2049 1
double *x, *y;
d2052 7
a2058 2
   int   j;
   double r, s;
d2060 2
a2061 1
   if (abs(prj->flag) != ZPN) {
d2065 12
a2076 1
   s = (90.0 - theta)*D2R;
d2078 13
a2090 3
   r = 0.0;
   for (j = 9; j >= 0; j--) {
      r = r*s + prj->p[j];
d2092 1
a2092 1
   r = prj->r0*r;
d2094 8
a2101 2
   *x =  r*sind(phi);
   *y = -r*cosd(phi);
d2103 111
a2213 2
   if (prj->flag > 0 && s > prj->w[0]) {
      return 2;
d2216 1
a2216 1
   return 0;
d2221 1
a2221 1
int zpnrev(x, y, prj, phi, theta)
a2222 1
const double x, y;
d2224 4
a2227 1
double *phi, *theta;
d2230 6
a2235 3
   int   i, j, k;
   double a, b, c, d, lambda, r, r1, r2, rt, zd, zd1, zd2;
   const double tol = 1.0e-13;
d2237 2
a2238 1
   if (abs(prj->flag) != ZPN) {
d2242 30
a2271 1
   k = prj->n;
d2273 7
a2279 1
   r = sqrt(x*x + y*y)/prj->r0;
d2281 3
a2283 33
   if (k < 1) {
      /* Constant - no solution. */
      return 1;
   } else if (k == 1) {
      /* Linear. */
      zd = (r - prj->p[0])/prj->p[1];
   } else if (k == 2) {
      /* Quadratic. */
      a = prj->p[2];
      b = prj->p[1];
      c = prj->p[0] - r;

      d = b*b - 4.0*a*c;
      if (d < 0.0) {
         return 2;
      }
      d = sqrt(d);

      /* Choose solution closest to pole. */
      zd1 = (-b + d)/(2.0*a);
      zd2 = (-b - d)/(2.0*a);
      zd  = (zd1<zd2) ? zd1 : zd2;
      if (zd < -tol) zd = (zd1>zd2) ? zd1 : zd2;
      if (zd < 0.0) {
         if (zd < -tol) {
            return 2;
         }
         zd = 0.0;
      } else if (zd > PI) {
         if (zd > PI+tol) {
            return 2;
         }
         zd = PI;
d2285 1
a2285 43
   } else {
      /* Higher order - solve iteratively. */
      zd1 = 0.0;
      r1  = prj->p[0];
      zd2 = prj->w[0];
      r2  = prj->w[1];

      if (r < r1) {
         if (r < r1-tol) {
            return 2;
         }
         zd = zd1;
      } else if (r > r2) {
         if (r > r2+tol) {
            return 2;
         }
         zd = zd2;
      } else {
         /* Disect the interval. */
         for (j = 0; j < 100; j++) {
            lambda = (r2 - r)/(r2 - r1);
            if (lambda < 0.1) {
               lambda = 0.1;
            } else if (lambda > 0.9) {
               lambda = 0.9;
            }

            zd = zd2 - lambda*(zd2 - zd1);

            rt = 0.0;
            for (i = k; i >= 0; i--) {
                rt = (rt * zd) + prj->p[i];
            }

            if (rt < r) {
                if (r-rt < tol) break;
                r1 = rt;
                zd1 = zd;
            } else {
                if (rt-r < tol) break;
                r2 = rt;
                zd2 = zd;
            }
d2287 4
a2290 2
            if (fabs(zd2-zd1) < tol) break;
         }
a2291 1
   }
d2293 5
a2297 4
   if (r == 0.0) {
      *phi = 0.0;
   } else {
      *phi = atan2d(x, -y);
a2298 1
   *theta = 90.0 - zd*R2D;
d2300 1
a2300 1
   return 0;
d2307 3
a2309 1
*      prj->r0      r0; reset to 180/pi if 0.
d2312 1
d2314 2
a2315 3
*      prj->flag     ZEA
*      prj->phi0     0.0
*      prj->theta0  90.0
d2318 2
a2319 2
*      prj->prjfwd  Pointer to zeafwd().
*      prj->prjrev  Pointer to zearev().
d2327 1
d2329 7
a2335 3
   prj->flag   =  ZEA;
   prj->phi0   =  0.0;
   prj->theta0 = 90.0;
d2346 2
a2347 2
   prj->prjfwd = zeafwd;
   prj->prjrev = zearev;
d2349 1
a2349 1
   return 0;
d2354 1
a2354 1
int zeafwd(phi, theta, prj, x, y)
a2355 1
const double phi, theta;
d2357 4
a2360 1
double *x, *y;
d2363 6
a2368 1
   double r;
d2370 2
d2376 26
a2401 3
   r =  prj->w[0]*sind((90.0 - theta)/2.0);
   *x =  r*sind(phi);
   *y = -r*cosd(phi);
d2403 38
a2440 1
   return 0;
d2445 1
a2445 1
int zearev(x, y, prj, phi, theta)
a2446 1
const double x, y;
d2448 4
a2451 1
double *phi, *theta;
d2454 6
a2459 2
   double r, s;
   const double tol = 1.0e-12;
d2461 1
d2466 26
a2491 5
   r = sqrt(x*x + y*y);
   if (r == 0.0) {
      *phi = 0.0;
   } else {
      *phi = atan2d(x, -y);
d2494 13
a2506 6
   s = r*prj->w[1];
   if (fabs(s) > 1.0) {
      if (fabs(r - prj->w[0]) < tol) {
         *theta = -90.0;
      } else {
         return 2;
a2507 2
   } else {
      *theta = 90.0 - 2.0*asind(s);
d2517 1
a2517 1
*      prj->p[1]    Latitude theta_b within which the error is minimized, in
d2521 3
a2523 1
*      prj->r0      r0; reset to 180/pi if 0.
d2526 1
d2528 2
a2529 3
*      prj->flag     AIR
*      prj->phi0     0.0
*      prj->theta0  90.0
d2538 2
a2539 2
*      prj->prjfwd  Pointer to airfwd().
*      prj->prjrev  Pointer to airrev().
d2548 1
a2548 1
   double cxi;
d2550 1
a2551 3
   prj->flag   =  AIR;
   prj->phi0   =  0.0;
   prj->theta0 = 90.0;
d2553 1
d2556 7
d2564 1
a2564 1
   if (prj->p[1] == 90.0) {
d2567 3
a2569 3
   } else if (prj->p[1] > -90.0) {
      cxi = cosd((90.0 - prj->p[1])/2.0);
      prj->w[1] = log(cxi)*(cxi*cxi)/(1.0-cxi*cxi);
d2580 2
a2581 2
   prj->prjfwd = airfwd;
   prj->prjrev = airrev;
d2583 1
a2583 1
   return 0;
d2588 1
a2588 1
int airfwd(phi, theta, prj, x, y)
a2589 1
const double phi, theta;
d2591 4
a2594 1
double *x, *y;
d2597 6
a2602 1
   double cxi, r, txi, xi;
d2604 2
d2610 23
a2632 10
   if (theta == 90.0) {
      r = 0.0;
   } else if (theta > -90.0) {
      xi = D2R*(90.0 - theta)/2.0;
      if (xi < prj->w[4]) {
         r = xi*prj->w[3];
      } else {
         cxi = cosd((90.0 - theta)/2.0);
         txi = sqrt(1.0-cxi*cxi)/cxi;
         r = -prj->w[0]*(log(cxi)/txi + prj->w[1]*txi);
a2633 2
   } else {
      return 2;
d2636 82
a2717 2
   *x =  r*sind(phi);
   *y = -r*cosd(phi);
d2719 1
a2719 1
   return 0;
d2724 1
a2724 1
int airrev(x, y, prj, phi, theta)
a2725 1
const double x, y;
d2727 4
a2730 1
double *phi, *theta;
d2733 6
a2738 3
   int   j;
   double cxi, lambda, r, r1, r2, rt, txi, x1, x2, xi;
   const double tol = 1.0e-12;
d2740 1
d2745 11
a2755 1
   r = sqrt(x*x + y*y)/prj->w[0];
d2757 7
a2763 12
   if (r == 0.0) {
      xi = 0.0;
   } else if (r < prj->w[5]) {
      xi = r*prj->w[6];
   } else {
      /* Find a solution interval. */
      x1 = 1.0;
      r1 = 0.0;
      for (j = 0; j < 30; j++) {
         x2 = x1/2.0;
         txi = sqrt(1.0-x2*x2)/x2;
         r2 = -(log(x2)/txi + prj->w[1]*txi);
d2765 7
a2771 3
         if (r2 >= r) break;
         x1 = x2;
         r1 = r2;
d2773 1
a2773 1
      if (j == 30) return 2;
a2774 9
      for (j = 0; j < 100; j++) {
         /* Weighted division of the interval. */
         lambda = (r2-r)/(r2-r1);
         if (lambda < 0.1) {
            lambda = 0.1;
         } else if (lambda > 0.9) {
            lambda = 0.9;
         }
         cxi = x2 - lambda*(x2-x1);
d2776 7
a2782 2
         txi = sqrt(1.0-cxi*cxi)/cxi;
         rt = -(log(cxi)/txi + prj->w[1]*txi);
d2784 6
a2789 4
         if (rt < r) {
             if (r-rt < tol) break;
             r1 = rt;
             x1 = cxi;
d2791 3
a2793 3
             if (rt-r < tol) break;
             r2 = rt;
             x2 = cxi;
d2795 4
a2799 1
      if (j == 100) return 2;
d2801 5
a2805 7
      xi = acosd(cxi);
   }

   if (r == 0.0) {
      *phi = 0.0;
   } else {
      *phi = atan2d(x, -y);
a2806 1
   *theta = 90.0 - 2.0*xi;
d2808 1
a2808 1
   return 0;
d2815 1
a2815 1
*      prj->p[1]    Distance of point of projection from the centre of the
d2817 1
a2817 1
*      prj->p[2]    Radius of the cylinder of projection, lambda, in units of
d2821 3
a2823 1
*      prj->r0      r0; reset to 180/pi if 0.
d2826 1
d2828 2
a2829 3
*      prj->flag    CYP
*      prj->phi0    0.0
*      prj->theta0  0.0
d2834 2
a2835 2
*      prj->prjfwd  Pointer to cypfwd().
*      prj->prjrev  Pointer to cyprev().
d2843 1
d2845 10
a2854 3
   prj->flag   = CYP;
   prj->phi0   = 0.0;
   prj->theta0 = 0.0;
d2859 1
a2859 1
      prj->w[0] = prj->p[2];
d2866 1
a2866 1
      prj->w[2] = R2D*(prj->p[1] + prj->p[2]);
d2873 1
a2873 1
      prj->w[0] = prj->r0*prj->p[2]*D2R;
d2880 1
a2880 1
      prj->w[2] = prj->r0*(prj->p[1] + prj->p[2]);
d2888 2
a2889 2
   prj->prjfwd = cypfwd;
   prj->prjrev = cyprev;
d2891 1
a2891 1
   return 0;
d2896 1
a2896 1
int cypfwd(phi, theta, prj, x, y)
a2897 1
const double phi, theta;
d2899 4
a2902 1
double *x, *y;
d2905 6
a2910 1
   double s;
d2912 1
d2917 21
a2937 3
   s = prj->p[1] + cosd(theta);
   if (s == 0.0) {
         return 2;
d2939 2
d2942 7
a2948 2
   *x = prj->w[0]*phi;
   *y = prj->w[2]*sind(theta)/s;
d2950 6
d2961 1
a2961 1
int cyprev(x, y, prj, phi, theta)
a2962 1
const double x, y;
d2964 4
a2967 1
double *phi, *theta;
d2970 5
a2974 1
   double eta;
d2976 2
d2982 49
a3030 3
   *phi   = x*prj->w[1];
   eta    = y*prj->w[3];
   *theta = atan2d(eta,1.0) + asind(eta*prj->p[1]/sqrt(eta*eta+1.0));
d3032 1
a3032 1
   return 0;
d3039 1
a3039 1
*      prj->p[1]    Square of the cosine of the latitude at which the
d3043 3
a3045 1
*      prj->r0      r0; reset to 180/pi if 0.
d3048 1
d3050 2
a3051 3
*      prj->flag    CEA
*      prj->phi0    0.0
*      prj->theta0  0.0
d3056 2
a3057 2
*      prj->prjfwd  Pointer to ceafwd().
*      prj->prjrev  Pointer to cearev().
d3065 1
d3067 9
a3075 3
   prj->flag   = CEA;
   prj->phi0   = 0.0;
   prj->theta0 = 0.0;
d3081 1
a3081 1
      if (prj->p[1] <= 0.0 || prj->p[1] > 1.0) {
d3084 2
a3085 2
      prj->w[2] = prj->r0/prj->p[1];
      prj->w[3] = prj->p[1]/prj->r0;
d3089 1
a3089 1
      if (prj->p[1] <= 0.0 || prj->p[1] > 1.0) {
d3092 2
a3093 2
      prj->w[2] = prj->r0/prj->p[1];
      prj->w[3] = prj->p[1]/prj->r0;
d3096 2
a3097 2
   prj->prjfwd = ceafwd;
   prj->prjrev = cearev;
d3099 1
a3099 1
   return 0;
d3104 1
a3104 1
int ceafwd(phi, theta, prj, x, y)
a3105 1
const double phi, theta;
d3107 4
a3110 1
double *x, *y;
d3113 9
d3126 33
a3158 2
   *x = prj->w[0]*phi;
   *y = prj->w[2]*sind(theta);
d3160 20
a3179 1
   return 0;
d3184 1
a3184 1
int cearev(x, y, prj, phi, theta)
a3185 1
const double x, y;
d3187 4
a3190 1
double *phi, *theta;
d3193 6
a3198 2
   double s;
   const double tol = 1.0e-13;
d3200 1
d3205 21
a3225 4
   s = y*prj->w[3];
   if (fabs(s) > 1.0) {
      if (fabs(s) > 1.0+tol) {
         return 2;
a3226 1
      s = copysign(1.0,s);
d3229 13
a3241 2
   *phi   = x*prj->w[1];
   *theta = asind(s);
d3247 1
a3247 1
*   CAR: Cartesian projection.
d3250 3
a3252 1
*      prj->r0      r0; reset to 180/pi if 0.
d3255 1
d3257 2
a3258 3
*      prj->flag    CAR
*      prj->phi0    0.0
*      prj->theta0  0.0
d3261 2
a3262 2
*      prj->prjfwd  Pointer to carfwd().
*      prj->prjrev  Pointer to carrev().
d3270 1
d3272 7
a3278 3
   prj->flag   = CAR;
   prj->phi0   = 0.0;
   prj->theta0 = 0.0;
d3289 2
a3290 2
   prj->prjfwd = carfwd;
   prj->prjrev = carrev;
d3292 1
a3292 1
   return 0;
d3297 1
a3297 1
int carfwd(phi, theta, prj, x, y)
a3298 1
const double phi, theta;
d3300 4
a3303 1
double *x, *y;
d3306 8
d3318 9
a3326 2
   *x = prj->w[0]*phi;
   *y = prj->w[0]*theta;
d3328 28
d3361 1
a3361 1
int carrev(x, y, prj, phi, theta)
a3362 1
const double x, y;
d3364 4
a3367 1
double *phi, *theta;
d3370 8
d3382 24
a3405 2
   *phi   = prj->w[1]*x;
   *theta = prj->w[1]*y;
d3407 13
d3427 3
a3429 1
*      prj->r0      r0; reset to 180/pi if 0.
d3432 1
d3434 2
a3435 3
*      prj->flag    MER
*      prj->phi0    0.0
*      prj->theta0  0.0
d3438 2
a3439 2
*      prj->prjfwd  Pointer to merfwd().
*      prj->prjrev  Pointer to merrev().
d3447 1
d3449 7
a3455 3
   prj->flag   = MER;
   prj->phi0   = 0.0;
   prj->theta0 = 0.0;
d3466 2
a3467 2
   prj->prjfwd = merfwd;
   prj->prjrev = merrev;
d3469 1
a3469 1
   return 0;
d3474 1
a3474 1
int merfwd(phi, theta, prj, x, y)
a3475 1
const double phi, theta;
d3477 4
a3480 1
double *x, *y;
d3483 8
d3495 22
a3516 2
   if (theta <= -90.0 || theta >= 90.0) {
      return 2;
d3519 13
a3531 2
   *x = prj->w[0]*phi;
   *y = prj->r0*log(tand((90.0+theta)/2.0));
d3538 1
a3538 1
int merrev(x, y, prj, phi, theta)
a3539 1
const double x, y;
d3541 4
a3544 1
double *phi, *theta;
d3547 8
d3559 47
a3605 2
   *phi   = x*prj->w[1];
   *theta = 2.0*atand(exp(y/prj->r0)) - 90.0;
d3607 1
a3607 1
   return 0;
d3614 3
a3616 1
*      prj->r0      r0; reset to 180/pi if 0.
d3619 1
d3621 2
a3622 3
*      prj->flag    SFL
*      prj->phi0    0.0
*      prj->theta0  0.0
d3625 2
a3626 2
*      prj->prjfwd  Pointer to sflfwd().
*      prj->prjrev  Pointer to sflrev().
d3634 1
a3635 3
   prj->flag   = SFL;
   prj->phi0   = 0.0;
   prj->theta0 = 0.0;
d3637 7
d3653 2
a3654 2
   prj->prjfwd = sflfwd;
   prj->prjrev = sflrev;
d3656 1
a3656 1
   return 0;
d3661 1
a3661 1
int sflfwd(phi, theta, prj, x, y)
a3662 1
const double phi, theta;
d3664 4
a3667 1
double *x, *y;
d3670 8
d3682 50
a3731 2
   *x = prj->w[0]*phi*cosd(theta);
   *y = prj->w[0]*theta;
d3738 1
a3738 1
int sflrev(x, y, prj, phi, theta)
a3739 1
const double x, y;
d3741 4
a3744 1
double *phi, *theta;
d3747 5
a3751 1
   double w;
d3753 2
d3759 3
a3761 3
   w = cos(y/prj->r0);
   if (w == 0.0) {
      *phi = 0.0;
d3763 35
a3797 1
      *phi = x*prj->w[1]/cos(y/prj->r0);
a3798 1
   *theta = y*prj->w[1];
d3807 3
a3809 1
*      prj->r0      r0; reset to 180/pi if 0.
d3812 1
d3814 2
a3815 3
*      prj->flag    PAR
*      prj->phi0    0.0
*      prj->theta0  0.0
d3820 2
a3821 2
*      prj->prjfwd  Pointer to parfwd().
*      prj->prjrev  Pointer to parrev().
d3829 1
d3831 7
a3837 3
   prj->flag   = PAR;
   prj->phi0   = 0.0;
   prj->theta0 = 0.0;
d3852 2
a3853 2
   prj->prjfwd = parfwd;
   prj->prjrev = parrev;
d3855 1
a3855 1
   return 0;
d3860 1
a3860 1
int parfwd(phi, theta, prj, x, y)
a3861 1
const double phi, theta;
d3863 4
a3866 1
double *x, *y;
d3869 7
a3875 1
   double s;
d3877 1
d3882 31
a3912 3
   s = sind(theta/3.0);
   *x = prj->w[0]*phi*(1.0 - 4.0*s*s);
   *y = prj->w[2]*s;
d3914 43
a3956 1
   return 0;
d3961 1
a3961 1
int parrev(x, y, prj, phi, theta)
a3962 1
const double x, y;
d3964 4
a3967 1
double *phi, *theta;
d3970 6
a3975 1
   double s, t;
d3977 1
d3982 7
a3988 3
   s = y*prj->w[3];
   if (s > 1.0 || s < -1.0) {
      return 2;
d3991 12
a4002 6
   t = 1.0 - 4.0*s*s;
   if (t == 0.0) {
      if (x == 0.0) {
         *phi = 0.0;
      } else {
         return 2;
a4003 2
   } else {
      *phi = prj->w[1]*x/t;
d4006 17
a4022 1
   *theta = 3.0*asind(s);
d4031 3
a4033 1
*      prj->r0      r0; reset to 180/pi if 0.
d4036 1
d4038 2
a4039 3
*      prj->flag    MOL
*      prj->phi0    0.0
*      prj->theta0  0.0
d4044 2
a4045 2
*      prj->prjfwd  Pointer to molfwd().
*      prj->prjrev  Pointer to molrev().
d4053 1
a4054 3
   prj->flag   = MOL;
   prj->phi0   = 0.0;
   prj->theta0 = 0.0;
d4058 7
d4071 2
a4072 2
   prj->prjfwd = molfwd;
   prj->prjrev = molrev;
d4074 1
a4074 1
   return 0;
d4079 1
a4079 1
int molfwd(phi, theta, prj, x, y)
a4080 1
const double phi, theta;
d4082 4
a4085 1
double *x, *y;
d4088 7
a4094 3
   int   j;
   double gamma, resid, u, v, v0, v1;
   const double tol = 1.0e-13;
d4096 1
d4101 98
a4198 26
   if (fabs(theta) == 90.0) {
      *x = 0.0;
      *y = copysign(prj->w[0],theta);
   } else if (theta == 0.0) {
      *x = prj->w[1]*phi;
      *y = 0.0;
   } else {
      u  = PI*sind(theta);
      v0 = -PI;
      v1 =  PI;
      v  = u;
      for (j = 0; j < 100; j++) {
         resid = (v - u) + sin(v);
         if (resid < 0.0) {
            if (resid > -tol) break;
            v0 = v;
         } else {
            if (resid < tol) break;
            v1 = v;
         }
         v = (v0 + v1)/2.0;
      }

      gamma = v/2.0;
      *x = prj->w[1]*phi*cos(gamma);
      *y = prj->w[0]*sin(gamma);
d4201 1
a4201 1
   return 0;
d4206 1
a4206 1
int molrev(x, y, prj, phi, theta)
a4207 1
const double x, y;
d4209 4
a4212 1
double *phi, *theta;
d4215 7
a4221 2
   double s, y0, z;
   const double tol = 1.0e-12;
d4223 1
d4228 9
a4236 7
   y0 = y/prj->r0;
   s  = 2.0 - y0*y0;
   if (s <= tol) {
      if (s < -tol) {
         return 2;
      }
      s = 0.0;
d4238 11
a4248 2
      if (fabs(x) > tol) {
         return 2;
a4249 4
      *phi = 0.0;
   } else {
      s = sqrt(s);
      *phi = prj->w[3]*x/s;
d4252 33
a4284 4
   z = y*prj->w[2];
   if (fabs(z) > 1.0) {
      if (fabs(z) > 1.0+tol) {
         return 2;
a4285 4
      z = copysign(1.0,z) + y0*s/PI;
   } else {
      z = asin(z)*prj->w[4] + y0*s/PI;
   }
d4287 5
a4291 3
   if (fabs(z) > 1.0) {
      if (fabs(z) > 1.0+tol) {
         return 2;
a4292 1
      z = copysign(1.0,z);
a4294 2
   *theta = asind(z);

d4302 3
a4304 1
*      prj->r0      r0; reset to 180/pi if 0.
d4307 1
d4309 2
a4310 3
*      prj->flag    AIT
*      prj->phi0    0.0
*      prj->theta0  0.0
d4315 2
a4316 2
*      prj->prjfwd  Pointer to aitfwd().
*      prj->prjrev  Pointer to aitrev().
d4324 1
a4325 3
   prj->flag   = AIT;
   prj->phi0   = 0.0;
   prj->theta0 = 0.0;
d4329 7
d4341 2
a4342 2
   prj->prjfwd = aitfwd;
   prj->prjrev = aitrev;
d4344 1
a4344 1
   return 0;
d4349 1
a4349 1
int aitfwd(phi, theta, prj, x, y)
a4350 1
const double phi, theta;
d4352 4
a4355 1
double *x, *y;
d4358 6
a4363 1
   double cthe, w;
d4365 2
d4371 79
a4449 4
   cthe = cosd(theta);
   w = sqrt(prj->w[0]/(1.0 + cthe*cosd(phi/2.0)));
   *x = 2.0*w*cthe*sind(phi/2.0);
   *y = w*sind(theta);
d4451 1
a4451 1
   return 0;
d4456 1
a4456 1
int aitrev(x, y, prj, phi, theta)
a4457 1
const double x, y;
d4459 4
a4462 1
double *phi, *theta;
d4465 6
a4470 2
   double s, u, xp, yp, z;
   const double tol = 1.0e-13;
d4472 1
d4477 8
a4484 5
   u = 1.0 - x*x*prj->w[2] - y*y*prj->w[1];
   if (u < 0.0) {
      if (u < -tol) {
         return 2;
      }
a4485 2
      u = 0.0;
   }
d4487 16
a4502 5
   z = sqrt(u);
   s = z*y/prj->r0;
   if (fabs(s) > 1.0) {
      if (fabs(s) > 1.0+tol) {
         return 2;
a4503 1
      s = copysign(1.0,s);
d4506 16
a4521 6
   xp = 2.0*z*z - 1.0;
   yp = z*x*prj->w[3];
   if (xp == 0.0 && yp == 0.0) {
      *phi = 0.0;
   } else {
      *phi = 2.0*atan2d(yp, xp);
a4522 1
   *theta = asind(s);
d4531 2
a4532 2
*      prj->p[1]    sigma = (theta2+theta1)/2
*      prj->p[2]    delta = (theta2-theta1)/2, where theta1 and theta2 are the
d4536 3
a4538 2
*      prj->flag    COP, or -COP if prj->flag is given < 0.
*      prj->r0      r0; reset to 180/pi if 0.
d4541 1
d4543 2
a4544 2
*      prj->phi0     0.0
*      prj->theta0  sigma
d4551 2
a4552 2
*      prj->prjfwd  Pointer to copfwd().
*      prj->prjrev  Pointer to coprev().
d4560 1
a4561 3
   prj->flag   = copysign(COP, prj->flag);
   prj->phi0   = 0.0;
   prj->theta0 = prj->p[1];
d4563 4
d4569 8
a4576 1
   prj->w[0] = sind(prj->p[1]);
d4583 1
a4583 1
   prj->w[3] = prj->r0*cosd(prj->p[2]);
d4589 1
a4589 1
   prj->w[5] = 1.0/tand(prj->p[1]);
d4593 2
a4594 2
   prj->prjfwd = copfwd;
   prj->prjrev = coprev;
d4596 1
a4596 1
   return 0;
d4601 1
a4601 1
int copfwd(phi, theta, prj, x, y)
a4602 1
const double phi, theta;
d4604 4
a4607 1
double *x, *y;
d4610 5
a4614 1
   double a, r, s, t;
d4616 2
a4617 1
   if (abs(prj->flag) != COP) {
d4621 22
a4642 4
   t = theta - prj->p[1];
   s = cosd(t);
   if (s == 0.0) {
      return 2;
d4645 12
a4656 2
   a = prj->w[0]*phi;
   r = prj->w[2] - prj->w[3]*sind(t)/s;
d4658 8
a4665 2
   *x =             r*sind(a);
   *y = prj->w[2] - r*cosd(a);
d4667 4
a4670 2
   if (prj->flag > 0 && r*prj->w[0] < 0.0) {
      return 2;
d4678 1
a4678 1
int coprev(x, y, prj, phi, theta)
a4679 1
const double x, y;
d4681 4
a4684 1
double *phi, *theta;
d4687 5
a4691 1
   double a, dy, r;
d4693 2
a4694 1
   if (abs(prj->flag) != COP) {
d4698 31
a4728 3
   dy = prj->w[2] - y;
   r  = sqrt(x*x + dy*dy);
   if (prj->p[1] < 0.0) r = -r;
d4730 30
a4759 4
   if (r == 0.0) {
      a = 0.0;
   } else {
      a = atan2d(x/r, dy/r);
d4762 1
a4762 4
   *phi   = a*prj->w[1];
   *theta = prj->p[1] + atand(prj->w[5] - r*prj->w[4]);

   return 0;
d4769 2
a4770 2
*      prj->p[1]    sigma = (theta2+theta1)/2
*      prj->p[2]    delta = (theta2-theta1)/2, where theta1 and theta2 are the
d4774 3
a4776 1
*      prj->r0      r0; reset to 180/pi if 0.
d4779 1
d4781 2
a4782 3
*      prj->flag    COE
*      prj->phi0    0.0
*      prj->theta0  sigma
d4792 2
a4793 2
*      prj->prjfwd  Pointer to coefwd().
*      prj->prjrev  Pointer to coerev().
d4803 1
a4804 3
   prj->flag   = COE;
   prj->phi0   = 0.0;
   prj->theta0 = prj->p[1];
d4806 4
d4812 9
a4820 2
   theta1 = prj->p[1] - prj->p[2];
   theta2 = prj->p[1] + prj->p[2];
d4836 1
a4836 1
   prj->w[2] = prj->w[3]*sqrt(prj->w[4] - prj->w[5]*sind(prj->p[1]));
d4838 2
a4839 2
   prj->prjfwd = coefwd;
   prj->prjrev = coerev;
d4841 1
a4841 1
   return 0;
d4846 1
a4846 1
int coefwd(phi, theta, prj, x, y)
a4847 1
const double phi, theta;
d4849 4
a4852 1
double *x, *y;
d4855 6
a4860 1
   double a, r;
d4862 1
d4867 3
a4869 3
   a = phi*prj->w[0];
   if (theta == -90.0) {
      r = prj->w[8];
d4871 20
a4890 1
      r = prj->w[3]*sqrt(prj->w[4] - prj->w[5]*sind(theta));
d4893 47
a4939 2
   *x =             r*sind(a);
   *y = prj->w[2] - r*cosd(a);
d4941 1
a4941 1
   return 0;
d4946 1
a4946 1
int coerev(x, y, prj, phi, theta)
a4947 1
const double x, y;
d4949 4
a4952 1
double *phi, *theta;
d4955 5
a4959 2
   double a, dy, r, w;
   const double tol = 1.0e-12;
d4961 1
d4966 9
a4974 3
   dy = prj->w[2] - y;
   r  = sqrt(x*x + dy*dy);
   if (prj->p[1] < 0.0) r = -r;
d4976 17
a4992 4
   if (r == 0.0) {
      a = 0.0;
   } else {
      a = atan2d(x/r, dy/r);
d4995 10
a5004 13
   *phi = a*prj->w[1];
   if (fabs(r - prj->w[8]) < tol) {
      *theta = -90.0;
   } else {
      w = (prj->w[6] - r*r)*prj->w[7];
      if (fabs(w) > 1.0) {
         if (fabs(w-1.0) < tol) {
            *theta = 90.0;
         } else if (fabs(w+1.0) < tol) {
            *theta = -90.0;
         } else {
            return 2;
         }
d5006 7
a5012 1
         *theta = asind(w);
d5023 2
a5024 2
*      prj->p[1]    sigma = (theta2+theta1)/2
*      prj->p[2]    delta = (theta2-theta1)/2, where theta1 and theta2 are the
d5028 3
a5030 1
*      prj->r0      r0; reset to 180/pi if 0.
d5033 1
d5035 2
a5036 3
*      prj->flag    COD
*      prj->phi0    0.0
*      prj->theta0  sigma
d5041 2
a5042 2
*      prj->prjfwd  Pointer to codfwd().
*      prj->prjrev  Pointer to codrev().
d5050 1
a5051 3
   prj->flag   = COD;
   prj->phi0   = 0.0;
   prj->theta0 = prj->p[1];
d5053 4
d5059 9
a5067 2
   if (prj->p[2] == 0.0) {
      prj->w[0] = prj->r0*sind(prj->p[1])*D2R;
d5069 1
a5069 1
      prj->w[0] = prj->r0*sind(prj->p[1])*sind(prj->p[2])/prj->p[2];
d5077 2
a5078 2
   prj->w[2] = prj->r0*cosd(prj->p[2])*cosd(prj->p[1])/prj->w[0];
   prj->w[3] = prj->w[2] + prj->p[1];
d5080 2
a5081 2
   prj->prjfwd = codfwd;
   prj->prjrev = codrev;
d5083 1
a5083 1
   return 0;
d5088 1
a5088 1
int codfwd(phi, theta, prj, x, y)
a5089 1
const double phi, theta;
d5091 4
a5094 1
double *x, *y;
d5097 5
a5101 1
   double a, r;
d5103 1
d5108 39
a5146 2
   a = prj->w[0]*phi;
   r = prj->w[3] - theta;
d5148 11
a5158 2
   *x =             r*sind(a);
   *y = prj->w[2] - r*cosd(a);
d5165 1
a5165 1
int codrev(x, y, prj, phi, theta)
a5166 1
const double x, y;
d5168 4
a5171 1
double *phi, *theta;
d5174 5
a5178 1
   double a, dy, r;
d5180 1
d5185 9
a5193 3
   dy = prj->w[2] - y;
   r  = sqrt(x*x + dy*dy);
   if (prj->p[1] < 0.0) r = -r;
d5195 17
a5211 4
   if (r == 0.0) {
      a = 0.0;
   } else {
      a = atan2d(x/r, dy/r);
a5213 2
   *phi   = a*prj->w[1];
   *theta = prj->w[3] - r;
d5215 16
d5238 2
a5239 2
*      prj->p[1]    sigma = (theta2+theta1)/2
*      prj->p[2]    delta = (theta2-theta1)/2, where theta1 and theta2 are the
d5243 3
a5245 1
*      prj->r0      r0; reset to 180/pi if 0.
d5248 1
d5250 2
a5251 3
*      prj->flag    COO
*      prj->phi0    0.0
*      prj->theta0  sigma
d5259 2
a5260 2
*      prj->prjfwd  Pointer to coofwd().
*      prj->prjrev  Pointer to coorev().
d5270 1
a5271 3
   prj->flag   = COO;
   prj->phi0   = 0.0;
   prj->theta0 = prj->p[1];
d5273 4
d5279 6
a5284 2
   theta1 = prj->p[1] - prj->p[2];
   theta2 = prj->p[1] + prj->p[2];
d5286 3
d5309 1
a5309 1
   prj->w[2] = prj->w[3]*pow(tand((90.0 - prj->p[1])/2.0),prj->w[0]);
d5312 2
a5313 2
   prj->prjfwd = coofwd;
   prj->prjrev = coorev;
d5315 1
a5315 1
   return 0;
d5320 1
a5320 1
int coofwd(phi, theta, prj, x, y)
a5321 1
const double phi, theta;
d5323 4
a5326 1
double *x, *y;
d5329 5
a5333 1
   double a, r;
d5335 1
d5340 23
a5362 6
   a = prj->w[0]*phi;
   if (theta == -90.0) {
      if (prj->w[0] < 0.0) {
         r = 0.0;
      } else {
         return 2;
a5363 2
   } else {
      r = prj->w[3]*pow(tand((90.0 - theta)/2.0),prj->w[0]);
d5366 40
a5405 2
   *x =             r*sind(a);
   *y = prj->w[2] - r*cosd(a);
d5407 1
a5407 1
   return 0;
d5412 1
a5412 1
int coorev(x, y, prj, phi, theta)
a5413 1
const double x, y;
d5415 4
a5418 1
double *phi, *theta;
d5421 5
a5425 1
   double a, dy, r;
d5427 1
d5432 10
a5441 3
   dy = prj->w[2] - y;
   r  = sqrt(x*x + dy*dy);
   if (prj->p[1] < 0.0) r = -r;
d5443 18
a5460 4
   if (r == 0.0) {
      a = 0.0;
   } else {
      a = atan2d(x/r, dy/r);
d5463 16
a5478 4
   *phi = a*prj->w[1];
   if (r == 0.0) {
      if (prj->w[0] < 0.0) {
         *theta = -90.0;
d5480 7
a5486 1
         return 2;
a5487 2
   } else {
      *theta = 90.0 - 2.0*atand(pow(r*prj->w[4],prj->w[1]));
d5490 1
a5490 1
   return 0;
d5497 1
a5497 1
*      prj->p[1]    Bonne conformal latitude, theta1, in degrees.
d5500 3
a5502 1
*      prj->r0      r0; reset to 180/pi if 0.
d5505 1
d5507 2
a5508 3
*      prj->flag    BON
*      prj->phi0    0.0
*      prj->theta0  0.0
d5511 2
a5512 2
*      prj->prjfwd  Pointer to bonfwd().
*      prj->prjrev  Pointer to bonrev().
d5520 1
d5522 4
a5525 3
   prj->flag   = BON;
   prj->phi0   = 0.0;
   prj->theta0 = 0.0;
d5527 7
d5537 1
a5537 1
      prj->w[2] = prj->r0*cosd(prj->p[1])/sind(prj->p[1]) + prj->p[1];
d5540 2
a5541 1
      prj->w[2] = prj->r0*(cosd(prj->p[1])/sind(prj->p[1]) + prj->p[1]*D2R);
d5544 2
a5545 2
   prj->prjfwd = bonfwd;
   prj->prjrev = bonrev;
d5547 1
a5547 1
   return 0;
d5552 1
a5552 1
int bonfwd(phi, theta, prj, x, y)
a5553 1
const double phi, theta;
d5555 4
a5558 1
double *x, *y;
d5561 5
a5565 1
   double a, r;
d5567 3
a5569 1
   if (prj->p[1] == 0.0) {
d5571 1
a5571 1
      return sflfwd(phi, theta, prj, x, y);
d5578 39
a5616 2
   r = prj->w[2] - theta*prj->w[1];
   a = prj->r0*phi*cosd(theta)/r;
d5618 13
a5630 2
   *x =             r*sind(a);
   *y = prj->w[2] - r*cosd(a);
d5632 6
d5643 1
a5643 1
int bonrev(x, y, prj, phi, theta)
a5644 1
const double x, y;
d5646 4
a5649 1
double *phi, *theta;
d5652 5
a5656 1
   double a, cthe, dy, r;
d5658 2
a5659 1
   if (prj->p[1] == 0.0) {
d5661 1
a5661 1
      return sflrev(x, y, prj, phi, theta);
d5668 11
a5678 3
   dy = prj->w[2] - y;
   r = sqrt(x*x + dy*dy);
   if (prj->p[1] < 0.0) r = -r;
d5680 12
a5691 4
   if (r == 0.0) {
      a = 0.0;
   } else {
      a = atan2d(x/r, dy/r);
d5694 16
a5709 6
   *theta = (prj->w[2] - r)/prj->w[1];
   cthe = cosd(*theta);
   if (cthe == 0.0) {
      *phi = 0.0;
   } else {
      *phi = a*(r/prj->r0)/cthe;
d5719 3
a5721 1
*      prj->r0      r0; reset to 180/pi if 0.
d5724 1
d5726 2
a5727 3
*      prj->flag    PCO
*      prj->phi0    0.0
*      prj->theta0  0.0
d5731 2
a5732 2
*      prj->prjfwd  Pointer to pcofwd().
*      prj->prjrev  Pointer to pcorev().
d5740 1
a5741 3
   prj->flag   = PCO;
   prj->phi0   = 0.0;
   prj->theta0 = 0.0;
d5743 7
d5761 2
a5762 2
   prj->prjfwd = pcofwd;
   prj->prjrev = pcorev;
d5764 1
a5764 1
   return 0;
d5769 1
a5769 1
int pcofwd(phi, theta, prj, x, y)
a5770 1
const double phi, theta;
d5772 4
a5775 1
double *x, *y;
d5778 7
a5784 1
   double a, cthe, cotthe, sthe;
d5786 2
d5792 106
a5897 11
   cthe = cosd(theta);
   sthe = sind(theta);
   a = phi*sthe;

   if (sthe == 0.0) {
      *x = prj->w[0]*phi;
      *y = 0.0;
   } else {
      cotthe = cthe/sthe;
      *x = prj->r0*cotthe*sind(a);
      *y = prj->r0*(cotthe*(1.0 - cosd(a)) + theta*D2R);
d5905 1
a5905 1
int pcorev(x, y, prj, phi, theta)
a5906 1
const double x, y;
d5908 4
a5911 1
double *phi, *theta;
d5914 5
a5918 3
   int   j;
   double f, fneg, fpos, lambda, tanthe, theneg, thepos, w, xp, xx, ymthe, yp;
   const double tol = 1.0e-12;
d5920 1
d5925 8
a5932 15
   w = fabs(y*prj->w[1]);
   if (w < tol) {
      *phi = x*prj->w[1];
      *theta = 0.0;
   } else if (fabs(w-90.0) < tol) {
      *phi = 0.0;
      *theta = copysign(90.0,y);
   } else {
      /* Iterative solution using weighted division of the interval. */
      if (y > 0.0) {
         thepos =  90.0;
      } else {
         thepos = -90.0;
      }
      theneg = 0.0;
a5933 4
      xx = x*x;
      ymthe = y - prj->w[0]*thepos;
      fpos = xx + ymthe*ymthe;
      fneg = -999.0;
d5935 11
a5945 19
      for (j = 0; j < 64; j++) {
         if (fneg < -100.0) {
            /* Equal division of the interval. */
            *theta = (thepos+theneg)/2.0;
         } else {
            /* Weighted division of the interval. */
            lambda = fpos/(fpos-fneg);
            if (lambda < 0.1) {
               lambda = 0.1;
            } else if (lambda > 0.9) {
               lambda = 0.9;
            }
            *theta = thepos - lambda*(thepos-theneg);
         }

         /* Compute the residue. */
         ymthe = y - prj->w[0]*(*theta);
         tanthe = tand(*theta);
         f = xx + ymthe*(ymthe - prj->w[2]/tanthe);
a5946 3
         /* Check for convergence. */
         if (fabs(f) < tol) break;
         if (fabs(thepos-theneg) < tol) break;
d5948 14
a5961 4
         /* Redefine the interval. */
         if (f > 0.0) {
            thepos = *theta;
            fpos = f;
d5963 4
a5966 2
            theneg = *theta;
            fneg = f;
a5967 1
      }
d5969 1
a5969 6
      xp = prj->r0 - ymthe*tanthe;
      yp = x*tanthe;
      if (xp == 0.0 && yp == 0.0) {
         *phi = 0.0;
      } else {
         *phi = atan2d(yp, xp)/sind(*theta);
d5980 3
a5982 1
*      prj->r0      r0; reset to 180/pi if 0.
d5985 1
d5987 2
a5988 3
*      prj->flag    TSC
*      prj->phi0    0.0
*      prj->theta0  0.0
d5991 2
a5992 2
*      prj->prjfwd  Pointer to tscfwd().
*      prj->prjrev  Pointer to tscrev().
d6000 1
d6002 7
a6008 3
   prj->flag   = TSC;
   prj->phi0   = 0.0;
   prj->theta0 = 0.0;
d6019 2
a6020 2
   prj->prjfwd = tscfwd;
   prj->prjrev = tscrev;
d6022 1
a6022 1
   return 0;
d6027 1
a6027 1
int tscfwd(phi, theta, prj, x, y)
a6028 1
const double phi, theta;
d6030 4
a6033 1
double *x, *y;
d6036 6
a6041 3
   int   face;
   double cthe, l, m, n, rho, x0, xf, y0, yf;
   const double tol = 1.0e-12;
d6043 1
d6048 23
a6070 69
   cthe = cosd(theta);
   l = cthe*cosd(phi);
   m = cthe*sind(phi);
   n = sind(theta);

   face = 0;
   rho  = n;
   if (l > rho) {
      face = 1;
      rho  = l;
   }
   if (m > rho) {
      face = 2;
      rho  = m;
   }
   if (-l > rho) {
      face = 3;
      rho  = -l;
   }
   if (-m > rho) {
      face = 4;
      rho  = -m;
   }
   if (-n > rho) {
      face = 5;
      rho  = -n;
   }

   if (face == 0) {
      xf =  m/rho;
      yf = -l/rho;
      x0 =  0.0;
      y0 =  2.0;
   } else if (face == 1) {
      xf =  m/rho;
      yf =  n/rho;
      x0 =  0.0;
      y0 =  0.0;
   } else if (face == 2) {
      xf = -l/rho;
      yf =  n/rho;
      x0 =  2.0;
      y0 =  0.0;
   } else if (face == 3) {
      xf = -m/rho;
      yf =  n/rho;
      x0 =  4.0;
      y0 =  0.0;
   } else if (face == 4) {
      xf =  l/rho;
      yf =  n/rho;
      x0 =  6.0;
      y0 =  0.0;
   } else if (face == 5) {
      xf =  m/rho;
      yf =  l/rho;
      x0 =  0.0;
      y0 = -2.0;
   }

   if (fabs(xf) > 1.0) {
      if (fabs(xf) > 1.0+tol) {
         return 2;
      }
      xf = copysign(1.0,xf);
   }
   if (fabs(yf) > 1.0) {
      if (fabs(yf) > 1.0+tol) {
         return 2;
a6071 1
      yf = copysign(1.0,yf);
d6074 82
a6155 2
   *x = prj->w[0]*(xf + x0);
   *y = prj->w[0]*(yf + y0);
d6157 1
a6157 1
   return 0;
d6162 1
a6162 1
int tscrev(x, y, prj, phi, theta)
a6163 1
const double x, y;
d6165 4
a6168 1
double *phi, *theta;
d6171 7
a6177 1
   double l, m, n, xf, yf;
d6179 1
d6184 107
a6290 2
   xf = x*prj->w[1];
   yf = y*prj->w[1];
d6292 15
a6306 48
   /* Check bounds. */
   if (fabs(xf) <= 1.0) {
      if (fabs(yf) > 3.0) return 2;
   } else {
      if (fabs(xf) > 7.0) return 2;
      if (fabs(yf) > 1.0) return 2;
   }

   /* Map negative faces to the other side. */
   if (xf < -1.0) xf += 8.0;

   /* Determine the face. */
   if (xf > 5.0) {
      /* face = 4 */
      xf = xf - 6.0;
      m  = -1.0/sqrt(1.0 + xf*xf + yf*yf);
      l  = -m*xf;
      n  = -m*yf;
   } else if (xf > 3.0) {
      /* face = 3 */
      xf = xf - 4.0;
      l  = -1.0/sqrt(1.0 + xf*xf + yf*yf);
      m  =  l*xf;
      n  = -l*yf;
   } else if (xf > 1.0) {
      /* face = 2 */
      xf = xf - 2.0;
      m  =  1.0/sqrt(1.0 + xf*xf + yf*yf);
      l  = -m*xf;
      n  =  m*yf;
   } else if (yf > 1.0) {
      /* face = 0 */
      yf = yf - 2.0;
      n  = 1.0/sqrt(1.0 + xf*xf + yf*yf);
      l  = -n*yf;
      m  =  n*xf;
   } else if (yf < -1.0) {
      /* face = 5 */
      yf = yf + 2.0;
      n  = -1.0/sqrt(1.0 + xf*xf + yf*yf);
      l  = -n*yf;
      m  = -n*xf;
   } else {
      /* face = 1 */
      l  =  1.0/sqrt(1.0 + xf*xf + yf*yf);
      m  =  l*xf;
      n  =  l*yf;
   }
d6308 4
a6311 4
   if (l == 0.0 && m == 0.0) {
      *phi = 0.0;
   } else {
      *phi = atan2d(m, l);
a6312 1
   *theta = asind(n);
d6314 1
a6314 1
   return 0;
d6321 3
a6323 1
*      prj->r0      r0; reset to 180/pi if 0.
d6326 1
d6328 2
a6329 3
*      prj->flag    CSC
*      prj->phi0    0.0
*      prj->theta0  0.0
d6332 2
a6333 2
*      prj->prjfwd  Pointer to cscfwd().
*      prj->prjrev  Pointer to cscrev().
d6341 1
a6342 3
   prj->flag   = CSC;
   prj->phi0   = 0.0;
   prj->theta0 = 0.0;
d6344 7
d6360 2
a6361 2
   prj->prjfwd = cscfwd;
   prj->prjrev = cscrev;
d6363 1
a6363 1
   return 0;
d6368 1
a6368 1
int cscfwd(phi, theta, prj, x, y)
a6369 1
const double phi, theta;
d6371 4
a6374 1
double *x, *y;
d6377 5
a6381 118
   int   face;
   double cthe, eta, l, m, n, rho, xi;
   const float tol = 1.0e-7;

   float a, a2, a2b2, a4, ab, b, b2, b4, ca2, cb2, x0, xf, y0, yf;
   const float gstar  =  1.37484847732;
   const float mm     =  0.004869491981;
   const float gamma  = -0.13161671474;
   const float omega1 = -0.159596235474;
   const float d0  =  0.0759196200467;
   const float d1  = -0.0217762490699;
   const float c00 =  0.141189631152;
   const float c10 =  0.0809701286525;
   const float c01 = -0.281528535557;
   const float c11 =  0.15384112876;
   const float c20 = -0.178251207466;
   const float c02 =  0.106959469314;

   if (prj->flag != CSC) {
      if (cscset(prj)) return 1;
   }

   cthe = cosd(theta);
   l = cthe*cosd(phi);
   m = cthe*sind(phi);
   n = sind(theta);

   face = 0;
   rho  = n;
   if (l > rho) {
      face = 1;
      rho  = l;
   }
   if (m > rho) {
      face = 2;
      rho  = m;
   }
   if (-l > rho) {
      face = 3;
      rho  = -l;
   }
   if (-m > rho) {
      face = 4;
      rho  = -m;
   }
   if (-n > rho) {
      face = 5;
      rho  = -n;
   }

   if (face == 0) {
      xi  =  m;
      eta = -l;
      x0  =  0.0;
      y0  =  2.0;
   } else if (face == 1) {
      xi  =  m;
      eta =  n;
      x0  =  0.0;
      y0  =  0.0;
   } else if (face == 2) {
      xi  = -l;
      eta =  n;
      x0  =  2.0;
      y0  =  0.0;
   } else if (face == 3) {
      xi  = -m;
      eta =  n;
      x0  =  4.0;
      y0  =  0.0;
   } else if (face == 4) {
      xi  =  l;
      eta =  n;
      x0  =  6.0;
      y0  =  0.0;
   } else if (face == 5) {
      xi  =  m;
      eta =  l;
      x0  =  0.0;
      y0  = -2.0;
   }

   a =  xi/rho;
   b = eta/rho;

   a2 = a*a;
   b2 = b*b;
   ca2 = 1.0 - a2;
   cb2 = 1.0 - b2;

   /* Avoid floating underflows. */
   ab   = fabs(a*b);
   a4   = (a2 > 1.0e-16) ? a2*a2 : 0.0;
   b4   = (b2 > 1.0e-16) ? b2*b2 : 0.0;
   a2b2 = (ab > 1.0e-16) ? a2*b2 : 0.0;

   xf = a*(a2 + ca2*(gstar + b2*(gamma*ca2 + mm*a2 +
          cb2*(c00 + c10*a2 + c01*b2 + c11*a2b2 + c20*a4 + c02*b4)) +
          a2*(omega1 - ca2*(d0 + d1*a2))));
   yf = b*(b2 + cb2*(gstar + a2*(gamma*cb2 + mm*b2 +
          ca2*(c00 + c10*b2 + c01*a2 + c11*a2b2 + c20*b4 + c02*a4)) +
          b2*(omega1 - cb2*(d0 + d1*b2))));

   if (fabs(xf) > 1.0) {
      if (fabs(xf) > 1.0+tol) {
         return 2;
      }
      xf = copysign(1.0,xf);
   }
   if (fabs(yf) > 1.0) {
      if (fabs(yf) > 1.0+tol) {
         return 2;
      }
      yf = copysign(1.0,yf);
   }

   *x = prj->w[0]*(x0 + xf);
   *y = prj->w[0]*(y0 + yf);
a6382 14
   return 0;
}

/*--------------------------------------------------------------------------*/

int cscrev(x, y, prj, phi, theta)

const double x, y;
struct prjprm *prj;
double *phi, *theta;

{
   int   face;
   double l, m, n;
d6384 1
d6419 191
a6609 2
   xf = x*prj->w[1];
   yf = y*prj->w[1];
d6611 28
a6638 80
   /* Check bounds. */
   if (fabs(xf) <= 1.0) {
      if (fabs(yf) > 3.0) return 2;
   } else {
      if (fabs(xf) > 7.0) return 2;
      if (fabs(yf) > 1.0) return 2;
   }

   /* Map negative faces to the other side. */
   if (xf < -1.0) xf += 8.0;

   /* Determine the face. */
   if (xf > 5.0) {
      face = 4;
      xf = xf - 6.0;
   } else if (xf > 3.0) {
      face = 3;
      xf = xf - 4.0;
   } else if (xf > 1.0) {
      face = 2;
      xf = xf - 2.0;
   } else if (yf > 1.0) {
      face = 0;
      yf = yf - 2.0;
   } else if (yf < -1.0) {
      face = 5;
      yf = yf + 2.0;
   } else {
      face = 1;
   }

   xx  =  xf*xf;
   yy  =  yf*yf;

   z0 = p00 + xx*(p10 + xx*(p20 + xx*(p30 + xx*(p40 + xx*(p50 + xx*(p60))))));
   z1 = p01 + xx*(p11 + xx*(p21 + xx*(p31 + xx*(p41 + xx*(p51)))));
   z2 = p02 + xx*(p12 + xx*(p22 + xx*(p32 + xx*(p42))));
   z3 = p03 + xx*(p13 + xx*(p23 + xx*(p33)));
   z4 = p04 + xx*(p14 + xx*(p24));
   z5 = p05 + xx*(p15);
   z6 = p06;

   a = z0 + yy*(z1 + yy*(z2 + yy*(z3 + yy*(z4 + yy*(z5 + yy*z6)))));
   a = xf + xf*(1.0 - xx)*a;

   z0 = p00 + yy*(p10 + yy*(p20 + yy*(p30 + yy*(p40 + yy*(p50 + yy*(p60))))));
   z1 = p01 + yy*(p11 + yy*(p21 + yy*(p31 + yy*(p41 + yy*(p51)))));
   z2 = p02 + yy*(p12 + yy*(p22 + yy*(p32 + yy*(p42))));
   z3 = p03 + yy*(p13 + yy*(p23 + yy*(p33)));
   z4 = p04 + yy*(p14 + yy*(p24));
   z5 = p05 + yy*(p15);
   z6 = p06;

   b = z0 + xx*(z1 + xx*(z2 + xx*(z3 + xx*(z4 + xx*(z5 + xx*z6)))));
   b = yf + yf*(1.0 - yy)*b;

   if (face == 0) {
      n =  1.0/sqrt(a*a + b*b + 1.0);
      l = -b*n;
      m =  a*n;
   } else if (face == 1) {
      l =  1.0/sqrt(a*a + b*b + 1.0);
      m =  a*l;
      n =  b*l;
   } else if (face == 2) {
      m =  1.0/sqrt(a*a + b*b + 1.0);
      l = -a*m;
      n =  b*m;
   } else if (face == 3) {
      l = -1.0/sqrt(a*a + b*b + 1.0);
      m =  a*l;
      n = -b*l;
   } else if (face == 4) {
      m = -1.0/sqrt(a*a + b*b + 1.0);
      l = -a*m;
      n = -b*m;
   } else if (face == 5) {
      n = -1.0/sqrt(a*a + b*b + 1.0);
      l = -b*n;
      m = -a*n;
d6641 119
a6759 4
   if (l == 0.0 && m == 0.0) {
      *phi = 0.0;
   } else {
      *phi = atan2d(m, l);
a6760 1
   *theta = asind(n);
d6762 1
a6762 1
   return 0;
d6769 3
a6771 1
*      prj->r0      r0; reset to 180/pi if 0.
d6774 1
d6776 2
a6777 3
*      prj->flag    QSC
*      prj->phi0    0.0
*      prj->theta0  0.0
d6780 2
a6781 2
*      prj->prjfwd  Pointer to qscfwd().
*      prj->prjrev  Pointer to qscrev().
d6789 1
d6791 7
a6797 3
   prj->flag   = QSC;
   prj->phi0   = 0.0;
   prj->theta0 = 0.0;
d6808 2
a6809 2
   prj->prjfwd = qscfwd;
   prj->prjrev = qscrev;
d6811 1
a6811 1
   return 0;
d6816 1
a6816 1
int qscfwd(phi, theta, prj, x, y)
a6817 1
const double phi, theta;
d6819 4
a6822 1
double *x, *y;
d6825 2
a6826 2
   int   face;
   double cthe, eta, l, m, n, omega, p, rho, rhu, t, tau, x0, xf, xi, y0, yf;
d6828 4
d6833 1
d6838 23
a6860 145
   if (fabs(theta) == 90.0) {
      *x = 0.0;
      *y = copysign(2.0*prj->w[0],theta);
      return 0;
   }

   cthe = cosd(theta);
   l = cthe*cosd(phi);
   m = cthe*sind(phi);
   n = sind(theta);

   face = 0;
   rho  = n;
   if (l > rho) {
      face = 1;
      rho  = l;
   }
   if (m > rho) {
      face = 2;
      rho  = m;
   }
   if (-l > rho) {
      face = 3;
      rho  = -l;
   }
   if (-m > rho) {
      face = 4;
      rho  = -m;
   }
   if (-n > rho) {
      face = 5;
      rho  = -n;
   }

   rhu = 1.0 - rho;

   if (face == 0) {
      xi  =  m;
      eta = -l;
      if (rhu < 1.0e-8) {
         /* Small angle formula. */
         t = (90.0 - theta)*D2R;
         rhu = t*t/2.0;
      }
      x0  =  0.0;
      y0  =  2.0;
   } else if (face == 1) {
      xi  =  m;
      eta =  n;
      if (rhu < 1.0e-8) {
         /* Small angle formula. */
         t = theta*D2R;
         p = fmod(phi,360.0);
         if (p < -180.0) p += 360.0;
         if (p >  180.0) p -= 360.0;
         p *= D2R;
         rhu = (p*p + t*t)/2.0;
      }
      x0  =  0.0;
      y0  =  0.0;
   } else if (face == 2) {
      xi  = -l;
      eta =  n;
      if (rhu < 1.0e-8) {
         /* Small angle formula. */
         t = theta*D2R;
         p = fmod(phi,360.0);
         if (p < -180.0) p += 360.0;
         p = (90.0 - p)*D2R;
         rhu = (p*p + t*t)/2.0;
      }
      x0  =  2.0;
      y0  =  0.0;
   } else if (face == 3) {
      xi  = -m;
      eta =  n;
      if (rhu < 1.0e-8) {
         /* Small angle formula. */
         t = theta*D2R;
         p = fmod(phi,360.0);
         if (p < 0.0) p += 360.0;
         p = (180.0 - p)*D2R;
         rhu = (p*p + t*t)/2.0;
      }
      x0  =  4.0;
      y0  =  0.0;
   } else if (face == 4) {
      xi  =  l;
      eta =  n;
      if (rhu < 1.0e-8) {
         /* Small angle formula. */
         t = theta*D2R;
         p = fmod(phi,360.0);
         if (p > 180.0) p -= 360.0;
         p *= (90.0 + p)*D2R;
         rhu = (p*p + t*t)/2.0;
      }
      x0  =  6;
      y0  =  0.0;
   } else if (face == 5) {
      xi  =  m;
      eta =  l;
      if (rhu < 1.0e-8) {
         /* Small angle formula. */
         t = (90.0 + theta)*D2R;
         rhu = t*t/2.0;
      }
      x0  =  0.0;
      y0  = -2;
   }

   if (xi == 0.0 && eta == 0.0) {
      xf  = 0.0;
      yf  = 0.0;
   } else if (-xi >= fabs(eta)) {
      omega = eta/xi;
      tau = 1.0 + omega*omega;
      xf  = -sqrt(rhu/(1.0-1.0/sqrt(1.0+tau)));
      yf  = (xf/15.0)*(atand(omega) - asind(omega/sqrt(tau+tau)));
   } else if (xi >= fabs(eta)) {
      omega = eta/xi;
      tau = 1.0 + omega*omega;
      xf  =  sqrt(rhu/(1.0-1.0/sqrt(1.0+tau)));
      yf  = (xf/15.0)*(atand(omega) - asind(omega/sqrt(tau+tau)));
   } else if (-eta > fabs(xi)) {
      omega = xi/eta;
      tau = 1.0 + omega*omega;
      yf  = -sqrt(rhu/(1.0-1.0/sqrt(1.0+tau)));
      xf  = (yf/15.0)*(atand(omega) - asind(omega/sqrt(tau+tau)));
   } else if (eta > fabs(xi)) {
      omega = xi/eta;
      tau = 1.0 + omega*omega;
      yf  =  sqrt(rhu/(1.0-1.0/sqrt(1.0+tau)));
      xf  = (yf/15.0)*(atand(omega) - asind(omega/sqrt(tau+tau)));
   }

   if (fabs(xf) > 1.0) {
      if (fabs(xf) > 1.0+tol) {
         return 2;
      }
      xf = copysign(1.0,xf);
   }
   if (fabs(yf) > 1.0) {
      if (fabs(yf) > 1.0+tol) {
         return 2;
a6861 1
      yf = copysign(1.0,yf);
d6864 180
a7043 2
   *x = prj->w[0]*(xf + x0);
   *y = prj->w[0]*(yf + y0);
d7045 4
d7050 1
a7050 1
   return 0;
d7055 1
a7055 1
int qscrev(x, y, prj, phi, theta)
a7056 1
const double x, y;
d7058 4
a7061 1
double *phi, *theta;
d7064 3
a7066 2
   int   direct, face;
   double l, m, n, omega, rho, rhu, tau, xf, yf, w;
d7068 5
d7078 27
a7104 60
   xf = x*prj->w[1];
   yf = y*prj->w[1];

   /* Check bounds. */
   if (fabs(xf) <= 1.0) {
      if (fabs(yf) > 3.0) return 2;
   } else {
      if (fabs(xf) > 7.0) return 2;
      if (fabs(yf) > 1.0) return 2;
   }

   /* Map negative faces to the other side. */
   if (xf < -1.0) xf += 8.0;

   /* Determine the face. */
   if (xf > 5.0) {
      face = 4;
      xf = xf - 6.0;
   } else if (xf > 3.0) {
      face = 3;
      xf = xf - 4.0;
   } else if (xf > 1.0) {
      face = 2;
      xf = xf - 2.0;
   } else if (yf > 1.0) {
      face = 0;
      yf = yf - 2.0;
   } else if (yf < -1.0) {
      face = 5;
      yf = yf + 2.0;
   } else {
      face = 1;
   }

   direct = (fabs(xf) > fabs(yf));
   if (direct) {
      if (xf == 0.0) {
         omega = 0.0;
         tau = 1.0;
         rho = 1.0;
         rhu = 0.0;
      } else {
         w = 15.0*yf/xf;
         omega = sind(w)/(cosd(w) - SQRT2INV);
         tau = 1.0 + omega*omega;
         rhu = xf*xf*(1.0 - 1.0/sqrt(1.0 + tau));
         rho = 1.0 - rhu;
      }
   } else {
      if (yf == 0.0) {
         omega = 0.0;
         tau = 1.0;
         rho = 1.0;
         rhu = 0.0;
      } else {
         w = 15.0*xf/yf;
         omega = sind(w)/(cosd(w) - SQRT2INV);
         tau = 1.0 + omega*omega;
         rhu = yf*yf*(1.0 - 1.0/sqrt(1.0 + tau));
         rho = 1.0 - rhu;
d7108 147
a7254 4
   if (rho < -1.0) {
      if (rho < -1.0-tol) {
         return 2;
      }
d7256 15
a7270 6
      rho = -1.0;
      rhu =  2.0;
      w   =  0.0;
   } else {
      w = sqrt(rhu*(2.0-rhu)/tau);
   }
d7272 3
a7274 65
   if (face == 0) {
      n = rho;
      if (direct) {
         m = w;
         if (xf < 0.0) m = -m;
         l = -m*omega;
      } else {
         l = w;
         if (yf > 0.0) l = -l;
         m = -l*omega;
      }
   } else if (face == 1) {
      l = rho;
      if (direct) {
         m = w;
         if (xf < 0.0) m = -m;
         n = m*omega;
      } else {
         n = w;
         if (yf < 0.0) n = -n;
         m = n*omega;
      }
   } else if (face == 2) {
      m = rho;
      if (direct) {
         l = w;
         if (xf > 0.0) l = -l;
         n = -l*omega;
      } else {
         n = w;
         if (yf < 0.0) n = -n;
         l = -n*omega;
      }
   } else if (face == 3) {
      l = -rho;
      if (direct) {
         m = w;
         if (xf > 0.0) m = -m;
         n = -m*omega;
      } else {
         n = w;
         if (yf < 0.0) n = -n;
         m = -n*omega;
      }
   } else if (face == 4) {
      m = -rho;
      if (direct) {
         l = w;
         if (xf < 0.0) l = -l;
         n = l*omega;
      } else {
         n = w;
         if (yf < 0.0) n = -n;
         l = n*omega;
      }
   } else if (face == 5) {
      n = -rho;
      if (direct) {
         m = w;
         if (xf < 0.0) m = -m;
         l = m*omega;
      } else {
         l = w;
         if (yf < 0.0) l = -l;
         m = l*omega;
d7278 1
a7278 8
   if (l == 0.0 && m == 0.0) {
      *phi = 0.0;
   } else {
      *phi = atan2d(m, l);
   }
   *theta = asind(n);

   return 0;
@


2.19
log
@Generalized AZP to support the tilt parameter, gamma; added support for the
SZP projection with szpset(), szpfwd() and szprev(); initialize phi0 in the
setup routines; revised usage of the SIN parameters to accord with changes
to the paper and likewise renamed some variables.
@
text
@d4 1
a4 1
*   Copyright (C) 1995-2001, Mark Calabretta
d232 1
a232 1
*   $Id: proj.c,v 2.18 2000/12/06 00:56:16 mcalabre Exp mcalabre $
@


2.18
log
@Provide driver routines prjset(), prjfwd() & prjrev() which use the pointer
to function now included in the prjprm struct; the value of prjprm.flag is
now specific to each projection type; the projection initialization routines
now set the code, theta0, prjfwd and prjrev elements of the prjprm struct;
renamed glsset(), glsfwd() & glsrev() to sflset(), sflfwd() & sflrev();
reordered projections to match paper.
@
text
@d4 1
a4 1
*   Copyright (C) 1995-2000, Mark Calabretta
d45 1
d163 1
a163 1
*         checking for the AZP, TAN, SIN, ZPN, and COP projections.
d184 2
a185 2
*      double theta0
*         Native latitude of the reference point, in degrees.
d210 6
a215 5
*      to division by zero).  The forward routines for AZP, TAN, SIN, ZPN, and
*      COP also return error 2 if (phi,theta) corresponds to the overlapped
*      (far) side of the projection but also return the corresponding value of
*      (x,y).  This strict bounds checking may be relaxed by setting prj->flag
*      to -1 (rather than 0) when these projections are initialized.
d232 1
a232 1
*   $Id: proj.c,v 2.18 2000/12/05 04:02:24 mcalabre Exp mcalabre $
d240 5
a244 5
int  npcode = 25;
char pcodes[25][4] =
      {"AZP", "TAN", "STG", "SIN", "ARC", "ZPN", "ZEA", "AIR", "CYP", "CEA",
       "CAR", "MER", "COP", "COE", "COD", "COO", "SFL", "PAR", "MOL", "AIT",
       "BON", "PCO", "TSC", "CSC", "QSC"};
d247 8
a254 7
const int TAN = 102;
const int STG = 103;
const int SIN = 104;
const int ARC = 105;
const int ZPN = 106;
const int ZEA = 107;
const int AIR = 108;
d306 2
d392 2
a393 1
*      prj->p[1]    AZP distance parameter, mu in units of r0.
d396 1
d401 1
d404 7
a410 3
*      prj->w[1]    1/prj->w[0]
*      prj->w[2]    Boundary parameter, -mu    for |mu| <= 1,
*                                       -1/mu  for |mu| >= 1.
d421 2
d432 11
a442 3
   prj->w[1] = 1.0/prj->w[0];
   if (fabs(prj->p[1]) <= 1.0) {
      prj->w[2] = -prj->p[1];
d444 1
a444 1
      prj->w[2] = -1.0/prj->p[1];
d447 3
a452 6
   if (prj->flag == -1) {
      prj->flag = -AZP;
   } else {
      prj->flag =  AZP;
   }

d465 1
a465 1
   double r, s, sthe;
d471 2
a472 1
   sthe = sind(theta);
d474 3
a476 2
   s = prj->p[1] + sthe;
   if (s == 0.0) {
d480 1
a480 1
   r =  prj->w[0]*cosd(theta)/s;
d482 21
a502 1
   *y = -r*cosd(phi);
d504 5
a508 2
   if (prj->flag > 0 && sthe < prj->w[2]) {
      return 2;
d523 1
a523 1
   double r, rho, s;
d530 3
a532 1
   r = sqrt(x*x + y*y);
d534 91
a624 1
      *phi = 0.0;
d626 32
a657 1
      *phi = atan2d(x, -y);
d660 7
a666 4
   rho = r*prj->w[1];
   s = rho*prj->p[1]/sqrt(rho*rho+1.0);
   if (fabs(s) > 1.0) {
      if (fabs(s) > 1.0+tol) {
d669 54
a722 1
      *theta = atan2d(1.0,rho) - copysign(90.0,s);
d724 37
a760 1
      *theta = atan2d(1.0,rho) - asind(s);
d763 2
d772 1
d777 1
d789 2
a797 6
   if (prj->flag == -1) {
      prj->flag = -TAN;
   } else {
      prj->flag =  TAN;
   }

d866 2
d881 2
a896 2
   prj->flag = STG;

d957 1
a957 1
*      prj->p[1:2]  SIN obliqueness parameters, alpha and beta.
d960 1
d965 1
d968 3
a970 4
*      prj->w[1]    alpha**2 + beta**2
*      prj->w[2]    2*(alpha**2 + beta**2)
*      prj->w[3]    2*(alpha**2 + beta**2 + 1)
*      prj->w[4]    alpha**2 + beta**2 - 1
d981 2
d989 2
a990 3
   prj->w[2] = 2.0*prj->w[1];
   prj->w[3] = prj->w[2] + 2.0;
   prj->w[4] = prj->w[1] - 1.0;
a994 6
   if (prj->flag == -1) {
      prj->flag = -SIN;
   } else {
      prj->flag =  SIN;
   }

d1016 1
a1016 1
         z = -t*t/2.0;
d1018 1
a1018 1
         z = -2.0 + t*t/2.0;
d1022 1
a1022 1
      z =  sind(theta) - 1.0;
d1029 1
a1029 1
   *y = -prj->r0*(cthe*cphi + prj->p[2]*z);
d1040 1
a1040 1
         t = atand(prj->p[1]*sphi + prj->p[2]*cphi);
d1060 1
a1060 1
   double a, b, c, d, r2, sth, sth1, sth2, sxy, x0, xp, y0, yp, z;
d1089 4
d1095 2
a1096 2
         z = -r2/2.0;
         *theta = 90.0 - R2D*sqrt(r2/(1.0 - x0*prj->p[1] + y0*prj->p[2]));
d1099 4
a1102 6
         sxy = 2.0*(prj->p[1]*x0 - prj->p[2]*y0);

         a = prj->w[3];
         b = -(sxy + prj->w[2]);
         c = r2 + sxy + prj->w[4];
         d = b*b - 2.0*a*c;
d1113 4
a1116 4
         sth = (sth1>sth2) ? sth1 : sth2;
         if (sth > 1.0) {
            if (sth-1.0 < tol) {
               sth = 1.0;
d1118 1
a1118 1
               sth = (sth1<sth2) ? sth1 : sth2;
d1121 8
a1128 1
         if (sth > 1.0 || sth < -1.0) {
d1132 2
a1133 2
         *theta = asind(sth);
         z = sth - 1.0;
d1136 1
a1136 1
      xp = -y0 - prj->p[2]*z;
d1156 2
d1171 2
a1186 2
   prj->flag = ARC;

d1245 1
d1250 1
d1268 3
a1270 1
   strcpy(prj->code, "ARC");
a1337 6
   if (prj->flag == -1) {
      prj->flag = -ZPN;
   } else {
      prj->flag =  ZPN;
   }

d1497 2
d1512 2
a1524 1
   prj->theta0 = 90.0;
a1527 2
   prj->flag = ZEA;

d1602 2
d1626 2
a1651 2
   prj->flag = AIR;

d1781 2
d1798 2
a1836 2
   prj->flag = CYP;

d1900 2
d1917 2
a1939 1
   prj->theta0 = 0.0;
a1942 2
   prj->flag = CEA;

d2003 2
d2018 2
a2033 2
   prj->flag = CAR;

d2083 2
d2098 2
a2113 2
   prj->flag = MER;

d2167 2
d2182 2
a2197 2
   prj->flag = SFL;

d2254 2
d2271 2
a2287 1
   prj->theta0 = 0.0;
a2290 2
   prj->flag = PAR;

d2360 2
d2377 2
a2391 2
   prj->flag = MOL;

d2405 1
a2405 1
   double alpha, resid, u, v, v0, v1;
d2435 3
a2437 3
      alpha = v/2.0;
      *x = prj->w[1]*phi*cos(alpha);
      *y = prj->w[0]*sin(alpha);
d2506 2
d2523 2
a2536 2
   prj->flag = AIT;

d2549 1
a2549 1
   double costhe, w;
d2555 3
a2557 3
   costhe = cosd(theta);
   w = sqrt(prj->w[0]/(1.0 + costhe*cosd(phi/2.0)));
   *x = 2.0*w*costhe*sind(phi/2.0);
d2618 1
d2623 1
d2641 2
a2666 6
   if (prj->flag == -1) {
      prj->flag = -COP;
   } else {
      prj->flag =  COP;
   }

d2748 2
d2772 2
a2799 2
   prj->flag = COE;

d2891 2
d2908 2
a2930 2
   prj->flag = COD;

d3002 2
d3024 2
a3058 2
   prj->flag = COO;

d3144 2
d3159 2
a3174 2
   prj->flag = BON;

d3216 1
a3216 1
   double a, dy, costhe, r;
d3238 2
a3239 2
   costhe = cosd(*theta);
   if (costhe == 0.0) {
d3242 1
a3242 1
      *phi = a*(r/prj->r0)/cosd(*theta);
d3256 2
d3272 2
a3289 2
   prj->flag = PCO;

d3302 1
a3302 1
   double a, costhe, cotthe, sinthe;
d3308 3
a3310 3
   costhe = cosd(theta);
   sinthe = sind(theta);
   a = phi*sinthe;
d3312 1
a3312 1
   if (sinthe == 0.0) {
d3316 1
a3316 1
      cotthe = costhe/sinthe;
d3416 2
d3431 2
a3446 2
   prj->flag = TSC;

d3460 1
a3460 1
   double costhe, l, m, n, rho, x0, xf, y0, yf;
d3467 3
a3469 3
   costhe = cosd(theta);
   l = costhe*cosd(phi);
   m = costhe*sind(phi);
d3631 2
d3646 2
a3661 2
   prj->flag = CSC;

d3675 1
a3675 1
   double costhe, eta, l, m, n, rho, xi;
d3696 3
a3698 3
   costhe = cosd(theta);
   l = costhe*cosd(phi);
   m = costhe*sind(phi);
d3945 2
d3960 2
a3975 2
   prj->flag = QSC;

d3989 1
a3989 1
   double chi, costhe, eta, l, m, n, p, psi, rho, rhu, t, x0, xf, xi, y0, yf;
d4002 3
a4004 3
   costhe = cosd(theta);
   l = costhe*cosd(phi);
   m = costhe*sind(phi);
d4111 4
a4114 4
      psi = eta/xi;
      chi = 1.0 + psi*psi;
      xf  = -sqrt(rhu/(1.0-1.0/sqrt(1.0+chi)));
      yf  = (xf/15.0)*(atand(psi) - asind(psi/sqrt(chi+chi)));
d4116 4
a4119 4
      psi = eta/xi;
      chi = 1.0 + psi*psi;
      xf  =  sqrt(rhu/(1.0-1.0/sqrt(1.0+chi)));
      yf  = (xf/15.0)*(atand(psi) - asind(psi/sqrt(chi+chi)));
d4121 4
a4124 4
      psi = xi/eta;
      chi = 1.0 + psi*psi;
      yf  = -sqrt(rhu/(1.0-1.0/sqrt(1.0+chi)));
      xf  = (yf/15.0)*(atand(psi) - asind(psi/sqrt(chi+chi)));
d4126 4
a4129 4
      psi = xi/eta;
      chi = 1.0 + psi*psi;
      yf  =  sqrt(rhu/(1.0-1.0/sqrt(1.0+chi)));
      xf  = (yf/15.0)*(atand(psi) - asind(psi/sqrt(chi+chi)));
d4162 1
a4162 1
   double chi, l, m, n, psi, rho, rhu, xf, yf, w;
d4206 2
a4207 2
         psi = 0.0;
         chi = 1.0;
d4212 3
a4214 3
         psi = sind(w)/(cosd(w) - SQRT2INV);
         chi = 1.0 + psi*psi;
         rhu = xf*xf*(1.0 - 1.0/sqrt(1.0 + chi));
d4219 2
a4220 2
         psi = 0.0;
         chi = 1.0;
d4225 3
a4227 3
         psi = sind(w)/(cosd(w) - SQRT2INV);
         chi = 1.0 + psi*psi;
         rhu = yf*yf*(1.0 - 1.0/sqrt(1.0 + chi));
d4241 1
a4241 1
      w = sqrt(rhu*(2.0-rhu)/chi);
d4249 1
a4249 1
         l = -m*psi;
d4253 1
a4253 1
         m = -l*psi;
d4260 1
a4260 1
         n = m*psi;
d4264 1
a4264 1
         m = n*psi;
d4271 1
a4271 1
         n = -l*psi;
d4275 1
a4275 1
         l = -n*psi;
d4282 1
a4282 1
         n = -m*psi;
d4286 1
a4286 1
         m = -n*psi;
d4293 1
a4293 1
         n = l*psi;
d4297 1
a4297 1
         l = n*psi;
d4304 1
a4304 1
         l = m*psi;
d4308 1
a4308 1
         m = l*psi;
@


2.17
log
@Updated date in copyright notice.
@
text
@d42 2
d46 1
a47 1
*      stgset stgfwd stgrev   STG: stereographic
d53 1
d56 4
a59 1
*      ceaset ceafwd cearev   CEA: cylindrical equal area
d61 1
a62 1
*      coeset coefwd coerev   COE: conic equal area
d66 1
a66 4
*      glsset glsfwd glsrev   GLS: Sanson-Flamsteed (global sinusoidal)
*      parset parfwd parrev   PAR: parabolic
*      aitset aitfwd aitrev   AIT: Hammer-Aitoff
*      molset molfwd molrev   MOL: Mollweide
d69 23
a91 1
*      tscset tscfwd tscrev   TSC: tangential spherical cube
d152 1
d163 1
d168 1
d180 7
a187 1
*      double w[10]
d190 4
d230 1
a230 1
*   $Id: proj.c,v 2.17 2000/05/10 04:44:05 mcalabre Exp mcalabre $
d238 32
d291 92
d387 1
a387 1
*      prj->p[1]   AZP distance parameter, mu in units of r0.
d390 11
a400 5
*      prj->r0     r0; reset to 180/pi if 0.
*      prj->w[0]   r0*(mu+1)
*      prj->w[1]   1/prj->w[0]
*      prj->w[2]   Boundary parameter, -mu    for |mu| <= 1,
*                                      -1/mu  for |mu| >= 1.
d408 3
d425 3
d429 1
a429 1
      prj->flag = -PRJSET;
d431 1
a431 1
      prj->flag = PRJSET;
d448 1
a448 1
   if (abs(prj->flag) != PRJSET) {
d463 1
a463 1
   if (prj->flag == PRJSET && sthe < prj->w[2]) {
d482 1
a482 1
   if (abs(prj->flag) != PRJSET) {
d511 7
a517 1
*      prj->r0     r0; reset to 180/pi if 0.
d525 3
d530 3
d534 1
a534 1
      prj->flag = -PRJSET;
d536 1
a536 1
      prj->flag = PRJSET;
d553 1
a553 1
   if (abs(prj->flag) != PRJSET) {
d566 1
a566 1
   if (prj->flag == PRJSET && s < 0.0) {
d584 1
a584 1
   if (abs(prj->flag) != PRJSET) {
d600 93
d696 1
a696 1
*      prj->p[1:2] SIN obliqueness parameters, alpha and beta.
d699 12
a710 6
*      prj->r0     r0; reset to 180/pi if 0.
*      prj->w[0]   1/r0
*      prj->w[1]   alpha**2 + beta**2
*      prj->w[2]   2*(alpha**2 + beta**2)
*      prj->w[3]   2*(alpha**2 + beta**2 + 1)
*      prj->w[4]   alpha**2 + beta**2 - 1
d718 3
d729 3
d733 1
a733 1
      prj->flag = -PRJSET;
d735 1
a735 1
      prj->flag = PRJSET;
d752 1
a752 1
   if (abs(prj->flag) != PRJSET) {
d775 1
a775 1
   if (prj->flag == PRJSET) {
d805 1
a805 1
   if (abs(prj->flag) != PRJSET) {
d883 1
a883 1
*   STG: stereographic projection.
d886 1
a886 79
*      prj->r0     r0; reset to 180/pi if 0.
*      prj->w[0]   2*r0
*      prj->w[1]   1/(2*r0)
*===========================================================================*/

int stgset(prj)

struct prjprm *prj;

{
   if (prj->r0 == 0.0) {
      prj->r0 = R2D;
      prj->w[0] = 360.0/PI;
      prj->w[1] = PI/360.0;
   } else {
      prj->w[0] = 2.0*prj->r0;
      prj->w[1] = 1.0/prj->w[0];
   }

   prj->flag = PRJSET;

   return 0;
}

/*--------------------------------------------------------------------------*/

int stgfwd(phi, theta, prj, x, y)

const double phi, theta;
struct prjprm *prj;
double *x, *y;

{
   double r, s;

   if (prj->flag != PRJSET) {
      if (stgset(prj)) return 1;
   }

   s = 1.0 + sind(theta);
   if (s == 0.0) {
      return 2;
   }

   r =  prj->w[0]*cosd(theta)/s;
   *x =  r*sind(phi);
   *y = -r*cosd(phi);

   return 0;
}

/*--------------------------------------------------------------------------*/

int stgrev(x, y, prj, phi, theta)

const double x, y;
struct prjprm *prj;
double *phi, *theta;

{
   double r;

   if (prj->flag != PRJSET) {
      if (stgset(prj)) return 1;
   }

   r = sqrt(x*x + y*y);
   if (r == 0.0) {
      *phi = 0.0;
   } else {
      *phi = atan2d(x, -y);
   }
   *theta = 90.0 - 2.0*atand(r*prj->w[1]);

   return 0;
}

/*============================================================================
*   ARC: zenithal/azimuthal equidistant projection.
d888 7
a894 4
*   Given and/or returned:
*      prj->r0     r0; reset to 180/pi if 0.
*      prj->w[0]   r0*(pi/180)
*      prj->w[1]   (180/pi)/r0
d902 3
d914 4
a917 1
   prj->flag = PRJSET;
d933 1
a933 1
   if (prj->flag != PRJSET) {
d955 1
a955 1
   if (prj->flag != PRJSET) {
d974 1
a974 1
*      prj->p[0:9] Polynomial coefficients.
d977 10
a986 4
*      prj->r0     r0; reset to 180/pi if 0.
*      prj->n      Degree of the polynomial, N.
*      prj->w[0]   Co-latitude of the first point of inflection (N > 2).
*      prj->w[1]   Radius of the first point of inflection (N > 2).
d998 3
d1063 3
d1067 1
a1067 1
      prj->flag = -PRJSET;
d1069 1
a1069 1
      prj->flag = PRJSET;
d1087 1
a1087 1
   if (abs(prj->flag) != PRJSET) {
d1102 1
a1102 1
   if (prj->flag == PRJSET && s > prj->w[0]) {
d1122 1
a1122 1
   if (abs(prj->flag) != PRJSET) {
d1227 9
a1235 3
*      prj->r0     r0; reset to 180/pi if 0.
*      prj->w[0]   2*r0
*      prj->w[1]   1/(2*r0)
d1243 3
d1255 5
a1259 1
   prj->flag = PRJSET;
d1275 1
a1275 1
   if (prj->flag != PRJSET) {
d1298 1
a1298 1
   if (prj->flag != PRJSET) {
d1327 2
a1328 2
*      prj->p[1]   Latitude theta_b within which the error is minimized,
*                  in degrees.
d1331 15
a1345 9
*      prj->r0     r0; reset to 180/pi if 0.
*      prj->w[0]   2*r0
*      prj->w[1]   ln(cos(xi_b))/tan(xi_b)**2, where xi_b = (90-theta_b)/2
*      prj->w[2]   1/2 - prj->w[1]
*      prj->w[3]   2*r0*prj->w[2]
*      prj->w[4]   tol, cutoff for using small angle approximation, in
*                  radians.
*      prj->w[5]   prj->w[2]*tol
*      prj->w[6]   (180/pi)/prj->w[2]
d1356 3
d1378 2
a1379 1
   prj->flag = PRJSET;
d1381 2
d1397 1
a1397 1
   if (prj->flag != PRJSET) {
d1435 1
a1435 1
   if (prj->flag != PRJSET) {
d1502 4
a1505 4
*      prj->p[1]   Distance of point of projection from the centre of the
*                  generating sphere, mu, in units of r0.
*      prj->p[2]   Radius of the cylinder of projection, lambda, in units
*                  of r0.
d1508 11
a1518 5
*      prj->r0     r0; reset to 180/pi if 0.
*      prj->w[0]   r0*lambda*(pi/180)
*      prj->w[1]   (180/pi)/(r0*lambda)
*      prj->w[2]   r0*(mu + lambda)
*      prj->w[3]   1/(r0*(mu + lambda))
d1526 3
d1561 4
a1564 1
   prj->flag = PRJSET;
d1580 1
a1580 1
   if (prj->flag != PRJSET) {
d1606 1
a1606 1
   if (prj->flag != PRJSET) {
d1618 106
d1727 9
a1735 3
*      prj->r0     r0; reset to 180/pi if 0.
*      prj->w[0]   r0*(pi/180)
*      prj->w[1]   (180/pi)/r0
d1743 2
d1755 4
a1758 1
   prj->flag = PRJSET;
d1772 1
a1772 1
   if (prj->flag != PRJSET) {
d1791 1
a1791 1
   if (prj->flag != PRJSET) {
d1805 9
a1813 3
*      prj->r0     r0; reset to 180/pi if 0.
*      prj->w[0]   r0*(pi/180)
*      prj->w[1]   (180/pi)/r0
d1821 3
d1833 4
a1836 1
   prj->flag = PRJSET;
d1850 1
a1850 1
   if (prj->flag != PRJSET) {
d1873 1
a1873 1
   if (prj->flag != PRJSET) {
d1884 4
a1887 1
*   CEA: cylindrical equal area projection.
d1889 81
a1969 3
*   Given:
*      prj->p[1]   Square of the cosine of the latitude at which the
*                  projection is conformal, lambda.
d1972 11
a1982 5
*      prj->r0     r0; reset to 180/pi if 0.
*      prj->w[0]   r0*(pi/180)
*      prj->w[1]   (180/pi)/r0
*      prj->w[2]   r0/lambda
*      prj->w[3]   lambda/r0
d1985 1
a1985 1
int ceaset(prj)
d1990 3
d1997 202
a2198 2
      if (prj->p[1] <= 0.0 || prj->p[1] > 1.0) {
         return 1;
d2200 1
a2200 2
      prj->w[2] = prj->r0/prj->p[1];
      prj->w[3] = prj->p[1]/prj->r0;
d2202 6
a2207 4
      prj->w[0] = prj->r0*D2R;
      prj->w[1] = R2D/prj->r0;
      if (prj->p[1] <= 0.0 || prj->p[1] > 1.0) {
         return 1;
d2209 1
a2209 2
      prj->w[2] = prj->r0/prj->p[1];
      prj->w[3] = prj->p[1]/prj->r0;
d2212 39
a2250 1
   prj->flag = PRJSET;
d2252 2
d2259 1
a2259 1
int ceafwd(phi, theta, prj, x, y)
d2266 4
a2269 2
   if (prj->flag != PRJSET) {
      if (ceaset(prj)) return 1;
d2272 4
a2275 2
   *x = prj->w[0]*phi;
   *y = prj->w[2]*sind(theta);
d2282 1
a2282 1
int cearev(x, y, prj, phi, theta)
d2289 1
a2289 1
   double s;
d2292 11
a2302 2
   if (prj->flag != PRJSET) {
      if (ceaset(prj)) return 1;
d2305 2
a2306 1
   s = y*prj->w[3];
d2314 7
a2320 1
   *phi   = x*prj->w[1];
d2330 3
a2332 3
*      prj->p[1]   sigma = (theta2+theta1)/2
*      prj->p[2]   delta = (theta2-theta1)/2, where theta1 and theta2 are the
*                  latitudes of the standard parallels, in degrees.
d2335 13
a2347 7
*      prj->r0     r0; reset to 180/pi if 0.
*      prj->w[0]   C  = sin(sigma)
*      prj->w[1]   1/C
*      prj->w[2]   Y0 = r0*cos(delta)*cot(sigma)
*      prj->w[3]   r0*cos(delta)
*      prj->w[4]   1/(r0*cos(delta)
*      prj->w[5]   cot(sigma)
d2355 3
d2377 3
d2381 1
a2381 1
      prj->flag = -PRJSET;
d2383 1
a2383 1
      prj->flag = PRJSET;
d2400 1
a2400 1
   if (abs(prj->flag) != PRJSET) {
d2416 1
a2416 1
   if (prj->flag == PRJSET && r*prj->w[0] < 0.0) {
d2434 1
a2434 1
   if (abs(prj->flag) != PRJSET) {
d2455 1
a2455 1
*   COD: conic equidistant projection.
d2458 3
a2460 3
*      prj->p[1]   sigma = (theta2+theta1)/2
*      prj->p[2]   delta = (theta2-theta1)/2, where theta1 and theta2 are the
*                  latitudes of the standard parallels, in degrees.
d2463 16
a2478 5
*      prj->r0     r0; reset to 180/pi if 0.
*      prj->w[0]   C = r0*sin(sigma)*sin(delta)/delta
*      prj->w[1]   1/C
*      prj->w[2]   Y0 = delta*cot(delta)*cot(sigma)
*      prj->w[3]   Y0 + sigma
d2481 1
a2481 1
int codset(prj)
d2486 5
d2493 2
a2494 5
   if (prj->p[2] == 0.0) {
      prj->w[0] = prj->r0*sind(prj->p[1])*D2R;
   } else {
      prj->w[0] = prj->r0*sind(prj->p[1])*sind(prj->p[2])/prj->p[2];
   }
d2496 1
d2502 12
a2513 2
   prj->w[2] = prj->r0*cosd(prj->p[2])*cosd(prj->p[1])/prj->w[0];
   prj->w[3] = prj->w[2] + prj->p[1];
d2515 1
a2515 1
   prj->flag = PRJSET;
d2522 1
a2522 1
int codfwd(phi, theta, prj, x, y)
d2531 2
a2532 2
   if (prj->flag != PRJSET) {
      if (codset(prj)) return 1;
d2535 6
a2540 2
   a = prj->w[0]*phi;
   r = prj->w[3] - theta;
d2550 1
a2550 1
int codrev(x, y, prj, phi, theta)
d2557 2
a2558 1
   double a, dy, r;
d2560 2
a2561 2
   if (prj->flag != PRJSET) {
      if (codset(prj)) return 1;
d2574 17
a2590 2
   *phi   = a*prj->w[1];
   *theta = prj->w[3] - r;
d2596 1
a2596 1
*   COE: conic equal area projection.
d2599 3
a2601 3
*      prj->p[1]   sigma = (theta2+theta1)/2
*      prj->p[2]   delta = (theta2-theta1)/2, where theta1 and theta2 are the
*                  latitudes of the standard parallels, in degrees.
d2604 11
a2614 10
*      prj->r0     r0; reset to 180/pi if 0.
*      prj->w[0]   C = (sin(theta1) + sin(theta2))/2
*      prj->w[1]   1/C
*      prj->w[2]   Y0 = chi*sqrt(psi - 2C*sind(sigma))
*      prj->w[3]   chi = r0/C
*      prj->w[4]   psi = 1 + sin(theta1)*sin(theta2)
*      prj->w[5]   2C
*      prj->w[6]   (1 + sin(theta1)*sin(theta2))*(r0/C)**2
*      prj->w[7]   C/(2*r0**2)
*      prj->w[8]   chi*sqrt(psi + 2C)
d2617 1
a2617 1
int coeset(prj)
d2622 2
a2623 1
   double theta1, theta2;
d2627 5
a2631 2
   theta1 = prj->p[1] - prj->p[2];
   theta2 = prj->p[1] + prj->p[2];
a2632 1
   prj->w[0] = (sind(theta1) + sind(theta2))/2.0;
d2638 2
a2639 7

   prj->w[3] = prj->r0/prj->w[0];
   prj->w[4] = 1.0 + sind(theta1)*sind(theta2);
   prj->w[5] = 2.0*prj->w[0];
   prj->w[6] = prj->w[3]*prj->w[3]*prj->w[4];
   prj->w[7] = 1.0/(2.0*prj->r0*prj->w[3]);
   prj->w[8] = prj->w[3]*sqrt(prj->w[4] + prj->w[5]);
d2641 2
a2642 1
   prj->w[2] = prj->w[3]*sqrt(prj->w[4] - prj->w[5]*sind(prj->p[1]));
d2644 1
a2644 1
   prj->flag = PRJSET;
d2651 1
a2651 1
int coefwd(phi, theta, prj, x, y)
d2660 2
a2661 2
   if (prj->flag != PRJSET) {
      if (coeset(prj)) return 1;
d2664 2
a2665 6
   a = phi*prj->w[0];
   if (theta == -90.0) {
      r = prj->w[8];
   } else {
      r = prj->w[3]*sqrt(prj->w[4] - prj->w[5]*sind(theta));
   }
d2675 1
a2675 1
int coerev(x, y, prj, phi, theta)
d2682 1
a2682 2
   double a, dy, r, w;
   const double tol = 1.0e-12;
d2684 2
a2685 2
   if (prj->flag != PRJSET) {
      if (coeset(prj)) return 1;
d2698 2
a2699 17
   *phi = a*prj->w[1];
   if (fabs(r - prj->w[8]) < tol) {
      *theta = -90.0;
   } else {
      w = (prj->w[6] - r*r)*prj->w[7];
      if (fabs(w) > 1.0) {
         if (fabs(w-1.0) < tol) {
            *theta = 90.0;
         } else if (fabs(w+1.0) < tol) {
            *theta = -90.0;
         } else {
            return 2;
         }
      } else {
         *theta = asind(w);
      }
   }
d2708 3
a2710 3
*      prj->p[1]   sigma = (theta2+theta1)/2
*      prj->p[2]   delta = (theta2-theta1)/2, where theta1 and theta2 are the
*                  latitudes of the standard parallels, in degrees.
d2713 14
a2726 8
*      prj->r0     r0; reset to 180/pi if 0.
*      prj->w[0]   C = ln(cos(theta2)/cos(theta1))/ln(tan(tau2)/tan(tau1))
*                      where tau1 = (90 - theta1)/2
*                            tau2 = (90 - theta2)/2
*      prj->w[1]   1/C
*      prj->w[2]   Y0 = psi*tan((90-sigma)/2)**C
*      prj->w[3]   psi = (r0*cos(theta1)/C)/tan(tau1)**C
*      prj->w[4]   1/psi
d2736 3
d2767 4
a2770 1
   prj->flag = PRJSET;
d2786 1
a2786 1
   if (prj->flag != PRJSET) {
d2818 1
a2818 1
   if (prj->flag != PRJSET) {
d2850 1
a2850 1
*      prj->p[1]   Bonne conformal latitude, theta1, in degrees.
d2853 9
a2861 3
*      prj->r0     r0; reset to 180/pi if 0.
*      prj->w[1]   r0*pi/180
*      prj->w[2]   Y0 = r0*(cot(theta1) + theta1*pi/180)
d2869 3
d2881 4
a2884 1
   prj->flag = PRJSET;
d2902 1
a2902 1
      return glsfwd(phi, theta, prj, x, y);
d2905 1
a2905 1
   if (prj->flag != PRJSET) {
d2931 1
a2931 1
      return glsrev(x, y, prj, phi, theta);
d2934 1
a2934 1
   if (prj->flag != PRJSET) {
d2963 10
a2972 4
*      prj->r0     r0; reset to 180/pi if 0.
*      prj->w[0]   r0*(pi/180)
*      prj->w[1]   1/r0
*      prj->w[2]   2*r0
d2980 3
d2994 2
a2995 1
   prj->flag = PRJSET;
d2997 2
d3013 1
a3013 1
   if (prj->flag != PRJSET) {
d3046 1
a3046 1
   if (prj->flag != PRJSET) {
d3118 1
a3118 1
*   GLS: Sanson-Flamsteed ("global sinusoid") projection.
d3121 9
a3129 3
*      prj->r0     r0; reset to 180/pi if 0.
*      prj->w[0]   r0*(pi/180)
*      prj->w[1]   (180/pi)/r0
d3132 1
a3132 1
int glsset(prj)
d3137 3
d3142 2
a3143 2
      prj->w[0] = 1.0;
      prj->w[1] = 1.0;
d3145 1
a3145 1
      prj->w[0] = prj->r0*D2R;
d3149 4
a3152 1
   prj->flag = PRJSET;
d3159 1
a3159 1
int glsfwd(phi, theta, prj, x, y)
d3166 6
a3171 2
   if (prj->flag != PRJSET) {
      if (glsset(prj)) return 1;
d3174 4
a3177 2
   *x = prj->w[0]*phi*cosd(theta);
   *y = prj->w[0]*theta;
d3179 5
a3183 16
   return 0;
}

/*--------------------------------------------------------------------------*/

int glsrev(x, y, prj, phi, theta)

const double x, y;
struct prjprm *prj;
double *phi, *theta;

{
   double w;

   if (prj->flag != PRJSET) {
      if (glsset(prj)) return 1;
d3185 3
a3187 6

   w = cos(y/prj->r0);
   if (w == 0.0) {
      *phi = 0.0;
   } else {
      *phi = x*prj->w[1]/cos(y/prj->r0);
d3189 3
a3191 32
   *theta = y*prj->w[1];

   return 0;
}

/*============================================================================
*   PAR: parabolic projection.
*
*   Given and/or returned:
*      prj->r0     r0; reset to 180/pi if 0.
*      prj->w[0]   r0*(pi/180)
*      prj->w[1]   (180/pi)/r0
*      prj->w[2]   pi*r0
*      prj->w[3]   1/(pi*r0)
*===========================================================================*/

int parset(prj)

struct prjprm *prj;

{
   if (prj->r0 == 0.0) {
      prj->r0 = R2D;
      prj->w[0] = 1.0;
      prj->w[1] = 1.0;
      prj->w[2] = 180.0;
      prj->w[3] = 1.0/prj->w[2];
   } else {
      prj->w[0] = prj->r0*D2R;
      prj->w[1] = 1.0/prj->w[0];
      prj->w[2] = PI*prj->r0;
      prj->w[3] = 1.0/prj->w[2];
d3193 3
a3195 19

   prj->flag = PRJSET;

   return 0;
}

/*--------------------------------------------------------------------------*/

int parfwd(phi, theta, prj, x, y)

const double phi, theta;
struct prjprm *prj;
double *x, *y;

{
   double s;

   if (prj->flag != PRJSET) {
      if (parset(prj)) return 1;
d3197 3
a3199 21

   s = sind(theta/3.0);
   *x = prj->w[0]*phi*(1.0 - 4.0*s*s);
   *y = prj->w[2]*s;

   return 0;
}

/*--------------------------------------------------------------------------*/

int parrev(x, y, prj, phi, theta)

const double x, y;
struct prjprm *prj;
double *phi, *theta;

{
   double s, t;

   if (prj->flag != PRJSET) {
      if (parset(prj)) return 1;
d3202 30
a3231 3
   s = y*prj->w[3];
   if (s > 1.0 || s < -1.0) {
      return 2;
d3234 2
a3235 5
   t = 1.0 - 4.0*s*s;
   if (t == 0.0) {
      if (x == 0.0) {
         *phi = 0.0;
      } else {
d3238 1
a3238 2
   } else {
      *phi = prj->w[1]*x/t;
d3240 5
a3244 47

   *theta = 3.0*asind(s);

   return 0;
}

/*============================================================================
*   AIT: Hammer-Aitoff projection.
*
*   Given and/or returned:
*      prj->r0     r0; reset to 180/pi if 0.
*      prj->w[0]   2*r0**2
*      prj->w[1]   1/(2*r0)**2
*      prj->w[2]   1/(4*r0)**2
*      prj->w[3]   1/(2*r0)
*===========================================================================*/

int aitset(prj)

struct prjprm *prj;

{
   if (prj->r0 == 0.0) prj->r0 = R2D;

   prj->w[0] = 2.0*prj->r0*prj->r0;
   prj->w[1] = 1.0/(2.0*prj->w[0]);
   prj->w[2] = prj->w[1]/4.0;
   prj->w[3] = 1.0/(2.0*prj->r0);

   prj->flag = PRJSET;

   return 0;
}

/*--------------------------------------------------------------------------*/

int aitfwd(phi, theta, prj, x, y)

const double phi, theta;
struct prjprm *prj;
double *x, *y;

{
   double costhe, w;

   if (prj->flag != PRJSET) {
      if (aitset(prj)) return 1;
d3247 2
a3248 4
   costhe = cosd(theta);
   w = sqrt(prj->w[0]/(1.0 + costhe*cosd(phi/2.0)));
   *x = 2.0*w*costhe*sind(phi/2.0);
   *y = w*sind(theta);
d3255 1
a3255 1
int aitrev(x, y, prj, phi, theta)
d3262 1
a3262 2
   double s, u, xp, yp, z;
   const double tol = 1.0e-13;
d3264 2
a3265 2
   if (prj->flag != PRJSET) {
      if (aitset(prj)) return 1;
d3268 2
a3269 5
   u = 1.0 - x*x*prj->w[2] - y*y*prj->w[1];
   if (u < 0.0) {
      if (u < -tol) {
         return 2;
      }
d3271 3
a3273 16
      u = 0.0;
   }

   z = sqrt(u);
   s = z*y/prj->r0;
   if (fabs(s) > 1.0) {
      if (fabs(s) > 1.0+tol) {
         return 2;
      }
      s = copysign(1.0,s);
   }

   xp = 2.0*z*z - 1.0;
   yp = z*x*prj->w[3];
   if (xp == 0.0 && yp == 0.0) {
      *phi = 0.0;
d3275 2
a3276 1
      *phi = 2.0*atan2d(yp, xp);
a3277 1
   *theta = asind(s);
d3279 2
a3280 2
   return 0;
}
d3282 31
a3312 52
/*============================================================================
*   MOL: Mollweide's projection.
*
*   Given and/or returned:
*      prj->r0     r0; reset to 180/pi if 0.
*      prj->w[0]   sqrt(2)*r0
*      prj->w[1]   sqrt(2)*r0/90
*      prj->w[2]   1/(sqrt(2)*r0)
*      prj->w[3]   90/r0
*===========================================================================*/

int molset(prj)

struct prjprm *prj;

{
   if (prj->r0 == 0.0) prj->r0 = R2D;

   prj->w[0] = SQRT2*prj->r0;
   prj->w[1] = prj->w[0]/90.0;
   prj->w[2] = 1.0/prj->w[0];
   prj->w[3] = 90.0/prj->r0;
   prj->w[4] = 2.0/PI;

   prj->flag = PRJSET;

   return 0;
}

/*--------------------------------------------------------------------------*/

int molfwd(phi, theta, prj, x, y)

const double phi, theta;
struct prjprm *prj;
double *x, *y;

{
   int   j;
   double alpha, resid, u, v, v0, v1;
   const double tol = 1.0e-13;

   if (prj->flag != PRJSET) {
      if (molset(prj)) return 1;
   }

   if (fabs(theta) == 90.0) {
      *x = 0.0;
      *y = copysign(prj->w[0],theta);
   } else if (theta == 0.0) {
      *x = prj->w[1]*phi;
      *y = 0.0;
d3314 4
a3317 19
      u  = PI*sind(theta);
      v0 = -PI;
      v1 =  PI;
      v  = u;
      for (j = 0; j < 100; j++) {
         resid = (v - u) + sin(v);
         if (resid < 0.0) {
            if (resid > -tol) break;
            v0 = v;
         } else {
            if (resid < tol) break;
            v1 = v;
         }
         v = (v0 + v1)/2.0;
      }

      alpha = v/2.0;
      *x = prj->w[1]*phi*cos(alpha);
      *y = prj->w[0]*sin(alpha);
d3320 1
a3320 30
   return 0;
}

/*--------------------------------------------------------------------------*/

int molrev(x, y, prj, phi, theta)

const double x, y;
struct prjprm *prj;
double *phi, *theta;

{
   double s, y0, z;
   const double tol = 1.0e-12;

   if (prj->flag != PRJSET) {
      if (molset(prj)) return 1;
   }

   y0 = y/prj->r0;
   s  = 2.0 - y0*y0;
   if (s <= tol) {
      if (s < -tol) {
         return 2;
      }
      s = 0.0;

      if (fabs(x) > tol) {
         return 2;
      }
d3323 1
a3323 2
      s = sqrt(s);
      *phi = prj->w[3]*x/s;
d3325 1
a3325 19

   z = y*prj->w[2];
   if (fabs(z) > 1.0) {
      if (fabs(z) > 1.0+tol) {
         return 2;
      }
      z = copysign(1.0,z) + y0*s/PI;
   } else {
      z = asin(z)*prj->w[4] + y0*s/PI;
   }

   if (fabs(z) > 1.0) {
      if (fabs(z) > 1.0+tol) {
         return 2;
      }
      z = copysign(1.0,z);
   }

   *theta = asind(z);
d3334 9
a3342 3
*      prj->r0     r0; reset to 180/pi if 0.
*      prj->w[0]   r0*(pi/4)
*      prj->w[1]   (4/pi)/r0
d3350 3
d3362 4
a3365 1
   prj->flag = PRJSET;
d3397 1
a3397 1
   if (prj->flag != PRJSET) {
d3543 1
a3543 1
   if (prj->flag != PRJSET) {
d3646 9
a3654 3
*      prj->r0     r0; reset to 180/pi if 0.
*      prj->w[0]   r0*(pi/4)
*      prj->w[1]   (4/pi)/r0
d3662 3
d3674 2
a3675 1
   prj->flag = PRJSET;
d3677 2
d3695 1
a3695 1
   if (prj->flag != PRJSET) {
d3868 1
a3868 1
   if (prj->flag != PRJSET) {
a4012 201
   }

   if (l == 0.0 && m == 0.0) {
      *phi = 0.0;
   } else {
      *phi = atan2d(m, l);
   }
   *theta = asind(n);

   return 0;
}

/*============================================================================
*   TSC: tangential spherical cube projection.
*
*   Given and/or returned:
*      prj->r0     r0; reset to 180/pi if 0.
*      prj->w[0]   r0*(pi/4)
*      prj->w[1]   (4/pi)/r0
*===========================================================================*/

int tscset(prj)

struct prjprm *prj;

{
   if (prj->r0 == 0.0) {
      prj->r0 = R2D;
      prj->w[0] = 45.0;
      prj->w[1] = 1.0/45.0;
   } else {
      prj->w[0] = prj->r0*PI/4.0;
      prj->w[1] = 1.0/prj->w[0];
   }

   prj->flag = PRJSET;

   return 0;
}

/*--------------------------------------------------------------------------*/

int tscfwd(phi, theta, prj, x, y)

const double phi, theta;
struct prjprm *prj;
double *x, *y;

{
   int   face;
   double costhe, l, m, n, rho, x0, xf, y0, yf;
   const double tol = 1.0e-12;

   if (prj->flag != PRJSET) {
      if (tscset(prj)) return 1;
   }

   costhe = cosd(theta);
   l = costhe*cosd(phi);
   m = costhe*sind(phi);
   n = sind(theta);

   face = 0;
   rho  = n;
   if (l > rho) {
      face = 1;
      rho  = l;
   }
   if (m > rho) {
      face = 2;
      rho  = m;
   }
   if (-l > rho) {
      face = 3;
      rho  = -l;
   }
   if (-m > rho) {
      face = 4;
      rho  = -m;
   }
   if (-n > rho) {
      face = 5;
      rho  = -n;
   }

   if (face == 0) {
      xf =  m/rho;
      yf = -l/rho;
      x0 =  0.0;
      y0 =  2.0;
   } else if (face == 1) {
      xf =  m/rho;
      yf =  n/rho;
      x0 =  0.0;
      y0 =  0.0;
   } else if (face == 2) {
      xf = -l/rho;
      yf =  n/rho;
      x0 =  2.0;
      y0 =  0.0;
   } else if (face == 3) {
      xf = -m/rho;
      yf =  n/rho;
      x0 =  4.0;
      y0 =  0.0;
   } else if (face == 4) {
      xf =  l/rho;
      yf =  n/rho;
      x0 =  6.0;
      y0 =  0.0;
   } else if (face == 5) {
      xf =  m/rho;
      yf =  l/rho;
      x0 =  0.0;
      y0 = -2.0;
   }

   if (fabs(xf) > 1.0) {
      if (fabs(xf) > 1.0+tol) {
         return 2;
      }
      xf = copysign(1.0,xf);
   }
   if (fabs(yf) > 1.0) {
      if (fabs(yf) > 1.0+tol) {
         return 2;
      }
      yf = copysign(1.0,yf);
   }

   *x = prj->w[0]*(xf + x0);
   *y = prj->w[0]*(yf + y0);

   return 0;
}

/*--------------------------------------------------------------------------*/

int tscrev(x, y, prj, phi, theta)

const double x, y;
struct prjprm *prj;
double *phi, *theta;

{
   double l, m, n, xf, yf;

   if (prj->flag != PRJSET) {
      if (tscset(prj)) return 1;
   }

   xf = x*prj->w[1];
   yf = y*prj->w[1];

   /* Check bounds. */
   if (fabs(xf) <= 1.0) {
      if (fabs(yf) > 3.0) return 2;
   } else {
      if (fabs(xf) > 7.0) return 2;
      if (fabs(yf) > 1.0) return 2;
   }

   /* Map negative faces to the other side. */
   if (xf < -1.0) xf += 8.0;

   /* Determine the face. */
   if (xf > 5.0) {
      /* face = 4 */
      xf = xf - 6.0;
      m  = -1.0/sqrt(1.0 + xf*xf + yf*yf);
      l  = -m*xf;
      n  = -m*yf;
   } else if (xf > 3.0) {
      /* face = 3 */
      xf = xf - 4.0;
      l  = -1.0/sqrt(1.0 + xf*xf + yf*yf);
      m  =  l*xf;
      n  = -l*yf;
   } else if (xf > 1.0) {
      /* face = 2 */
      xf = xf - 2.0;
      m  =  1.0/sqrt(1.0 + xf*xf + yf*yf);
      l  = -m*xf;
      n  =  m*yf;
   } else if (yf > 1.0) {
      /* face = 0 */
      yf = yf - 2.0;
      n  = 1.0/sqrt(1.0 + xf*xf + yf*yf);
      l  = -n*yf;
      m  =  n*xf;
   } else if (yf < -1.0) {
      /* face = 5 */
      yf = yf + 2.0;
      n  = -1.0/sqrt(1.0 + xf*xf + yf*yf);
      l  = -n*yf;
      m  = -n*xf;
   } else {
      /* face = 1 */
      l  =  1.0/sqrt(1.0 + xf*xf + yf*yf);
      m  =  l*xf;
      n  =  l*yf;
@


2.16
log
@Check for invalid (x,y) in zearev().
@
text
@d4 1
a4 1
*   Copyright (C) 1995-1999, Mark Calabretta
d192 1
a192 1
*   $Id: proj.c,v 2.15 1999/12/13 07:27:05 mcalabre Exp mcalabre $
@


2.15
log
@Revised include file handling.
@
text
@d192 1
a192 1
*   $Id: proj.c,v 2.14 1999/11/19 05:50:05 mcalabre Exp mcalabre $
d1048 1
a1048 1
   double r;
d1062 7
a1068 2
   if (fabs(r-prj->w[0]) < tol) {
      *theta = -90.0;
d1070 1
a1070 1
      *theta = 90.0 - 2.0*asind(r*prj->w[1]);
@


2.14
log
@Allow more general face layout in the inverse quadcube projections.
@
text
@d192 1
a192 1
*   $Id: proj.c,v 2.13 1999/11/19 00:20:18 mcalabre Exp mcalabre $
d195 1
d197 1
@


2.13
log
@Deimplemented the DSS projection.
@
text
@d192 1
a192 1
*   $Id: proj.c,v 2.12 1999/11/19 00:14:19 mcalabre Exp mcalabre $
d2890 11
d2902 1
a2902 4
   if (xf > 7.0) {
      return 2;
   } else if (xf > 5.0) {
      if (fabs(yf) > 1.0) return 2;
a2905 1
      if (fabs(yf) > 1.0) return 2;
a2908 1
      if (fabs(yf) > 1.0) return 2;
a2910 2
   } else if (xf < -1.0) {
      return 2;
a2911 1
      if (yf > 3.0) return 2;
a2914 1
      if (yf < -3.0) return 2;
d3203 11
d3215 1
a3215 4
   if (xf > 7.0) {
      return 2;
   } else if (xf > 5.0) {
      if (fabs(yf) > 1.0) return 2;
a3218 1
      if (fabs(yf) > 1.0) return 2;
a3221 1
      if (fabs(yf) > 1.0) return 2;
a3223 2
   } else if (xf < -1.0) {
      return 2;
a3224 1
      if (yf > 3.0) return 2;
a3227 1
      if (yf < -3.0) return 2;
d3495 11
d3507 1
a3507 4
   if (xf > 7.0) {
      return 2;
   } else if (xf > 5.0) {
      if (fabs(yf) > 1.0) return 2;
a3513 1
      if (fabs(yf) > 1.0) return 2;
a3519 1
      if (fabs(yf) > 1.0) return 2;
a3524 2
   } else if (xf < -1.0) {
      return 2;
a3525 1
      if (yf > 3.0) return 2;
a3531 1
      if (yf < -3.0) return 2;
@


2.12
log
@Made a small allowance for rounding error in determining the validity of
(x,y) in cearev() and aitrev(); corrected a comment in the BON prologue.
@
text
@a66 1
*      dssset dssfwd dssrev   DSS: Digitized Sky Survey plate solution
d192 1
a192 1
*   $Id: proj.c,v 2.11 1999/04/09 05:05:56 mcalabre Exp mcalabre $
a3544 261
   return 0;
}

/*============================================================================
*   DSS: Digitized Sky Survey plate solution.
*
*   Given:
*      prj->p[1]   AMDX1  (= a1)
*      prj->p[2]   AMDX2  (= a2)
*      prj->p[3]   AMDX3  (= a3)
*      prj->p[4]   AMDX4  (= a4)
*      prj->p[5]   AMDX5  (= a5)
*      prj->p[6]   AMDX6  (= a6)
*      prj->p[7]   AMDX7  (= a7)
*      prj->p[8]   AMDX8  (= a8)
*      prj->p[9]   AMDX9  (= a9)
*      prj->p[10]  AMDX10 (= a10)
*      prj->p[11]  AMDX11 (= a11)
*      prj->p[12]  AMDX12 (= a12)
*      prj->p[13]  AMDX13 (= a13)
*                 (AMDX14 to AMDX20 are reserved but not used)
*      prj->p[21]  AMDY1  (= b1)
*      prj->p[22]  AMDY2  (= b2)
*      prj->p[23]  AMDY3  (= b3)
*      prj->p[24]  AMDY4  (= b4)
*      prj->p[25]  AMDY5  (= b5)
*      prj->p[26]  AMDY6  (= b6)
*      prj->p[27]  AMDY7  (= b7)
*      prj->p[28]  AMDY8  (= b8)
*      prj->p[29]  AMDY9  (= b9)
*      prj->p[30]  AMDY10 (= b10)
*      prj->p[31]  AMDY11 (= b11)
*      prj->p[32]  AMDY12 (= b12)
*      prj->p[33]  AMDY13 (= b13)
*                 (AMDY14 to AMDY20 are reserved but not used)
*
*   Given and/or returned:
*      prj->r0     r0; reset to 180/pi if 0.
*      prj->w[0]   3600*r0
*      prj->w[1]   3600.0/a1  ...x plate scale, mm/degree.
*      prj->w[2]   3600.0/b1  ...y plate scale, mm/degree.
*      prj->w[3]   a4  + a7
*      prj->w[4]   a6  + a7
*      prj->w[5]   a8  + a12
*      prj->w[6]   a10 + a12
*      prj->w[7]   2*(a4  + a7)
*      prj->w[8]   2*(a6  + a7)
*      prj->w[9]   3*(a8  + a12)
*      prj->w[10]  2*(a10 + a12)
*      prj->w[11]  2*a9
*      prj->w[12]  3*a11
*      prj->w[13]  4*a13
*      prj->w[14]  b4  + b7
*      prj->w[15]  b6  + b7
*      prj->w[16]  b8  + b12
*      prj->w[17]  b10 + b12
*      prj->w[18]  2*(b4  + b7)
*      prj->w[19]  2*(b6  + b7)
*      prj->w[20]  3*(b8  + b12)
*      prj->w[21]  2*(b10 + b12)
*      prj->w[22]  2*b9
*      prj->w[23]  3*b11
*      prj->w[24]  4*b13
*===========================================================================*/
 
int dssset(prj)
 
struct prjprm *prj;
 
{
   if (prj->r0 == 0.0) {
      prj->r0 = R2D;
   }
 
   if (prj->p[1] == 0.0 || prj->p[21] == 0.0) {
      return 1;
   }

   prj->w[0]  = 3600.0*prj->r0;
   prj->w[1]  = 3600.0/prj->p[1];
   prj->w[2]  = 3600.0/prj->p[21];
   prj->w[3]  = prj->p[4]  + prj->p[7];
   prj->w[4]  = prj->p[6]  + prj->p[7];
   prj->w[5]  = prj->p[8]  + prj->p[12];
   prj->w[6]  = prj->p[10] + prj->p[12];
   prj->w[7]  = 2.0*prj->w[3];
   prj->w[8]  = 2.0*prj->w[4];
   prj->w[9]  = 3.0*prj->w[5];
   prj->w[10] = 2.0*prj->w[6];
   prj->w[11] = 2.0*prj->p[9];
   prj->w[12] = 3.0*prj->p[11];
   prj->w[13] = 4.0*prj->p[13];
   prj->w[14] = prj->p[24] + prj->p[27];
   prj->w[15] = prj->p[26] + prj->p[27];
   prj->w[16] = prj->p[28] + prj->p[32];
   prj->w[17] = prj->p[30] + prj->p[32];
   prj->w[18] = 2.0*prj->w[14];
   prj->w[19] = 2.0*prj->w[15];
   prj->w[20] = 3.0*prj->w[16];
   prj->w[21] = 2.0*prj->w[17];
   prj->w[22] = 2.0*prj->p[29];
   prj->w[23] = 3.0*prj->p[31];
   prj->w[24] = 4.0*prj->p[33];
 
   prj->flag = PRJSET;
 
   return 0;
}
 
/*--------------------------------------------------------------------------*/
 
int dssfwd(phi, theta, prj, x, y)
 
const double phi, theta;
struct prjprm *prj;
double *x, *y;
 
{
   int iter;
   double deta, detadx, detady, dx, dxi, dxidx, dxidy, dy;
   double eta, eta0, r, r4, rr, s, xi, xi0, xo, xx, xy, yo, yy, z;
   const double tol = 1.0e-12;

   if (abs(prj->flag) != PRJSET) {
      if (dssset(prj)) return 1;
   }

   /* Apply forward gnomonic projection to get standard coordinates. */
   s = sind(theta);
   if (s == 0.0) {
      return 2;
   }
 
   r =  prj->w[0]*cosd(theta)/s;
   xi0  =  r*sind(phi);
   eta0 = -r*cosd(phi);

   /* Initial guess for plate offsets (in mm). */
   xo =  (xi0 - prj->p[3])/prj->p[1];
   yo = (eta0 - prj->p[23])/prj->p[21];

   /* Iterate. */
   for (iter = 0; iter < 100; iter++) {
      xx = xo*xo;
      yy = yo*yo;
      xy = xo*yo;
      rr = xx + yy;
      r4 = rr*rr;

      xi =     xo*r4*prj->p[13] +
               xy*(prj->p[5]  + xo*prj->p[9]   + yo*prj->w[6])   +
               yo*(prj->p[2]  + yo*(prj->w[4]  + yo*prj->p[11])) +
               xo*(prj->p[1]  + xo*(prj->w[3]  + xo*prj->w[5]))  +
               prj->p[3];

      /* Derivative of xi wrt x. */
      dxidx =  xy*prj->w[11]  + rr*(4.0*xx + rr)*prj->p[13] +
               yo*(prj->p[5]  + yo*prj->w[6])  +
               xo*(prj->w[7]  + xo*prj->w[9])  +
               prj->p[1];

      /* Derivative of xi wrt y. */
      dxidy =  xy*(prj->w[10] + rr*prj->w[13]) +
               xo*(prj->p[5]  + xo*prj->p[9])  +
               yo*(prj->w[8]  + yo*prj->w[12]) +
               prj->p[2];

      eta =    yo*r4*prj->p[33] +
               xy*(prj->p[25] + yo*prj->p[29]  + xo*prj->w[17])  +
               xo*(prj->p[22] + xo*(prj->w[15] + xo*prj->p[31])) +
               yo*(prj->p[21] + yo*(prj->w[14] + yo*prj->w[16])) +
               prj->p[23];

      /* Derivative of eta wrt x. */
      detadx = xy*(prj->w[21] + rr*prj->w[24]) +
               yo*(prj->p[25] + yo*prj->p[29]) +
               xo*(prj->w[19] + xo*prj->w[23]) +
               prj->p[22];

      /* Derivative of eta wrt y. */
      detady = xy*prj->w[22]  + rr*(4.0*yy + rr)*prj->p[33] +
               xo*(prj->p[25] + xo*prj->w[17]) +
               yo*(prj->w[18] + yo*prj->w[20]) +
               prj->p[21];

      /* Error terms. */
      dxi   =  xi0 - xi;
      deta  = eta0 - eta;

      /* Compute correction. */
      z  = dxidx*detady - dxidy*detadx;
      dx = (dxi*detady - deta*dxidy)/z;
      dy = (deta*dxidx - dxi*detadx)/z;

      /* Apply correction. */
      xo = xo + dx;
      yo = yo + dy;

      /* Test for convergence. */
      if (fabs(dx) < tol) {
         if (fabs(dy) < tol) break;
      }
   }

   /* Convert plate centre offsets from mm to degrees. */
   *x = xo/prj->w[1];
   *y = yo/prj->w[2];
 
   if (prj->flag == PRJSET && s < 0.0) {
      return 2;
   }
 
   return 0;
}
 
/*--------------------------------------------------------------------------*/
 
int dssrev(x, y, prj, phi, theta)
 
const double x, y;
struct prjprm *prj;
double *phi, *theta;
 
{
   double eta, r, r4, rr, xi, xo, xx, xy, yo, yy;

   if (abs(prj->flag) != PRJSET) {
      if (dssset(prj)) return 1;
   }

   /* Convert plate centre offsets from degrees to mm. */
   xo = x*prj->w[1];
   yo = y*prj->w[2];

   xx = xo*xo;
   yy = yo*yo;
   xy = xo*yo;
   rr = xx + yy;
   r4 = rr*rr;

   /* Convert to standard coordinates in arcsec. */
   xi =  xo*r4*prj->p[13] +
         xy*(prj->p[5]  + xo*prj->p[9]   + yo*prj->w[6])   +
         yo*(prj->p[2]  + yo*(prj->w[4]  + yo*prj->p[11])) +
         xo*(prj->p[1]  + xo*(prj->w[3]  + xo*prj->w[5]))  +
         prj->p[3];
   eta = yo*r4*prj->p[33] +
         xy*(prj->p[25] + yo*prj->p[29]  + xo*prj->w[17])  +
         xo*(prj->p[22] + xo*(prj->w[15] + xo*prj->p[31])) +
         yo*(prj->p[21] + yo*(prj->w[14] + yo*prj->w[16])) +
         prj->p[23];

   /* Apply reverse gnomonic projection. */
   r = sqrt(xi*xi + eta*eta);
   if (r == 0.0) {
      *phi = 0.0;
   } else {
      *phi = atan2d(xi, -eta);
   }
   *theta = atan2d(prj->w[0], r);
 
@


2.11
log
@Fixed overlap test for COP, the signs of R and sigma must agree.
@
text
@d4 1
a4 1
*   Copyright (C) 1995-1998, Mark Calabretta
d193 1
a193 1
*   $Id: proj.c,v 2.10 1999/04/06 07:57:37 mcalabre Exp mcalabre $
d1550 1
d1558 4
a1561 1
      return 2;
d2051 1
a2051 1
*      prj->w[2]   Y0 = r0*cot(theta1) + theta1
d2515 1
d2523 5
a2527 1
      return 2;
d2529 1
d2532 5
a2536 2
   if (s < -1.0 || s > 1.0) {
      return 2;
@


2.10
log
@Account for missing factor of 2 in the Airy projection.
@
text
@d193 1
a193 1
*   $Id: proj.c,v 2.9 1998/02/25 07:05:50 mcalabre Exp mcalabre $
d1644 1
a1644 1
   if (prj->flag == PRJSET && r < 0.0) {
@


2.9
log
@Updated date in copyright notice.
@
text
@d193 1
a193 1
*   $Id: proj.c,v 2.8 1998/01/30 00:27:49 mcalabre Exp mcalabre $
d1079 5
a1083 4
*      prj->w[0]   ln(cos(xi_b))/tan(xi_b)**2, where xi_b = (90-theta_b)/2
*      prj->w[1]   1/2 - prj->w[0]
*      prj->w[2]   r0*prj->w[1]
*      prj->w[3]   tol, cutoff for using small angle approximation, in
d1085 2
a1086 2
*      prj->w[4]   prj->w[1]*tol
*      prj->w[5]   (180/pi)/prj->w[1]
d1099 1
d1101 2
a1102 2
      prj->w[0] = -0.5;
      prj->w[1] =  1.0;
d1105 2
a1106 2
      prj->w[0] = log(cxi)*(cxi*cxi)/(1.0-cxi*cxi);
      prj->w[1] = 0.5 - prj->w[0];
d1111 4
a1114 4
   prj->w[2] = prj->r0 * prj->w[1];
   prj->w[3] = tol;
   prj->w[4] = prj->w[1]*tol;
   prj->w[5] = R2D/prj->w[1];
d1140 2
a1141 2
      if (xi < prj->w[3]) {
         r = xi*prj->w[2];
d1145 1
a1145 1
         r = -prj->r0*(log(cxi)/txi + prj->w[0]*txi);
d1174 1
a1174 1
   r = sqrt(x*x + y*y)/prj->r0;
d1178 2
a1179 2
   } else if (r < prj->w[4]) {
      xi = r*prj->w[5];
d1187 1
a1187 1
         r2 = -(log(x2)/txi + prj->w[0]*txi);
d1206 1
a1206 1
         rt = -(log(cxi)/txi + prj->w[0]*txi);
@


2.8
log
@Implemented the DSS projection, dssset(), dssfwd(), and dssrev().
@
text
@d4 1
a4 1
*   Copyright (C) 1995-1998 Mark Calabretta
d193 1
a193 1
*   $Id: proj.c,v 2.7 1997/03/19 05:33:01 mcalabre Exp mcalabre $
@


2.7
log
@The projection routines for AZP, TAN, SIN, ZPN, and COP now return error 2
if (phi,theta) correspond to the overlapped (far) side of the projection.
This strict bounds checking can be switched off by setting prj->flag to -1
(rather than 0) when the projections are initialized.
@
text
@d4 1
a4 1
*   Copyright (C) 1995-1997 Mark Calabretta
d67 1
d193 1
a193 1
*   $Id: proj.c,v 2.6 1997/01/02 22:08:43 mcalabre Exp mcalabre $
d3531 261
@


2.6
log
@Include wcsmath.h before proj.h for mathematical constants.
@
text
@d4 1
a4 1
*   Copyright (C) 1995,1996 Mark Calabretta
d135 2
a136 1
*         intermediaries.
d168 8
a175 6
*      Although many of the forward projections will accept values of theta
*      outside the range [-90,90] such latitudes are not meaningful and should
*      normally be marked as an error.  However, in the interests of
*      efficiency, the forward projection routines do not check for this,
*      although they do check for any invalid values of theta within the
*      range [-90,90].
d186 1
a186 1
*   Closure to a precision of at least 1.0-10 degree of longitude and latitude
a190 4
*   Notwithstanding this, absolutely no claim is made for the accuracy or
*   reliability of these routines.  They are supplied as is, with no warranty
*   of fitness for any purpose.
*
d192 1
a192 1
*   $Id: proj.c,v 2.5 1996/09/10 06:33:59 mcalabre Exp mcalabre $
d229 2
d246 11
a257 1
   prj->flag = PRJSET;
d270 1
a270 1
   double r, s;
d272 1
a272 1
   if (prj->flag != PRJSET) {
d276 3
a278 1
   s = prj->p[1] + sind(theta);
d287 4
d306 1
a306 1
   if (prj->flag != PRJSET) {
d345 6
a350 1
   prj->flag = PRJSET;
d365 1
a365 1
   if (prj->flag != PRJSET) {
d370 3
a372 1
   if (s == 0.0) return 2;
d378 4
d396 1
a396 1
   if (prj->flag != PRJSET) {
d439 6
a444 1
   prj->flag = PRJSET;
d457 1
a457 1
   double cthe, t, z;
d459 1
a459 1
   if (prj->flag != PRJSET) {
d468 1
a468 1
         z = 2.0 - t*t/2.0;
d476 20
a495 2
   *x =  prj->r0*(cthe*sind(phi) + prj->p[1]*z);
   *y = -prj->r0*(cthe*cosd(phi) + prj->p[2]*z);
d512 1
a512 1
   if (prj->flag != PRJSET) {
d613 1
d694 1
d830 6
a835 1
   prj->flag = PRJSET;
d851 1
a851 1
   if (prj->flag != PRJSET) {
d856 1
d866 4
d886 1
a886 1
   if (prj->flag != PRJSET) {
d1011 1
d1114 1
d1285 1
d1362 1
d1428 1
d1514 1
d1605 6
a1610 1
   prj->flag = PRJSET;
d1623 1
a1623 1
   double a, r;
d1625 1
a1625 1
   if (prj->flag != PRJSET) {
d1629 6
d1636 1
a1636 1
   r = prj->w[2] - prj->w[3]*tand(theta-prj->p[1]);
d1641 4
d1659 1
a1659 1
   if (prj->flag != PRJSET) {
d1717 1
d1826 1
d1960 1
d2062 1
d2163 1
d2306 1
d2385 1
d2471 1
d2560 1
d2691 1
d2989 1
d3358 1
@


2.5
log
@* In sinrev(), cscrev(), qscrev(), and tscrev(), return error 2 if (x,y) do
  not lie within the perimeter of the projection.
* In sinrev(), stop the computation of phi for the "synthesis" projection
  being applied to the pure "orthographic" case.
* Renamed variables l <-> m in the quadcube projections to accord with
  standard usage (and revised WCS draft paper).
@
text
@d193 1
a193 1
*   $Id: proj.c,v 2.4 1996/05/24 07:25:36 mcalabre Exp mcalabre $
d196 1
@


2.4
log
@Include proj.h earlier to handle const definition for K&R compiler.
@
text
@d193 1
a193 1
*   $Id: proj.c,v 2.3 1996/05/07 20:13:50 mcalabre Exp mcalabre $
d470 1
d479 2
d482 1
a482 1
         *theta = asind(sqrt(1.0 - r2));
d486 1
a523 1
   }
d525 7
a531 7
   /* Compute native coordinates. */
   xp = -y0 - prj->p[2]*z;
   yp =  x0 - prj->p[1]*z;
   if (xp == 0.0 && yp == 0.0) {
      *phi = 0.0;
   } else {
      *phi   = atan2d(yp,xp);
d2632 2
a2633 2
   l = costhe*sind(phi);
   m = costhe*cosd(phi);
d2638 1
a2638 1
   if (m > rho) {
d2640 1
a2640 1
      rho  = m;
d2642 1
a2642 1
   if (l > rho) {
d2644 1
a2644 1
      rho  = l;
d2646 1
a2646 1
   if (-m > rho) {
d2648 1
a2648 1
      rho  = -m;
d2650 1
a2650 1
   if (-l > rho) {
d2652 1
a2652 1
      rho  = -l;
d2660 2
a2661 2
      xi  =  l;
      eta = -m;
d2665 1
a2665 1
      xi  =  l;
d2670 1
a2670 1
      xi  = -m;
d2675 1
a2675 1
      xi  = -l;
d2680 1
a2680 1
      xi  =  m;
d2685 2
a2686 2
      xi  =  l;
      eta =  m;
d2780 5
a2784 1
   if (xf > 5.0) {
d2788 1
d2792 1
d2795 2
d2798 1
d2802 1
d2836 2
a2837 2
      l =  a*n;
      m = -b*n;
d2839 4
d2844 1
a2844 1
      l =  a*m;
a2845 4
   } else if (face == 2) {
      l =  1.0/sqrt(a*a + b*b + 1.0);
      m = -a*l;
      n =  b*l;
d2847 4
d2852 1
a2852 1
      l =  a*m;
a2853 4
   } else if (face == 4) {
      l = -1.0/sqrt(a*a + b*b + 1.0);
      m = -a*l;
      n = -b*l;
d2856 2
a2857 2
      l = -a*n;
      m = -b*n;
d2863 1
a2863 1
      *phi = atan2d(l, m);
d2921 2
a2922 2
   l = costhe*sind(phi);
   m = costhe*cosd(phi);
d2927 1
a2927 1
   if (m > rho) {
d2929 1
a2929 1
      rho  = m;
d2931 1
a2931 1
   if (l > rho) {
d2933 1
a2933 1
      rho  = l;
d2935 1
a2935 1
   if (-m > rho) {
d2937 1
a2937 1
      rho  = -m;
d2939 1
a2939 1
   if (-l > rho) {
d2941 1
a2941 1
      rho  = -l;
d2951 2
a2952 2
      xi  =  l;
      eta = -m;
d2961 1
a2961 1
      xi  =  l;
d2975 1
a2975 1
      xi  = -m;
d2988 1
a2988 1
      xi  = -l;
d3001 1
a3001 1
      xi  =  m;
d3014 2
a3015 2
      xi  =  l;
      eta =  m;
d3090 5
a3094 1
   if (xf > 5.0) {
d3098 1
d3102 1
d3105 2
d3108 1
d3112 1
d3163 4
d3168 1
a3168 1
         if (xf < 0.0) l = -l;
d3170 7
d3178 3
a3180 3
         m = w;
         if (yf > 0.0) m = -m;
         l = -m*psi;
d3182 1
a3182 1
   } else if (face == 1) {
d3186 2
a3187 2
         if (xf < 0.0) l = -l;
         n = l*psi;
d3191 1
a3191 1
         l = n*psi;
d3193 2
a3194 2
   } else if (face == 2) {
      l =  rho;
d3204 1
a3204 1
   } else if (face == 3) {
d3208 2
a3209 2
         if (xf > 0.0) l = -l;
         n = -l*psi;
d3213 1
a3213 1
         l = -n*psi;
d3215 2
a3216 2
   } else if (face == 4) {
      l = -rho;
d3220 1
a3220 1
         n = m*psi;
a3221 7
         n = w;
         if (yf < 0.0) n = -n;
         m = n*psi;
      }
   } else if (face == 5) {
      n = -rho;
      if (direct) {
d3223 1
a3223 1
         if (xf < 0.0) l = -l;
a3224 4
      } else {
         m = w;
         if (yf < 0.0) m = -m;
         l = m*psi;
d3231 1
a3231 1
      *phi = atan2d(l, m);
d3283 2
a3284 2
   l = costhe*sind(phi);
   m = costhe*cosd(phi);
d3289 1
a3289 1
   if (m > rho) {
d3291 1
a3291 1
      rho  = m;
d3293 1
a3293 1
   if (l > rho) {
d3295 1
a3295 1
      rho  = l;
d3297 1
a3297 1
   if (-m > rho) {
d3299 1
a3299 1
      rho  = -m;
d3301 1
a3301 1
   if (-l > rho) {
d3303 1
a3303 1
      rho  = -l;
d3311 2
a3312 2
      xf =  l/rho;
      yf = -m/rho;
d3316 1
a3316 1
      xf =  l/rho;
d3321 1
a3321 1
      xf = -m/rho;
d3326 1
a3326 1
      xf = -l/rho;
d3331 1
a3331 1
      xf =  m/rho;
d3336 2
a3337 2
      xf =  l/rho;
      yf =  m/rho;
d3379 5
a3383 1
   if (xf > 5.0) {
d3386 3
a3388 3
      l  = -1.0/sqrt(1.0 + xf*xf + yf*yf);
      m  = -l*xf;
      n  = -l*yf;
d3390 1
d3393 3
a3395 3
      m  = -1.0/sqrt(1.0 + xf*xf + yf*yf);
      l  =  m*xf;
      n  = -m*yf;
d3397 1
d3400 5
a3404 3
      l  =  1.0/sqrt(1.0 + xf*xf + yf*yf);
      m  = -l*xf;
      n  =  l*yf;
d3406 1
d3410 2
a3411 2
      l  =  n*xf;
      m  = -n*yf;
d3413 1
d3417 2
a3418 2
      l  = -n*xf;
      m  = -n*yf;
d3421 3
a3423 3
      m  =  1.0/sqrt(1.0 + xf*xf + yf*yf);
      l  =  m*xf;
      n  =  m*yf;
d3429 1
a3429 1
      *phi = atan2d(l, m);
@


2.3
log
@Fixed two bugs in zpnset().
Added const-correctness to function arguments.
Added external arrays of error messages indexed by function return value.
@
text
@d193 1
a193 1
*   $Id: proj.c,v 2.2 1995/12/22 02:38:33 mcalabre Exp mcalabre $
d196 2
a212 2

#include "proj.h"
@


2.2
log
@Amended the conic projections to allow for sigma < 0.  Likewise for
Bonne's projection.
@
text
@d4 1
a4 1
*   Copyright (C) 1995, Mark Calabretta
d63 1
a63 1
*      molset molfwd molrev   MOL: Molweide
d90 3
a92 2
*      phi,     double   Longitude and latitude of the projected point in
*      theta             native spherical coordinates, in degrees.
d112 2
a113 1
*      x,y      double   Projected coordinates.
d142 3
a144 1
*         to the PROJPn keywords in FITS.
d193 1
a193 1
*   $Id: proj.c,v 2.1 1995/11/09 03:15:35 mcalabre Exp mcalabre $
d196 16
a213 6
#ifndef __STDC__
#ifndef const
#define const
#endif
#endif

d253 1
a253 1
double phi, theta, *x, *y;
d255 1
d280 1
a280 1
double x, y, *phi, *theta;
d282 1
d335 1
a335 1
double phi, theta, *x, *y;
d337 1
d360 1
a360 1
double x, y, *phi, *theta;
d362 1
d418 1
a418 1
double phi, theta, *x, *y;
d420 1
d452 1
a452 1
double x, y, *phi, *theta;
d454 1
d565 1
a565 1
double phi, theta, *x, *y;
d567 1
d592 1
a592 1
double x, y, *phi, *theta;
d594 1
d645 1
a645 1
double phi, theta, *x, *y;
d647 1
d667 1
a667 1
double x, y, *phi, *theta;
d669 1
d692 3
d714 1
a714 1
   for (k = 9; k >= 0 && prj->p[k] != 0.0; k--);
d740 1
a740 1
      if (i == 10) {
d781 1
a781 1
double phi, theta, *x, *y;
d783 1
d810 1
a810 1
double x, y, *phi, *theta;
d812 1
d951 1
a951 1
double phi, theta, *x, *y;
d953 1
d973 1
a973 1
double x, y, *phi, *theta;
d975 1
d1053 1
a1053 1
double phi, theta, *x, *y;
d1055 1
d1089 1
a1089 1
double x, y, *phi, *theta;
d1091 1
d1223 1
a1223 1
double phi, theta, *x, *y;
d1225 1
d1249 1
a1249 1
double x, y, *phi, *theta;
d1251 1
d1299 1
a1299 1
double phi, theta, *x, *y;
d1301 1
d1318 1
a1318 1
double x, y, *phi, *theta;
d1320 1
d1364 1
a1364 1
double phi, theta, *x, *y;
d1366 1
d1387 1
a1387 1
double x, y, *phi, *theta;
d1389 1
d1449 1
a1449 1
double phi, theta, *x, *y;
d1451 1
d1468 1
a1468 1
double x, y, *phi, *theta;
d1470 1
d1540 1
a1540 1
double phi, theta, *x, *y;
d1542 1
d1564 1
a1564 1
double x, y, *phi, *theta;
d1566 1
d1636 1
a1636 1
double phi, theta, *x, *y;
d1638 1
d1660 1
a1660 1
double x, y, *phi, *theta;
d1662 1
d1744 1
a1744 1
double phi, theta, *x, *y;
d1746 1
d1772 1
a1772 1
double x, y, *phi, *theta;
d1774 1
d1877 1
a1877 1
double phi, theta, *x, *y;
d1879 1
d1909 1
a1909 1
double x, y, *phi, *theta;
d1911 1
d1978 1
a1978 1
double phi, theta, *x, *y;
d1980 1
d2007 1
a2007 1
double x, y, *phi, *theta;
d2009 1
d2078 1
a2078 1
double phi, theta, *x, *y;
d2080 1
d2109 1
a2109 1
double x, y, *phi, *theta;
d2111 1
d2220 1
a2220 1
double phi, theta, *x, *y;
d2222 1
d2239 1
a2239 1
double x, y, *phi, *theta;
d2241 1
d2298 1
a2298 1
double phi, theta, *x, *y;
d2300 1
d2320 1
a2320 1
double x, y, *phi, *theta;
d2322 1
d2383 1
a2383 1
double phi, theta, *x, *y;
d2385 1
d2406 1
a2406 1
double x, y, *phi, *theta;
d2408 1
d2471 1
a2471 1
double phi, theta, *x, *y;
d2473 1
d2519 1
a2519 1
double x, y, *phi, *theta;
d2521 1
d2601 1
a2601 1
double phi, theta, *x, *y;
d2603 1
d2732 1
a2732 1
double x, y, *phi, *theta;
d2734 1
d2888 1
a2888 1
double phi, theta, *x, *y;
d2890 1
d3061 1
a3061 1
double x, y, *phi, *theta;
d3063 1
d3246 1
a3246 1
double phi, theta, *x, *y;
d3248 1
d3342 1
a3342 1
double x, y, *phi, *theta;
d3344 1
@


2.1
log
@Added a special-case calculation to sinrev() for simple orthographic
projections.
@
text
@d189 1
a189 1
*   $Id: proj.c,v 2.0 1995/09/11 09:06:43 mcalabre Exp mcalabre $
d1461 1
a1461 1
*      prj->w[2]   Y0 = 0
d1475 1
a1475 1
   if (prj->w[0] <= 0.0) {
a1479 1
   prj->w[2] = 0.0;
d1489 2
d1510 1
a1510 1
   r = prj->w[3]*(prj->w[5] - tand(theta-prj->p[1]));
d1512 2
a1513 2
   *x =  r*sind(a);
   *y = -r*cosd(a);
d1526 1
a1526 1
   double a, r;
d1532 4
a1535 1
   r = sqrt(x*x + y*y);
d1539 1
a1539 1
      a = atan2d(x, -y);
d1560 2
a1561 2
*      prj->w[2]   Y0 = sigma - 90 + delta*cot(delta)*cot(sigma)
*      prj->w[3]   Y0 + 90
d1577 1
a1577 1
   if (prj->w[0] <= 0.0) {
d1580 1
d1582 2
a1584 3
   prj->w[3] = prj->p[1] + prj->r0*cosd(prj->p[2])*cosd(prj->p[1])/prj->w[0];
   prj->w[2] = prj->w[3] - 90.0;

d1606 1
a1606 1
   *x =           r*sind(a);
d1628 2
d1633 1
a1633 1
      a = atan2d(x, dy);
d1654 7
a1660 4
*      prj->w[2]   Y0 = r0*sqrt(1 + sin(theta1)*sin(theta2) - 2C)/C
*      prj->w[3]   (1 + sin(theta1)*sin(theta2))*(r0/C)**2
*      prj->w[4]   2*r0**2/C
*      prj->w[5]   C/(2*r0**2)
d1668 1
a1668 1
   double theta1, theta2, w;
d1676 1
a1676 1
   if (prj->w[0] <= 0.0) {
d1682 8
a1689 7
   w = 1.0 + sind(theta1)*sind(theta2);
   prj->w[2] = prj->r0*sqrt(w - 2.0*prj->w[0])/prj->w[0];
   prj->w[3] = prj->r0/prj->w[0], prj->w[3] *= w*prj->w[3];

   prj->w[4] = 2.0*prj->r0*prj->r0/prj->w[0];
   prj->w[5] = 1.0/prj->w[4];
   prj->w[6] = prj->r0*sqrt(w + prj->w[0]+prj->w[0])/prj->w[0];
d1711 1
a1711 1
      r = prj->w[6];
d1713 1
a1713 1
      r = sqrt(prj->w[3] - prj->w[4]*sind(theta));
d1716 1
a1716 1
   *x =           r*sind(a);
d1737 1
a1737 1
   dy = prj->w[2]-y;
d1739 2
d1744 1
a1744 1
      a = atan2d(x, dy);
d1748 1
a1748 1
   if (fabs(r-prj->w[6]) < tol) {
d1751 1
a1751 1
      w = (prj->w[3] - r*r)*prj->w[5];
d1782 3
a1784 3
*      prj->w[2]   Y0 = 0
*      prj->w[3]   (r0*cos(theta1)/C)/tan(tau1)**C
*      prj->w[4]   C/(r0*cos(theta1))*tan(tau1)**C
d1809 1
a1809 1
   if (prj->w[0] <= 0.0) {
a1813 1
   prj->w[2] = 0.0;
d1819 1
d1842 3
d1847 3
a1849 1
   r = prj->w[3]*pow(tand((90.0 - theta)/2.0),prj->w[0]);
d1851 2
a1852 2
   *x =  r*sind(a);
   *y = -r*cosd(a);
d1865 1
a1865 1
   double a, r;
d1871 4
a1874 1
   r = sqrt(x*x + y*y);
d1878 1
a1878 1
      a = atan2d(x, -y);
d1881 10
a1890 2
   *phi   = a*prj->w[1];
   *theta = 90.0 - 2.0*atand(pow(r*prj->w[4],prj->w[1]));
d1903 2
a1904 1
*      prj->w[0]   Y0 = r0*cot(theta1) + theta1
a1913 1
      prj->w[0] = prj->r0*cosd(prj->p[1])/sind(prj->p[1]) + prj->p[1];
d1915 1
a1916 1
      prj->w[0] = prj->r0*(cosd(prj->p[1])/sind(prj->p[1]) + prj->p[1]*D2R);
d1918 1
d1944 1
a1944 1
   r = prj->w[0] - theta*prj->w[1];
d1947 2
a1948 2
   *x =           r*sind(a);
   *y = prj->w[0] - r*cosd(a);
d1972 1
a1972 1
   dy = prj->w[0]-y;
d1974 2
d1979 1
a1979 1
      a = atan2d(x, dy);
a1980 1
   if (prj->p[1] < 0.0) r = -r;
d1982 1
a1982 1
   *theta = (prj->w[0] - r)/prj->w[1];
@


2.0
log
@WCSLIB 2.0
@
text
@d189 1
a189 1
*   $Id: proj.c,v 1.3 1995/09/11 09:06:18 mcalabre Exp mcalabre $
d449 12
a460 4
   if (r2 < 1.0e-10) {
      /* Use small angle formula. */
      z = -r2/2.0;
      *theta = 90.0 - R2D*sqrt(r2/(1.0 - x0*prj->p[1] + y0*prj->p[2]));
d463 4
a466 1
      sxy = 2.0*(prj->p[1]*x0 - prj->p[2]*y0);
d468 2
a469 4
      a = prj->w[3];
      b = -(sxy + prj->w[2]);
      c = r2 + sxy + prj->w[4];
      d = b*b - 2.0*a*c;
d471 10
a480 5
      /* Check for a solution. */
      if (d < 0.0) {
         return 2;
      }
      d = sqrt(d);
d482 10
a491 9
      /* Choose solution closest to pole. */
      sth1 = (-b + d)/a;
      sth2 = (-b - d)/a;
      sth = (sth1>sth2) ? sth1 : sth2;
      if (sth > 1.0) {
         if (sth-1.0 < tol) {
            sth = 1.0;
         } else {
            sth = (sth1<sth2) ? sth1 : sth2;
d493 6
a499 6
      if (sth > 1.0 || sth < -1.0) {
         return 2;
      }

      *theta = asind(sth);
      z = sth - 1.0;
@


1.3
log
@Defined tol in sinrev().
@
text
@d189 1
a189 1
*   $Id: proj.c,v 1.2 1995/09/11 08:31:21 mcalabre Exp mcalabre $
@


1.2
log
@1) Improve precision by using small angle formulae in SIN, AIR, and QSC
   and avoid floating underflows in CSC.
2) Revise the use of p[1] and p[2] for the conics, these now contain the
   half-sum and half-differences of the standard latitudes rather than the
   standard latitudes themselves.
@
text
@d189 1
a189 1
*   $Id: proj.c,v 1.1 1995/01/31 03:13:15 mcalabre Exp mcalabre $
d437 1
@


1.1
log
@Initial revision
@
text
@d35 2
a36 4
*   Each projection is implemented via separate functions for the forward
*   (*fwd) and reverse (*rev) transformation.  A separate function (*set)
*   initializes intermediate values formed from the projection parameters and
*   need not be called explicitly - see the explanation of prj.flag below.
d38 4
d56 1
a56 1
*      coeset coefwd coerev   CEA: conic equal area
d68 18
a85 2
*   Forward transformation
*   ----------------------
d105 2
a106 2
*   Reverse transformation
*   ----------------------
d126 2
a127 2
*   Projection parameters; prj
*   --------------------------
d130 5
a134 4
*      prj.p[10]
*         The first 10 elements contain projection parameters which correspond
*         to the PROJPn keywords in FITS.
*      prj.r0
d138 3
a140 4
*      prj.flag
*         This flag must be set to zero whenever any of prj.p[10] or prj.r0
*         are set or changed.  This signals the initialization routines to
*         recompute intermediaries.
d147 2
a148 2
*      prj.w[10]
*      prj.n
d151 2
a152 2
*   Usage of the prj.p[] array as it applies to each projection is described
*   in the prologue to each trio of projection routines.
d189 1
a189 1
*   $Id$
d404 1
a404 1
   double z;
d410 15
a424 3
   z =  sind(theta) - 1.0;
   *x =  prj->r0*(cosd(theta)*sind(phi) + prj->p[1]*z);
   *y = -prj->r0*(cosd(theta)*cosd(phi) + prj->p[2]*z);
d437 1
a437 1
   double a, b, c, d, pxy, sth, sth1, sth2, x0, xp, y0, yp;
d446 20
a465 5
   pxy = 2.0*(prj->p[1]*x0 - prj->p[2]*y0);
   a = prj->w[3];
   b = -(pxy + prj->w[2]);
   c = (x0*x0 + y0*y0) + pxy + prj->w[4];
   d = b*b - 2.0*a*c;
d467 14
a480 5
   /* Check for a solution. */
   if (d < 0.0) {
      return 2;
   }
   d = sqrt(d);
d482 2
a483 7
   /* Choose solution closest to pole. */
   sth1 = (-b + d)/a;
   sth2 = (-b - d)/a;
   sth = (sth1>sth2) ? sth1 : sth2;
   if (sth > 1.0) sth = (sth1<sth2) ? sth1 : sth2;
   if (sth > 1.0 || sth < -1.0) {
      return 2;
d487 2
a488 2
   xp = -y0 - prj->p[2]*(sth-1.0);
   yp =  x0 - prj->p[1]*(sth-1.0);
a493 1
   *theta = asind(sth);
d964 6
d977 1
d984 1
d988 1
d993 5
d1010 1
a1010 1
   double cxi, r, txi;
d1019 8
a1026 3
      cxi = cosd((90.0 - theta)/2.0);
      txi = sqrt(1.0-cxi*cxi)/cxi;
      r = -prj->r0*(log(cxi)/txi + prj->w[0]*txi);
d1057 2
d1210 1
a1210 1
   eta   = y*prj->w[3];
d1437 3
a1439 2
*      prj->p[1:2] Latitudes of the standard parallels, theta1 and theta2,
*                  in degrees.
d1443 1
a1443 1
*      prj->w[0]   C  = sin((theta1 + theta2)/2)
d1446 3
a1448 4
*      prj->w[3]   (theta1 + theta2)/2
*      prj->w[4]   r0*cos((theta2 - theta1)/2)
*      prj->w[5]   1/(r0*cos((theta2 - theta1)/2))
*      prj->w[6]   cot((theta1 + theta2)/2)
d1458 1
a1458 1
   prj->w[0] = sind((prj->p[2] + prj->p[1])/2.0);
a1464 1
   prj->w[3] = (prj->p[2] + prj->p[1])/2.0;
d1466 2
a1467 2
   prj->w[4] = prj->r0*cosd((prj->p[2] - prj->p[1])/2.0);
   if (prj->w[4] == 0.0) {
d1471 2
a1472 2
   prj->w[5] = 1.0/prj->w[4];
   prj->w[6] = 1.0/tand(prj->w[3]);
d1493 1
a1493 1
   r = prj->w[4]*(prj->w[6] - tand(theta-prj->w[3]));
d1523 1
a1523 1
   *theta = prj->w[3] + atand(prj->w[6] - r*prj->w[5]);
d1532 3
a1534 2
*      prj->p[1:2] Latitudes of the standard parallels, theta1 and theta2,
*                  in degrees.
d1538 1
a1538 3
*      prj->w[0]   C = r0*sin(sigma)*sin(delta)/delta, where
*                    sigma = (theta1+theta2)/2
*                    delta = (theta2-theta1)/2
d1540 1
a1540 1
*      prj->w[2]   Y0 = sigma - 90 +alpha*cot(alpha)*cot(sigma)
a1548 2
   double thedif, thesum;

d1551 2
a1552 5
   thesum = (prj->p[2] + prj->p[1])/2.0;
   thedif = (prj->p[2] - prj->p[1])/2.0;

   if (thedif == 0.0) {
      prj->w[0] = prj->r0*sind(thesum)*D2R;
d1554 1
a1554 1
      prj->w[0] = prj->r0*sind(thesum)*sind(thedif)/thedif;
d1562 1
a1562 1
   prj->w[3] = thesum + prj->r0*cosd(thedif)*cosd(thesum)/prj->w[0];
d1621 1
a1621 1
*   CEA: conic equal area projection.
d1624 3
a1626 2
*      prj->p[1:2] Latitudes of the standard parallels, theta1 and theta2,
*                  in degrees.
d1643 1
a1643 1
   double w;
d1647 4
a1650 1
   prj->w[0] = (sind(prj->p[1]) + sind(prj->p[2]))/2.0;
d1657 1
a1657 1
   w = 1.0 + sind(prj->p[1])*sind(prj->p[2]);
d1744 3
a1746 2
*      prj->p[1:2] Latitudes of the standard parallels, theta1 and theta2,
*                  in degrees.
d1764 1
a1764 1
   double cos1, cos2, tan1, tan2;
d1768 2
a1769 2
   tan1 = tand((90.0 - prj->p[1])/2.0);
   cos1 = cosd(prj->p[1]);
d1771 5
a1775 2
   if (prj->p[1] == prj->p[2]) {
      prj->w[0] = sind(prj->p[1]);
d1777 2
a1778 2
      tan2 = tand((90.0 - prj->p[2])/2.0);
      cos2 = cosd(prj->p[2]);
d2502 1
a2502 1
   float a, a2, a2b2, a4, b, b2, b4, ca2, cb2, x0, xf, y0, yf;
a2584 3
   a4 = a2*a2;
   b4 = b2*b2;
   a2b2 = a2*b2;
d2588 6
d2784 1
a2784 1
   double chi, costhe, eta, l, m, n, psi, rho, x0, xf, xi, y0, yf;
d2825 2
d2830 5
d2840 9
d2854 8
d2867 8
d2880 8
d2893 5
d2908 1
a2908 1
      xf  = -sqrt((1.0-rho)/(1.0-1.0/sqrt(1.0+chi)));
d2913 1
a2913 1
      xf  =  sqrt((1.0-rho)/(1.0-1.0/sqrt(1.0+chi)));
d2918 1
a2918 1
      yf  = -sqrt((1.0-rho)/(1.0-1.0/sqrt(1.0+chi)));
d2923 1
a2923 1
      yf  =  sqrt((1.0-rho)/(1.0-1.0/sqrt(1.0+chi)));
d2956 1
a2956 1
   double chi, l, m, n, psi, rho, xf, yf, w;
d2991 1
d2996 2
a2997 1
         rho = 1.0 - xf*xf*(1.0 - 1.0/sqrt(1.0 + chi));
d3004 1
d3009 2
a3010 1
         rho = 1.0 - yf*yf*(1.0 - 1.0/sqrt(1.0 + chi));
d3014 2
a3015 2
   if (fabs(rho) >= 1.0) {
      if (fabs(rho) >= 1.0+tol) {
d3018 4
a3021 2
      rho = copysign(1.0,rho);
      w = 0.0;
d3023 1
a3023 1
      w = sqrt((1.0-rho*rho)/chi);
a3233 1
   int   face;
d3244 1
a3244 1
      face = 4;
d3250 1
a3250 1
      face = 3;
d3256 1
a3256 1
      face = 2;
d3262 1
a3262 1
      face = 0;
d3268 1
a3268 1
      face = 5;
d3274 1
a3274 1
      face = 1;
@
