From 76d1e8c3df800b56457e046aeea426d2cce751ee Mon Sep 17 00:00:00 2001 From: "Gregory J. Ward" Date: Wed, 12 Jan 2022 21:07:39 +0000 Subject: [PATCH] refactor: created cropview() function to manage view sections --- src/common/image.c | 94 +++++++++++++++++++++++++++++++++++++++++----- src/common/view.h | 3 +- src/util/rpiece.c | 60 ++++++----------------------- 3 files changed, 98 insertions(+), 59 deletions(-) diff --git a/src/common/image.c b/src/common/image.c index 7cffc087f..8579e094e 100644 --- a/src/common/image.c +++ b/src/common/image.c @@ -1,5 +1,5 @@ #ifndef lint -static const char RCSid[] = "$Id: image.c,v 2.52 2021/02/12 00:47:08 greg Exp $"; +static const char RCSid[] = "$Id: image.c,v 2.53 2022/01/12 21:07:39 greg Exp $"; #endif /* * image.c - routines for image generation. @@ -63,8 +63,8 @@ VIEW *v return(ill_horiz); if (v->vert >= 180.0-FTINY) return(ill_vert); - v->hn2 = 2.0 * tan(v->horiz*(PI/180.0/2.0)); - v->vn2 = 2.0 * tan(v->vert*(PI/180.0/2.0)); + v->hn2 = 2.0 * tan(v->horiz*(PI/360.)); + v->vn2 = 2.0 * tan(v->vert*(PI/360.)); break; case VT_CYL: /* cylindrical panorama */ if (v->horiz > 360.0+FTINY) @@ -72,7 +72,7 @@ VIEW *v if (v->vert >= 180.0-FTINY) return(ill_vert); v->hn2 = v->horiz * (PI/180.0); - v->vn2 = 2.0 * tan(v->vert*(PI/180.0/2.0)); + v->vn2 = 2.0 * tan(v->vert*(PI/360.)); break; case VT_ANG: /* angular fisheye */ if (v->horiz > 360.0+FTINY) @@ -87,18 +87,18 @@ VIEW *v return(ill_horiz); if (v->vert > 180.0+FTINY) return(ill_vert); - v->hn2 = 2.0 * sin(v->horiz*(PI/180.0/2.0)); - v->vn2 = 2.0 * sin(v->vert*(PI/180.0/2.0)); + v->hn2 = 2.0 * sin(v->horiz*(PI/360.)); + v->vn2 = 2.0 * sin(v->vert*(PI/360.)); break; case VT_PLS: /* planispheric fisheye */ if (v->horiz >= 360.0-FTINY) return(ill_horiz); if (v->vert >= 360.0-FTINY) return(ill_vert); - v->hn2 = 2.*sin(v->horiz*(PI/180.0/2.0)) / - (1.0 + cos(v->horiz*(PI/180.0/2.0))); - v->vn2 = 2.*sin(v->vert*(PI/180.0/2.0)) / - (1.0 + cos(v->vert*(PI/180.0/2.0))); + v->hn2 = 2.*sin(v->horiz*(PI/360.)) / + (1.0 + cos(v->horiz*(PI/360.))); + v->vn2 = 2.*sin(v->vert*(PI/360.)) / + (1.0 + cos(v->vert*(PI/360.))); break; default: return("unknown view type"); @@ -120,6 +120,80 @@ VIEW *v } +char * +cropview( /* crop a view to the indicated bounds */ +VIEW *v, +double x0, +double y0, +double x1, +double y1 +) +{ + static char ill_crop[] = "zero crop area"; + static char ill_hemi[] = "illegal crop for hemispherical view"; + double d; + /* order crop extrema */ + if (x0 > x1) { d=x0; x0=x1; x1=d; } + if (y0 > y1) { d=y0; y0=y1; y1=d; } + + d = x1 - x0; + if (d == .0) + return(ill_crop); + if (!FABSEQ(d, 1.)) /* adjust horizontal size? */ + switch (v->type) { + case VT_PER: + v->horiz = 360./PI*atan( d*tan(PI/360.*v->horiz) ); + break; + case VT_PAR: + case VT_ANG: + case VT_CYL: + v->horiz *= d; + break; + case VT_HEM: + d *= sin(PI/360.*v->horiz); + if (d > 1.) + return(ill_hemi); + v->horiz = 360./PI*asin( d ); + break; + case VT_PLS: + d *= sin(PI/360.*v->horiz) / + (1. + cos(PI/360.*v->horiz)); + v->horiz = 360./PI*acos( (1. - d*d) / (1. + d*d) ); + break; + } + d = y1 - y0; + if (d == .0) + return(ill_crop); + if (!FABSEQ(d, 1.)) /* adjust vertical size? */ + switch (v->type) { + case VT_PER: + case VT_CYL: + v->vert = 360./PI*atan( d*tan(PI/360.*v->vert) ); + break; + case VT_PAR: + case VT_ANG: + v->vert *= d; + break; + case VT_HEM: + d *= sin(PI/360.*v->vert); + if (d > 1.) + return(ill_hemi); + v->vert = 360./PI*asin( d ); + break; + case VT_PLS: + d *= sin(PI/360.*v->vert) / + (1. + cos(PI/360.*v->vert)); + v->vert = 360./PI*acos( (1. - d*d) / (1. + d*d) ); + break; + } + /* fix offsets */ + v->hoff = ((x0 + x1)*.5 - .5 + v->hoff) / (x1 - x0); + v->voff = ((y0 + y1)*.5 - .5 + v->voff) / (y1 - y0); + + return(setview(v)); /* final error checks & set-up */ +} + + void normaspect( /* fix pixel aspect or resolution */ double va, /* view aspect ratio */ diff --git a/src/common/view.h b/src/common/view.h index 07dd57ab0..64a5e161f 100644 --- a/src/common/view.h +++ b/src/common/view.h @@ -1,4 +1,4 @@ -/* RCSid $Id: view.h,v 2.21 2021/12/03 18:10:48 greg Exp $ */ +/* RCSid $Id: view.h,v 2.22 2022/01/12 21:07:39 greg Exp $ */ /* * view.h - header file for image generation. * @@ -59,6 +59,7 @@ extern VIEW stdview; #define VL_BEYOND 0x8 /* point is beyond aft clipping plane */ extern char *setview(VIEW *v); +extern char *cropview(VIEW *v, double x0, double y0, double x1, double y1); extern void normaspect(double va, double *ap, int *xp, int *yp); extern double viewray(FVECT orig, FVECT direc, VIEW *v, double x, double y); extern int jitteraperture(FVECT orig, FVECT direc, VIEW *v, double dia); diff --git a/src/util/rpiece.c b/src/util/rpiece.c index 71c66d980..f27fb0ac1 100644 --- a/src/util/rpiece.c +++ b/src/util/rpiece.c @@ -1,5 +1,5 @@ #ifndef lint -static const char RCSid[] = "$Id: rpiece.c,v 2.58 2020/02/28 05:18:49 greg Exp $"; +static const char RCSid[] = "$Id: rpiece.c,v 2.59 2022/01/12 21:07:39 greg Exp $"; #endif /* * Generate sections of a picture. @@ -298,12 +298,12 @@ init( /* set up output file and start rpict */ fprintf(fp, "SOFTWARE= %s\n", VersionID); fputs(VIEWSTR, fp); fprintview(&ourview, fp); - putc('\n', fp); + fputc('\n', fp); fputnow(fp); if (pixaspect < .99 || pixaspect > 1.01) fputaspect(pixaspect, fp); fputformat(COLRFMT, fp); - putc('\n', fp); + fputc('\n', fp); fprtresolu(hres*hmult, vres*vmult, fp); } else if ((outfd = open(outfile, O_RDWR)) >= 0) { dolock(outfd, F_RDLCK); @@ -461,57 +461,21 @@ cleanup( /* close rpict process and clean up */ static void rpiece(void) /* render picture piece by piece */ { + char *err; VIEW pview; int xorg, yorg; - /* compute view parameters */ - pview = ourview; - switch (ourview.type) { - case VT_PER: - pview.horiz = (2.*180./PI)*atan( - tan((PI/180./2.)*ourview.horiz)/hmult ); - pview.vert = (2.*180./PI)*atan( - tan((PI/180./2.)*ourview.vert)/vmult ); - break; - case VT_PAR: - case VT_ANG: - pview.horiz = ourview.horiz / hmult; - pview.vert = ourview.vert / vmult; - break; - case VT_CYL: - pview.horiz = ourview.horiz / hmult; - pview.vert = (2.*180./PI)*atan( - tan((PI/180./2.)*ourview.vert)/vmult ); - break; - case VT_HEM: - pview.horiz = (2.*180./PI)*asin( - sin((PI/180./2.)*ourview.horiz)/hmult ); - pview.vert = (2.*180./PI)*asin( - sin((PI/180./2.)*ourview.vert)/vmult ); - break; - case VT_PLS: - pview.horiz = sin((PI/180./2.)*ourview.horiz) / - (1.0 + cos((PI/180./2.)*ourview.horiz)) / hmult; - pview.horiz *= pview.horiz; - pview.horiz = (2.*180./PI)*acos((1. - pview.horiz) / - (1. + pview.horiz)); - pview.vert = sin((PI/180./2.)*ourview.vert) / - (1.0 + cos((PI/180./2.)*ourview.vert)) / vmult; - pview.vert *= pview.vert; - pview.vert = (2.*180./PI)*acos((1. - pview.vert) / - (1. + pview.vert)); - break; - default: - fprintf(stderr, "%s: unknown view type '-vt%c'\n", - progname, ourview.type); - exit(cleanup(1)); - } /* render each piece */ while (nextpiece(&xorg, &yorg)) { - pview.hoff = ourview.hoff*hmult + xorg - 0.5*(hmult-1); - pview.voff = ourview.voff*vmult + yorg - 0.5*(vmult-1); + pview = ourview; + err = cropview(&pview, (double)xorg/hmult, (double)yorg/vmult, + (xorg+1.)/hmult, (yorg+1.)/vmult); + if (err != NULL) { + fprintf(stderr, "%s: %s\n", progname, err); + exit(cleanup(1)); + } fputs(VIEWSTR, torp); fprintview(&pview, torp); - putc('\n', torp); + fputc('\n', torp); fflush(torp); /* assigns piece to rpict */ putpiece(xorg, yorg); /* place piece in output */ }