clippoly-pl11/0040755000076400010400000000000010214341720014456 5ustar KlamerAdministratorsclippoly-pl11/.pure0100644000076400010400000000000010210642561015420 0ustar KlamerAdministratorsclippoly-pl11/case10100644000076400010400000000036210210642561015376 0ustar KlamerAdministrators 223 686 233 230 673 228 633 436 357 302 351 448 487 448 471 692 PolyMagic 397 604 397 372 723 374 723 608 PolyMagic clippoly-pl11/case20100644000076400010400000000032210210642561015373 0ustar KlamerAdministrators 137 424 535 270 483 522 805 678 165 804 PolyMagic 249 666 363 882 463 640 565 1028 187 1016 PolyMagic clippoly-pl11/case30100644000076400010400000000033510210642561015400 0ustar KlamerAdministrators 799993 400015 800020 400003 800007 399985 799980 399997 PolyMagic 799990 399996 799986 400007 800006 400011 800010 400000 PolyMagic clippoly-pl11/CLASSES0100644000076400010400000000165010210642133015473 0ustar KlamerAdministratorsConstPolyIter: A PolyIter which is constructed of a const Poly. DirPolyIter: Provides an iterator for a Poly which can go forward and backwards. Edge: A side of a polygon consisting of two Point's. I'm afraid this one is no longer used. NodePEdge: Represents an edge from a Poly. Point: A 2-D point. Some arithmetic operations are overloaded. PointList: List of Point's. I'm afraid that this one is no longer used. PointListIter: An iterator for a PointList. Poly: A polygon. Consist of a double linked list of PolyNode's. PolyIter: Provides an iterator over a Poly. PolyNode: A single point in a Poly. PosAdder: A 'boolean' which can have the values UnKnown, True and False. Set: A template implementation of a Set. Main design issue: fast to implement :-) SetIter: Iterator for a Set. RSet, RSetIter: Similar to the Set classes, but handle data by reference. clippoly-pl11/err.30100644000076400010400000000314010210642561015330 0ustar KlamerAdministrators.TH ERR 3 "25 July 1990" local "Utility routines" .SH NAME warning, error, fatal \- consistent error handling .SH SYNOPSIS #include .br #include .LP warning( fmt, ... ) .br char *fmt; .LP error( fmt, ... ) .br char *fmt; .LP fatal( fmt, ... ) .br char *fmt; .LP fatal_nr( nr, fmt, ... ) .br int nr; .br char *fmt; .LP extern int err_nr_errors, err_nr_warnings; .br extern int *err_warning_jmpbuf, *err_error_jmpbuf, *err_fatal_jmpbuf; .SH DESCRIPTION These routines provide a way to handle all kind of errors in a consistent way. The differences between the routines are: .I warning() is intended to be used when the error encountered is to be reported, but will probably not harm the result. .I error() should be called when the error will harm the result (it will probably not be valid), but execution can continue; .I fatal() should be called when the error means that the program can not continue. .I fatal() will exit with a return value of 1; .I fatal_nr() will exit with the return value .I nr. .br The integers .I err_nr_warnings and .I err_nr_errors hold the number of time these routines are called. .br The .I err_*_jmpbuf variables are pointers to a .I jmp_buf. When these are not NULL they should point to a valid .I jmp_buf for use by .I longjmp(3). In this way the program can catch errors as generated by these routines. .SH ARGUMENTS The string .I fmt and trailing arguments are handled in the way of .I printf(3). .SH SEE ALSO setjmp(3), printf(3), fprintf(3), exit(3). .SH AUTHOR Klamer Schutte, klamer@mi.el.utwente.nl clippoly-pl11/err.c0100644000076400010400000000535210210704445015417 0ustar KlamerAdministrators/* * tutvis library * Copyright (C) 1993 University of Twente * klamer@mi.el.utwente.nl * 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. */ static const char rcs_id[] = "$Header: /cvsroot/clippoly/clippoly/err.c,v 1.2 2005/02/28 21:12:05 klamer Exp $"; /* * $Log: err.c,v $ * Revision 1.2 2005/02/28 21:12:05 klamer * Made changes such that gcc 3.4.2 compiles silent with -ansi -pedantic -Wall. * * Revision 1.2 2003/11/11 12:57:38 kscp1 * Made changes such that linux/gcc-3.3 compiles without warnings. & * Revision 1.2 2000/11/10 08:05:43 kscp1 * ANSI C version * * Revision 1.1 1994/06/07 14:30:35 schutte * Initial revision * * * error.c Klamer Schutte 25/7/90 * * handle errors in a consistent way. */ #include #include #include #include #include "err.h" int err_nr_errors, err_nr_warnings; /* what is the type of a pointer to a jmp_buf? On sun4 int * will do */ int *err_warning_jmpbuf, *err_error_jmpbuf, *err_fatal_jmpbuf; void /*VARARGS1*/ warning( const char *fmt, ... ) { va_list args; va_start( args, fmt ); vfprintf(stderr, fmt, args ); va_end(args ); err_nr_warnings++; if (err_warning_jmpbuf != NULL) longjmp( (void *) err_warning_jmpbuf, 1 ); } void /*VARARGS1*/ error( const char *fmt, ... ) { va_list args; va_start( args, fmt ); vfprintf(stderr, fmt, args ); va_end(args ); err_nr_errors++; if (err_error_jmpbuf != NULL) longjmp( (void *) err_error_jmpbuf, 1 ); } void /*VARARGS2*/ fatal_exit_nr( int nr, const char *fmt, ... ) { va_list args; va_start( args, fmt ); vfprintf(stderr, fmt, args ); va_end(args ); if (err_fatal_jmpbuf != NULL) longjmp( (void *) err_fatal_jmpbuf, 1 ); exit( nr ); } void /*VARARGS1*/ fatal( const char *fmt, ... ) { va_list args; va_start( args, fmt ); vfprintf(stderr, fmt, args ); va_end(args ); if (err_fatal_jmpbuf != NULL) longjmp( (void *) err_fatal_jmpbuf, 1 ); exit( 1 ); } clippoly-pl11/err.h0100644000076400010400000000525010210704445015421 0ustar KlamerAdministrators/* * tutvis library * Copyright (C) 1993 University of Twente * klamer@mi.el.utwente.nl * 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. */ /* * $Log: err.h,v $ * Revision 1.6 2005/02/28 21:12:05 klamer * Made changes such that gcc 3.4.2 compiles silent with -ansi -pedantic -Wall. * * Revision 1.3 2000/11/10 07:41:07 kscp1 * Added printf style attributes to warning, error and fatal as supported by GCC * * Revision 1.2 1996/09/10 13:04:56 kscp1 * *** empty log message *** * * Revision 1.1 1994/06/07 14:30:35 schutte * Initial revision * * Revision 1.5 1992/06/01 15:37:48 klamer * Made prototypes gcc compatible. * * Revision 1.4 1991/11/15 14:55:03 klamer * Merged with /usr/local/include/err.h * * Revision 1.3 1991/11/15 14:52:04 klamer * Made K&R C compatible as well. * * Revision 1.2 1991/10/11 09:55:58 klamer * added prototype for warning. * * Revision 1.1 1991/09/16 12:59:45 klamer * Initial revision * */ #ifndef _ERROR #define _ERROR "$Id: err.h,v 1.6 2005/02/28 21:12:05 klamer Exp $" #ifdef __cplusplus #define EC extern "C" #define P(x) x #define CDOTS ... #else #define EC /* nothing */ #ifdef __STDC__ #define P(x) x #define CDOTS , ... #else #define P(x) (/* x */) #endif #endif #ifdef __GNUG__ /* is it GCC or G++ ? */ #define NORETURN_PRINTF __attribute__ ((noreturn, format(printf, 1, 2))) #define PRINTF __attribute__ ((format(printf, 1, 2))) #else #define NORETURN_PRINTF #define PRINTF #endif extern int err_nr_errors, err_nr_warnings; /* what is the type of a pointer to a jmp_buf? On sun4 int * will do */ extern int *err_warning_jmpbuf, *err_error_jmpbuf, *err_fatal_jmpbuf; EC void warning P((const char *fmt CDOTS )) PRINTF; EC void error P((const char *fmt CDOTS )) PRINTF; EC void fatal P((const char *fmt CDOTS )) NORETURN_PRINTF; #undef PRINTF #undef NORETURN_PRINTF #undef EC #undef P #undef CDOTS #endif /* _ERROR */ clippoly-pl11/graphadd.30100644000076400010400000000361210210642561016316 0ustar KlamerAdministrators.TH GRAPHADD 3 "9 September 1992" .SH NAME v_print2, v_print3, m_print2, m_print3, v_scan2, v_scan3, v_inters2, v_dupl2, v_dupl3, m_dupl2, m_dupl3 \- additional 3d graphics and associated matrix and vector routines .nf .SH SYNOPSIS .nf .B #include .LP .B void v_print2(hvec2_t vec, const char *name) .B void v_print3(hvec3_t vec, const char *name) .B void m_print2(hmat2_t mat, const char *name) .B void m_print3(hmat3_t mat, const char *name) .B int v_scan2(hvec2_t &vec) .B int v_scan3(hvec3_t &vec) .B int v_inters2( const hvec2_t &p1, const hvec2_t &p2, const hvec2_t &q1, const hvec2_t &q2, hvec2_t *S1, hvec2_t *S2) .B void v_dupl2(hvec2_t *, hvec2_t *) .B void v_dupl3(hvec3_t *, hvec3_t *) .B void m_dupl2(hmat2_t *, hmat2_t *) .B void m_dupl3(hmat3_t *, hmat3_t *) .SH DESCRIPTION These routines ar an addition to grapmat(3). The *print routines print the approriate data to .I stderr. The *scan routines read from .I stdin. The *dupl routines copy data. v_inters2 returns the intersection point of p1,p2 and q1,q2 in S1 and S2. The return value is 0 if no intersection point is found, 1 if there is an intersection point, and two if the two lines do overlap. In that case, the two points are the extrema. .SH NAMES Naming conventions as in graphmat(3). .SH USAGE All the "functions" may have been implemented as macro's, so you can't take the address of a function. It is however guaranteed that arguments of each function/macro will be evaluated only once, except for the result argument, which can be evaluated multiple times. .SH SEE ALSO graphmat(3), graphmat++(3), Graphics and matrix routines. .SH NOTE Only available in C++ and ANSI C. v_inters2 only in C++. Library file is .B /usr/local/lib/libgraphmat.a and the C++ util files. .SH AUTHOR Herbert Hilhorst .br Klamer Schutte clippoly-pl11/graphadd.cc0100644000076400010400000002762310210651410016542 0ustar KlamerAdministratorsstatic const char rcs_id[] = "$Header: /cvsroot/clippoly/clippoly/graphadd.cc,v 1.5 2005/02/28 17:21:12 klamer Exp $"; // tutvis library // Copyright (C) 1993 University of Twente // klamer@mi.el.utwente.nl // 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. // $Log: graphadd.cc,v $ // Revision 1.5 2005/02/28 17:21:12 klamer // Changed to have g++ 3.2.3 run silently using g++ -ansi -pedantic -Wall -Wno-unused -Wno-reorder. // Change use of (libg++) String to ANSI C++ string. // // Revision 1.1 1994/01/04 12:55:37 klamer // Initial revision // // Revision 1.6 1993/01/18 16:19:46 klamer // Fixed bug in swapping d1 and d2. // // Revision 1.5 1992/10/20 10:54:07 klamer // Made comparisons accurate. // Made in points const references. // // Revision 1.4 1992/09/16 15:54:07 klamer // Fixed bug for parallel lines... // // Revision 1.3 1992/09/11 14:51:38 klamer // Numerical more stable algorithm used. // // Revision 1.2 1992/09/09 15:49:10 klamer // split C and C++ parts. // // // GRAPHADD.CC // // // author : G.H.J. Hilhorst // // created : 16-04-1992 // last modified : 17-08-1992 // #include #include "graphadd.h" #include static const char h_rcs_id[] = "$Header"; #define Dabs(x) (((x)<0) ? (-(x)):(x)) #ifndef EPSILON #define EPSILON 1e-10 #endif #ifdef notdef #define Pos_cmp(pos1,pos2) (Dabs((pos1)-(pos2)) y ? x : y; } inline double min(double x, double y) { return x < y ? x : y; } static #ifdef __GNUG__ inline double m_len( const hvec2_t &v ) #else double m_len( const hvec2_t v ) #endif { if (v_x(v) > 0) return len( v ); if (v_x(v) < 0) return -len( v ); if (v_y(v) > 0) return len(v); return -len(v); } static inline double inp_ort( const hvec2_t &a, const hvec2_t &b ) { return v_x(a) * v_y(b) - v_y(a) * v_x(b); } static void recursive_intersection( const hvec2_t &p1, const hvec2_t &p2, const hvec2_t & q1, const hvec2_t &q2, hvec2_t &ret ) { // Find intersection point of p1-p2 and q1-q2 by iteratively // taking the middle of p1-p2 hvec2_t q = q2 - q1; if (len(q) < len(p2 - p1)) { recursive_intersection(q1,q2,p1,p2,ret); return; } hvec2_t s1 = p1 - q1, s2 = p2 - q1; hvec2_t m = (s1 + s2) / 2.0; double inp = inp_ort( q, s1 ); if (inp > 0) { hvec2_t tmp = s1; s1 = s2; s2 = tmp; } while ((m != s1) && (m != s2)) { assert(inp_ort(q,s1) <= 0); assert(inp_ort(q,s2) >= 0); #ifdef notdef hvec2_t mp = m + q1 - p1, q1p = q1 - p1, q2p = q2 - p1; assert(inp_ort(mp,q1p) * inp_ort(mp,q2p) <= 0); mp = m + q1 - p2, q1p = q1 - p2, q2p = q2 - p2; assert(inp_ort(mp,q1p) * inp_ort(mp,q2p) <= 0); #else // assert(len(m) <= len(q2 - q1)); // assert(len(m+q1 - q2) <= len(q2 - q1)); #endif if (inp_ort(q,m) <= 0) s1 = m; else s2 = m; m = (s1 + s2) / 2.0; } assert(len(m) <= len(q2 - q1)); assert(len(m+q1 - q2) <= len(q2 - q1)); ret = m + q1; return; } int v_inters2( const hvec2_t &p1, const hvec2_t &p2, const hvec2_t &q1, const hvec2_t &q2, hvec2_t *S1, hvec2_t *S2 ) /******************************************************************* * * procedure that calculates the intersection point of point pair p * and point pair q. It returns if they hit each other and * the position of the hit(s) (S1 (and S2)) * *******************************************************************/ { double rpx, rpy, rqx, rqy, t, deel, c1, c2, d1, d2, h; hvec2_t // normal, hv,hp1,hq1,hp2,hq2; if (max(v_x(p1),v_x(p2)) < min(v_x(q1),v_x(q2))) return 0; if (max(v_x(q1),v_x(q2)) < min(v_x(p1),v_x(p2))) return 0; rpx=v_x(p2)-v_x(p1); rpy=v_y(p2)-v_y(p1); rqx=v_x(q2)-v_x(q1); rqy=v_y(q2)-v_y(q1); deel=rpx*rqy-rpy*rqx; // every value below EPSILON is considered as being 0. Hence, we do not intro- // duce numerical inaccuracies // if (deel == 0) // //if(Dabs(deel)c2) { /* hv and h are used as help-variable. */ v_cpy2(&hp1,&hv); v_cpy2(&hp2,&hp1); v_cpy2(&hv,&hp2); h=c1; c1=c2; c2=h; } if (d1>d2) { v_cpy2(&hq1,&hv); v_cpy2(&hq2,&hq1); v_cpy2(&hv,&hq2); h=d1; d1=d2; d2=h; } /* Now the line-pieces are compared: */ if (c1d2) return 0; if (c2 len(*S1 - p2) / l_p) *S1 = p2; else if (EPSILON > len(*S1 - p1) / l_p) *S1 = p1; else { double l_q = len(q1 - q2); if (EPSILON > len(*S1 - q2) / l_q) *S1 = q2; else if (EPSILON > len(*S1 - q1) / l_q) *S1 = q1; } #endif /* * The intersection point is valid if it is * 1) on q1-q2 --> t >= 0 && t <= 1 * 2) on p1-p2 --> p1 must be on the other side of q1-q2 as p2 * This is so if the difference of the x coordinate of p1-s1 has the * opposite sign as the x coordinate of p2-s2. So the multiplication of * these two must be negative. This might fail if p1-p2 is a vertical line; * this can be solved by adding the same product for the y coordinates */ #ifdef notdef return((t>=0) && (t<=1) && ((v_x(*S1)-v_x(p1))*(v_x(*S1)-v_x(p2))+ (v_y(*S1)-v_y(p1))*(v_y(*S1)-v_y(p2))<=0) ); #else #ifdef notdef int condition = ((t>=0) && (t<=1) && ((v_x(*S1)-v_x(p1))*(v_x(*S1)-v_x(p2))+ (v_y(*S1)-v_y(p1))*(v_y(*S1)-v_y(p2))<=0) ); #endif // Implement an other way of checking whether the calculated point is valid. // This is done using the inproduct on the original points. hvec2_t p = p2 - p1, pq1 = q1 - p1, pq2 = q2 - p1; double inp1 = v_x(p) * v_y(pq1) - v_y(p) * v_x(pq1), inp2 = v_x(p) * v_y(pq2) - v_y(p) * v_x(pq2); int c1 = inp1 * inp2 <= 0; hvec2_t q = q2 - q1, qp1 = p1 - q1, qp2 = p2 - q1; double inp3 = v_x(q) * v_y(qp1) - v_y(q) * v_x(qp1), inp4 = v_x(q) * v_y(qp2) - v_y(q) * v_x(qp2); int c2 = inp3 * inp4 <= 0; //if (c1 && c2 && 0) { // Say that *S1 equals one of the points if the relative distance is smaller // than EPSILON double l_q = len(q1 - q2); double l_p = len(p1 - p2); if (EPSILON > len(*S1 - p2) / l_p) { *S1 = p2; c2 = 2; } else if (EPSILON > len(*S1 - p1) / l_p) { *S1 = p1; c2 = 2; } else { // double l_q = len(q1 - q2); if (EPSILON > len(*S1 - q2) / l_q) { *S1 = q2; c1 = 2; } else if (EPSILON > len(*S1 - q1) / l_q) { *S1 = q1; c1 = 2; } } } hvec2_t s = *S1 - p1; double inp1s = v_x(s) * v_y(pq1) - v_y(s) * v_x(pq1), inp2s = v_x(s) * v_y(pq2) - v_y(s) * v_x(pq2); int c1s = (*S1 == p1) ? -1 : inp1s * inp2s <= 0; hvec2_t qs = *S1 - q1; double inp3s = v_x(qs) * v_y(qp1) - v_y(qs) * v_x(qp1), inp4s = v_x(qs) * v_y(qp2) - v_y(qs) * v_x(qp2); int c2s = (*S1 == q1) ? -1 : inp3s * inp4s <= 0; // Roundig errors might make the statements below untrue int failed = 0; if (!((c1 == 0) || (c2 == 0) || (c1s == (c1 != 0)) || (c1s == -1))) failed = 1; else if (!((c1 == 0) || (c2 == 0) || (c2s == (c2 != 0)) || (c2s == -1))) failed = 2; else if (c1 && c2 && (len(*S1 - q1) > len(q2 - q1))) failed = 3; else if (c1 && c2 && (len(*S1 - q2) > len(q2 - q1))) failed = 4; else if (c1 && c2 && (len(*S1 - p1) > len(p2 - p1))) failed = 5; else if (c1 && c2 && (len(*S1 - p2) > len(p2 - p1))) failed = 6; if ((failed >= 3) && (c1 == 2 || c2 == 2)) { failed = -1; c1 = c2 = 0; } if (failed > 0) recursive_intersection(p1, p2, q1, q2, *S1); #ifdef notdef assert((c1 && c2) == condition); return condition; #else return (c1 && c2); #endif #endif } } clippoly-pl11/graphadd.h0100644000076400010400000000706310210704445016407 0ustar KlamerAdministrators/* * tutvis library * Copyright (C) 1993 University of Twente * klamer@mi.el.utwente.nl * 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. */ /* * $Log: graphadd.h,v $ * Revision 1.7 2005/02/28 21:12:05 klamer * Made changes such that gcc 3.4.2 compiles silent with -ansi -pedantic -Wall. * * Revision 1.6 2005/02/28 17:26:49 klamer * Changed comment with $Log: graphadd.h,v $ * Changed comment with Revision 1.7 2005/02/28 21:12:05 klamer * Changed comment with Made changes such that gcc 3.4.2 compiles silent with -ansi -pedantic -Wall. * Changed comment with to get rid of warning. * * Revision 1.5 2005/02/28 17:21:12 klamer * Changed to have g++ 3.2.3 run silently using g++ -ansi -pedantic -Wall -Wno-unused -Wno-reorder. * Change use of (libg++) String to ANSI C++ string. * * Revision 1.3 1992/10/20 13:48:39 klamer * Made input arguments of v_inters const. * // Revision 1.2 1992/09/09 15:49:10 klamer // split C and C++ parts. // Added ANSI C support. // // // GRAPHADD.H // // // author : G.H.J. Hilhorst // // created : 16-04-1992 // last modified : 21-05-1992 */ #ifndef GRAPHADD_H #define GRAPHADD_H "$Header: /cvsroot/clippoly/clippoly/graphadd.h,v 1.7 2005/02/28 21:12:05 klamer Exp $" #ifndef GRAPHMAT_INCLUDE #include #endif #define v_print2(vec,vec_name)(fprintf(stderr,"vec2 %s:\tx=%g\t y=%g\tw=%g\n",\ vec_name,v_x(vec),v_y(vec),v_w(vec))) #define v_print3(vec,vec_name)(fprintf(stderr,\ "vec3 %s:\tx=%g\t y=%g\tz=%g\tw=%g\n",\ vec_name,v_x(vec),v_y(vec),v_z(vec),v_w(vec))) #define m_print2(mat,vec_name) if(&(mat)!=NULL) fprintf(stderr, \ "mat2 %s:\n%g\t%g\t%g\n%g\t%g\t%g\n%g\t%g\t%g\n", \ vec_name,m_elem(mat,0,0),m_elem(mat,0,1),m_elem(mat,0,2), \ m_elem(mat,1,0),m_elem(mat,1,1),m_elem(mat,1,2), \ m_elem(mat,2,0),m_elem(mat,2,1),m_elem(mat,2,2)) #define m_print3(mat,vec_name) if(&(mat)!=NULL) fprintf(stderr, \ "mat3 %s:\n%g\t%g\t%g\t%g\n%g\t%g\t%g\t%g\n%g\t%g\t%g\t%g\n%g\t%g\t%g\t%g\n",\ vec_name,m_elem(mat,0,0),m_elem(mat,0,1),m_elem(mat,0,2),m_elem(mat,0,3),\ m_elem(mat,1,0),m_elem(mat,1,1),m_elem(mat,1,2),m_elem(mat,1,3), \ m_elem(mat,2,0),m_elem(mat,2,1),m_elem(mat,2,2),m_elem(mat,2,3), \ m_elem(mat,3,0),m_elem(mat,3,1),m_elem(mat,3,2),m_elem(mat,3,3)) #define v_scan2(vec)(scanf("%lf %lf %lf",&v_x(*vec),&v_y(*vec),&v_w(*vec))) #define v_scan3(vec)(scanf("%lf %lf %lf %lf",&v_x(*vec),&v_y(*vec),\ &v_z(*vec),&v_w(*vec))) #ifdef __cplusplus int v_inters2( const hvec2_t &p1, const hvec2_t &p2, const hvec2_t &q1, const hvec2_t &q2, hvec2_t *S1, hvec2_t *S2 ); extern "C" { #endif void v_dupl2(hvec2_t *, hvec2_t *); void v_dupl3(hvec3_t *, hvec3_t *); void m_dupl2(hmat2_t *, hmat2_t *); void m_dupl3(hmat3_t *, hmat3_t *); #ifdef __cplusplus } #endif #endif clippoly-pl11/graphmat++.30100644000076400010400000000220610210642561016473 0ustar KlamerAdministrators.TH GRAPHMAT++ 3 "20 October 1992" .SH NAME -, +, len \- Syntatic simple interface to graphmat. .nf .SH SYNOPSIS .nf .B #include .LP .B hvec2_t operator-(const hvec2_t &) .B hvec2_t operator-(const hvec2_t &, const hvec2_t &) .B hvec2_t operator+(const hvec2_t &, const hvec2_t &) .B hvec2_t operator*(const hmat2_t &, const hvec2_t &) .B hvec2_t operator*(double, const hvec2_t &) .B hvec2_t operator/(const hvec2_t &, double) .B const hvec2_t &operator+=(hvec2_t &, const hvec2_t &) .B const hvec2_t &operator-=(hvec2_t &, const hvec2_t &) .B const hvec2_t &operator*=(hvec2_t &, double) .B const hvec2_t &operator/=(hvec2_t &, double) .B double len(const hvec2_t &) .SH DESCRIPTION These routines ar an addition to grapmat(3). Actually, it are just some inline calls to the graphmat(3) equivalents. .SH SEE ALSO graphmat(3), graphadd(3), Graphics and matrix routines. .SH NOTE Only available in C++ .br Code is in the C++ util files. A lot more should be implemented! (It's easy, any volunteers? :-) Also the hvec3_t and hmat* versions should exsist. .SH AUTHOR Klamer Schutte clippoly-pl11/graphmat++.cc0100644000076400010400000000270010210651410016706 0ustar KlamerAdministratorsstatic const char rcs_id[] = "$Header: /cvsroot/clippoly/clippoly/graphmat++.cc,v 1.5 2005/02/28 17:21:12 klamer Exp $"; // tutvis library // Copyright (C) 1993 University of Twente // klamer@mi.el.utwente.nl // 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. // $Log: graphmat++.cc,v $ // Revision 1.5 2005/02/28 17:21:12 klamer // Changed to have g++ 3.2.3 run silently using g++ -ansi -pedantic -Wall -Wno-unused -Wno-reorder. // Change use of (libg++) String to ANSI C++ string. // // Revision 1.1 1992/09/11 14:51:38 klamer // Initial revision // #ifdef __GNUG__ #pragma implementation #pragma implementation "graphmat.h" #endif #include "graphmat++.h" static const char h_rcs_id[] = GRAPHMATPLUSPLUS_H; clippoly-pl11/graphmat++.h0100644000076400010400000001017410210651410016554 0ustar KlamerAdministrators// tutvis library // Copyright (C) 1993 University of Twente // klamer@mi.el.utwente.nl // 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. #ifndef GRAPHMATPLUSPLUS_H #define GRAPHMATPLUSPLUS_H "$Header: /cvsroot/clippoly/clippoly/graphmat++.h,v 1.5 2005/02/28 17:21:12 klamer Exp $" // $Log: graphmat++.h,v $ // Revision 1.5 2005/02/28 17:21:12 klamer // Changed to have g++ 3.2.3 run silently using g++ -ansi -pedantic -Wall -Wno-unused -Wno-reorder. // Change use of (libg++) String to ANSI C++ string. // // Revision 1.5 1993/05/13 12:50:59 klamer // fixed v2 -= v2 to use vv_sub2 instead of vv_add2 // added -v3, v3 * s, s * v3, v3 + v3, v3 -= v3 // // Revision 1.4 1993/01/18 16:23:47 klamer // Added m3 * m3, m3 * v3 and v3 - v3. // // Revision 1.3 1992/10/20 11:02:52 klamer // Added operator versions of: // double * hvec2 // hvec2 / double // hvec2 += hvec2 // hvec2 -= hvec2 // hvec2 *=double // hvec2 /= double // #ifndef GRAPHMAT_INCLUDE #include #endif #ifdef __GNUG__ #pragma interface #endif inline hvec2_t operator-( const hvec2_t &h ) { hvec2_t ret; v_fill2(-v_x(h),-v_y(h),v_w(h), &ret); return ret; } inline hvec2_t operator-( const hvec2_t &l, const hvec2_t &r ) { hvec2_t ret; vv_sub2( &l, &r, &ret ); return ret; } inline hvec2_t operator+( const hvec2_t &l, const hvec2_t &r ) { hvec2_t ret; vv_add2( &l, &r, &ret ); return ret; } inline hvec2_t operator*( const hmat2_t &m, const hvec2_t &v ) { hvec2_t ret; mv_mul2( &m, &v, &ret ); return ret; } inline hvec2_t operator*( double s, const hvec2_t &v ) { hvec2_t ret; sv_mul2( s, &v, &ret ); return ret; } inline hvec2_t operator/( const hvec2_t &v, double div ) { hvec2_t ret; sv_mul2( 1.0/div, &v, &ret ); return ret; } inline hvec2_t const & operator+=( hvec2_t &v, const hvec2_t &add ) { vv_add2( &v, &add, &v ); return v; } inline hvec2_t const & operator-=( hvec2_t &v, const hvec2_t &sub ) { vv_sub2( &v, &sub, &v ); return v; } inline hvec2_t const & operator*=( hvec2_t &v, double mul ) { sv_mul2( mul, &v, &v ); return v; } inline hvec2_t const & operator/=( hvec2_t &v, double div ) { sv_mul2( 1.0/div, &v, &v ); return v; } inline double len( const hvec2_t &v ) { return v_len2( &v ); } inline hvec3_t operator-( const hvec3_t &h ) { hvec3_t ret; v_fill3(-v_x(h),-v_y(h), -v_z(h), v_w(h), &ret); return ret; } inline hmat3_t operator*( const hmat3_t &l, const hmat3_t &r ) { hmat3_t res; mm_mul3(&l, &r, &res); return res; } inline hvec3_t operator*( const hmat3_t &m, const hvec3_t &v ) { hvec3_t res; mv_mul3(&m, &v, &res); return res; } inline hvec3_t operator-( const hvec3_t &l, const hvec3_t &r ) { hvec3_t res; vv_sub3( &l, &r, &res ); return res; } inline hvec3_t operator*( const hvec3_t &v, double s ) { hvec3_t ret; sv_mul3( s, &v, &ret ); return ret; } inline hvec3_t operator*( double s, const hvec3_t &v ) { hvec3_t ret; sv_mul3( s, &v, &ret ); return ret; } inline hvec3_t operator+( const hvec3_t &l, const hvec3_t &r ) { hvec3_t ret; vv_add3( &l, &r, &ret ); return ret; } inline hvec3_t const & operator-=( hvec3_t &v, const hvec3_t &sub ) { vv_sub3( &v, &sub, &v ); return v; } #endif clippoly-pl11/graphmat.30100644000076400010400000004336710210642561016362 0ustar KlamerAdministrators.TH GRAPHMAT 3 "15 September 1992" .SH NAME m_alloc2, m_free2, v_alloc2, v_free2, m_alloc3, m_free3, v_alloc3, v_free3, m_cpy2, m_unity2, v_cpy2, v_fill2, v_unity2, v_zero2, m_cpy3, m_unity3, v_cpy3, v_fill3, v_unity3, v_zero3, m_det2, v_len2, vtmv_mul2, vv_inprod2, m_inv2, m_tra2, mm_add2, mm_mul2, mm_sub2, mtmm_mul2, sm_mul2, mv_mul2, sv_mul2, v_homo2, v_norm2, vv_add2, vv_sub2, vvt_mul2, m_det3, v_len3, vtmv_mul3, vv_inprod3, m_inv3, m_tra3, mm_add3, mm_mul3, mm_sub3, mtmm_mul3, sm_mul3, mv_mul3, sv_mul3, v_homo3, v_norm3, vv_add3, vv_cross3, vv_sub3, vvt_mul3, miraxis2, mirorig2, mirplane2, rot2, scaorig2, scaplane2, scaxis2, transl2, miraxis3, mirorig3, mirplane3, prjorthaxis, prjpersaxis, rot3, scaorig3, scaplane3, scaxis3, transl3 \- 3d graphics and associated matrix and vector routines .nf .SH SYNOPSIS .nf .B #include .LP .I /* Data initialisation */ .LP .ta 1.0i .B hmat2_t *m_alloc2(m_result) .br .B hmat2_t *m_result; .B void m_free2(matrix) .br .B hmat2_t *matrix; .B hvec2_t *v_alloc2(v_result) .br .B hvec2_t *v_result; .B void v_free2(vector) .br .B hmat2_t *vector; .B hmat3_t *m_alloc3(m_result) .br .B hmat3_t *m_result; .B void m_free3(matrix) .br .B hmat3_t *matrix; .B hvec3_t *v_alloc3(v_result) .br .B hvec3_t *v_result; .B void v_free3(vector) .br .B hmat3_t *vector; .B hmat2_t *m_cpy2(m_source, m_result) .br .B hmat2_t *m_source, *m_result; .B hmat2_t *m_unity2( m_result) .br .B hmat2_t *m_result; .B hvec2_t *v_cpy2(v_source, v_result) .br .B hvec2_t *v_source, *v_result; .B hvec2_t *v_fill2(x, y, w, v_result) .br .B double x, y, w; .br .B hvec2_t *v_result; .B hvec2_t *v_unity2(axis, v_result) .br .B b_axis axis; .br .B hvec2_t *v_result; .B hvec2_t *v_zero2(v_result) .br .B hvec2_t *v_result; .B hmat3_t *m_cpy3(m_source, m_result) .br .B hmat3_t *m_source, *m_result; .B hmat3_t *m_unity3(m_result) .br .B hmat3_t *m_result; .B hvec3_t *v_cpy3(v_source, v_result) .br .B hvec3_t *v_source, *v_result; .B hvec3_t *v_fill3(x, y, z, w, v_result) .br .B double x, y, z, w; .br .B hvec3_t *v_result; .B hvec3_t *v_unity3(axis, v_result) .br .B b_axis axis; .br .B hvec3_t *v_result; .B hvec3_t *v_zero3(vector) .br .B hvec3_t *vector; .LP .I /* Basic Linear Algebra */ .LP .B double m_det2(matrix) .br .B hmat2_t *matrix; .B double v_len2(vector) .br .B hvec2_t *vector; .B double vtmv_mul2(vector, matrix) .br .B hvec2_t *vector; .br .B hmat2_t *matrix; .B double vv_inprod2(vectorA, vectorB) .br .B hvec2_t *vectorA, *vectorB; .B hmat2_t *m_inv2(matrix, m_result) .br .B hmat2_t *matrix, *m_result; .B hmat2_t *m_tra2(matrix, m_result) .br .B hmat2_t *matrix, *m_result; .B hmat2_t *mm_add2(matrixA, matrixB, m_result) .br .B hmat2_t *matrixA, *matrixB, *m_result; .B hmat2_t *mm_mul2(matrixA, matrixB, m_result) .br .B hmat2_t *matrixA, *matrixB, *m_result; .B hmat2_t *mm_sub2(matrixA, matrixB, m_result) .br .B hmat2_t *matrixA, *matrixB, *m_result; .B hmat2_t *mtmm_mul2(matrixA, matrixB, m_result) .br .B hmat2_t *matrixA, *matrixB, *m_result; .B hmat2_t *sm_mul2(scalar, matrix, m_result) .br .B double scalar; .br .B hmat2_t *matrix, *m_result; .B hmat2_t *vvt_mul2(vectorA, vectorB, m_result) .br .B hvec2_t *vectorA, *vectorB; .br .B hmat2_t *m_result; .B hvec2_t *mv_mul2(matrix, vector, v_result) .br .B hmat2 *matrix; .br .B hvec2_t *vector, *v_result; .B hvec2_t *sv_mul2(scalar, vector, v_result) .br .B double scalar; .br .B hvec2_t *vector, *v_result; .B hvec2_t *v_homo2(vector, v_result) .br .B hvec2_t *vector, *v_result; .B hvec2_t *v_norm2(vector, v_result) .br .B hvec2_t *vector, *v_result; .B hvec2_t *vv_add2(vectorA, vectorB, v_result) .br .B hvec2_t *vectorA, *vectorB, *v_result; .B hvec2_t *vv_sub2(vectorA, vectorB, v_result) .br .B hvec2_t *vectorA, *vectorB, *v_result; .B double m_det3(matrix) .br .B hmat3_t *matrix; .B double v_len3(vector) .br .B hvec3_t *vector; .B double vtmv_mul3(vector, matrix) .br .B hvec3_t *vector; .br .B hmat3_t *matrix; .B double vv_inprod3(vectorA, vectorB) .br .B hvec3_t *vectorA, *vectorB; .B hmat3_t *m_inv3(matrix, m_result) .br .B hmat3_t *matrix, *m_result; .B hmat3_t *m_tra3(matrix, m_result) .br .B hmat3_t *matrix, *m_result; .B hmat3_t *mm_add3(matrixA, matrixB, m_result) .br .B hmat3_t *matrixA, *matrixB, *m_result; .B hmat3_t *mm_mul3(matrixA, matrixB, m_result) .br .B hmat3_t *matrixA, *matrixB, *m_result; .B hmat3_t *mm_sub3(matrixA, matrixB, m_result) .br .B hmat3_t *matrixA, *matrixB, *m_result; .B hmat3_t *mtmm_mul3(matrixA, matrixB, m_result) .br .B hmat3_t *matrixA, *matrixB, *m_result; .B hmat3_t *sm_mul3(scalar, matrix, m_result) .br .B double scalar; .br .B hmat3_t *matrix, *m_result; .B hmat3_t *vvt_mul3(vectorA, vectorB, m_result) .br .B hvec3_t *vectorA, *vectorB; .br .B hmat3_t *m_result; .B hvec3_t *mv_mul3(matrix, vector, v_result) .br .B hmat3_t *matrix; .br .B *hvec3_t *vector, *v_result; .B hvec3_t *sv_mul3(scalar, vec, v_result) .br .B double scalar; .br .B hvec3_t *vector, *v_result; .B hvec3_t *v_homo3(vector, v_result) .br .B hvec3_t *vector, *v_result; .B hvec3_t *v_norm3(vector, v_result) .br .B hvec3_t *vector, *v_result; .B hvec3_t *vv_add3(vectorA, vectorB, v_result) .br .B hvec3_t *vectorA, *vectorB, *v_result; .B hvec3_t *vv_cross3(vectorA, vectorB, v_result) .br .B hvec3_t *vectorA, *vectorB, *v_result; .B hvec3_t *vv_sub3(vectorA, vectorB, v_result) .br .B hvec3_t *vectorA, *vectorB, *v_result; .LP .I /* Elementary transformations */ .LP .B hmat2_t *miraxis2(axis, m_result) .br .B b_axis axis; .br .B hmat2_t *m_result; .B hmat2_t *mirorig2(m_result) .br .B hmat2_t *m_result; .B hmat2_t *rot2( rotation, m_result) .br .B double rotation; .br .B hmat2_t *m_result; .B hmat2_t *scaorig2(scale, m_result) .br .B double scale; .br .B hmat2_t *m_result; .B hmat2_t *scaxis2(scale, axis, m_result) .br .B double scale; .br .B b_axis axis; .br .B hmat2_t *m_result; .B hmat2_t *transl2(translation, m_result) .br .B hvec2_t *translation; .br .B hmat2_t *m_result; .B hmat3_t *miraxis3(axis, m_result) .br .B b_axis axis; .br .B hmat3_t *m_result; .B hmat3_t *mirorig3(m_result) .br .B hmat3_t *m_result; .B hmat3_t *mirplane3(plane, m_result) .br .B b_axis plane; .br .B hmat3_t *m_result; .B hmat3_t *prjorthaxis(axis, m_result) .br .B b_axis axis; .br .B hmat3_t *m_result; .B hmat3_t *prjpersaxis(axis, m_result) .br .B b_axis axis; .br .B hmat3_t *m_result; .B hmat3_t *rot3( rotation, axis, m_result) .br .B double rotation; .br .B b_axis axis; .br .B hmat3_t *m_result; .B hmat3_t *scaorig3(scale, m_result) .br .B double scale; .br .B hmat3_t *m_result; .B hmat3_t *scaplane(scale, plane, m_result) .br .B double scale; .br .B b_axis plane; .br .B hmat3_t *m_result; .B hmat3_t *scaxis3(scale, axis, m_result) .br .B double scale; .br .B b_axis axis; .br .B hmat3_t *m_result; .B hmat3_t *transl3(translation, m_result) .br .B hvec3_t *translation; .br .B hmat3_t *m_result; .SH DESCRIPTION Matrix and vector routines associated with 3d graphics in homogeneous coordinates, such as basic linear algebra and elementary transformations. .LP This library is setup with a multi-level approach. .br .I Level1 : .B the data level. .br .I Level 2: .B the data initialisation level. .br .I Level 3: .B basic linear algebra level. .br .I Level 4: .B elementary transformation level. .br .I Level 1, the data structures, is realised as follows : .br .B typedef union .br .B { .br .B double a[3]; .br .B struct .br .B { .br .B double x, y, w; .br .B } s; .br .B } hvec2_t; .LP .LP .B typedef union .br .B { .br .B double a[4]; .br .B struct .br .B { .br .B double x, y, z, w; .br .B } s; .br .B } hvec3_t; .LP .LP .B typedef struct .br .B { .br .B double m[3][3]; .br .B } hmat2_t; .LP .LP .B typedef struct .br .B { .br .B double m[4][4]; .br .B } hmat3_t; .LP .LP To access the data elements of a vector or a matrix can be accessed with the macros: .LP #define v_x( vec ) ((vec).s.x) .br #define v_y( vec ) ((vec).s.y) .br #define v_z( vec ) ((vec).s.z) .br #define v_w( vec ) ((vec).s.w) .br #define v_elem( vec, i ) ((vec).a[(i)]) .br #define m_elem( mat, i, j ) ((mat).m[(i)][(j)]) .br .LP .LP .B typedef enum .br .B { .br .B X_AXIS, Y_AXIS, Z_AXIS .br .B } b_axis; .LP .LP The functions are as follows sorted: .br first on the level in which they belong, then on their return value and then on their name. .SH NAMES The function names begin with an abbreviation of the type of operand, and in which order the operations will be carried out on that operand. Then the order of and which operation will be carried out, followed by the type of coordinates. (i.e .I vtmv_mul3(vector, matrix) : first take the transpose of .I vector, multiply the transpose with .I matrix, this result is multiplied by the incoming vector, all coordinates are homogeneous 3d coordinates.) .SH USAGE All the "functions" may have been implemented as macro's, so you can't take the address of a function. It is however guaranteed that arguments of each function/macro will be evaluated only once, except for the result argument, which can be evaluated multiple times. .LP All operations can be used in place, but overlapping data gives unspecified results. .LP If the parameter .I v_result or .I m_result of a function or the parameter of an initialisation function equals .B NULL, space for the parameter will be dynamically allocated using .B malloc(), otherwise the parameter is assumed to hold a pointer to a memory area which can be used. A pointer to the used area (which may have been new allocated) is always returned. .br If an error occurred like memory could not be allocated, an attempt to divide by zero occurs, or an attempt to invert a singular matrix a general error-routine will be called, which has two parameters : .I gm_errno and .I gm_func. .br .I gm_errno is the error type which is one of the following constants : .B DIV0, .B NOMEM or .B MATSING. .I gm_func is a pointer to a string which contains the name of the function where the error occurred. .LP A pointer to the error routine is defined as follows : .br .B void (* gm_error)(gm_errno, gm_func); .br .B gm_error_t gm_errno; .br .B char *gm_func; .LP With .I gm_error_t is defined as : .br .B typedef enum .br .B { .br .B DIV0, NOMEM, MATSING .br .B } gm_error_t; .br .LP The default error handler will abort after printing a diagnostic. You can redirect .I gm_error to your own error handler. It is not advisable to return from the error handler as error recovery is not expected to take place. .LP Matrices are of type .B hmat3_t or .B hmat2_t for 2d or 3d coordinates, respectively. .br Vectors are of type .B hvec3_t or .B hvec2_t. .LP The elements of a vector can be accessed in two manners, the first one is by name of an element of a structure, the second is like an array. .LP A plane is described by the normal to that plane, with the assumption made that the origin is an element of the plane. .LP .I rotation is assumed to be a radial. .LP If a function is deallocating memory, it will check if the incoming pointer is a .B NULL pointer. .LP .LP .I /* Level2 : Data initialisation */ .LP .B m_alloc2(), v_alloc2(), m_alloc3(), v_alloc3() allocate memory for a data item of type .B hmat2_t, hvec2_t, hmat3_t and .B hvec3_t respectively. .br .B m_free2(), v_free2(), m_free3(), v_free3() reclaim the storage allocated previously. .br .B m_cpy2(), m_cpy3() copies .I m_matrix into .I m_result. .br .B m_unity2(), m_unity3() returns the unity matrix. (2d respectively 3d homogeneous coordinates) .br .B v_cpy2(), v_cpy3() copies .I v_source into .I v_result. (2d respectively 3d homogeneous coordinates) .br .B v_fill2(), v_fill3() fills .I v_result according the given values. .br .B v_unity2(), v_unity3() returns the unity vector with .I w = 1.0, the incoming basic axis .I axis = 1.0, and the other element(s) are 0.0; (2d respectively 3d homogeneous coordinates) .br .B v_zero2(), v_zero3() return a vector with .I w = 1.0 and the other elements 0.0; .br .B m_cpy2(), m_cpy3() copies .I m_source into .I m_result. (2d respectively 3d homogeneous coordinates) .LP .I /* level3 : Basic Linear Algebra */ .LP .B m_det2(), m_det3() calculates the determinant of the incoming matrix. The determinant is calculated in cartesian rather than homogeneous coordinates. .br .B v_len2(), v_len3() calculates the length of the cathesian part of the homogeneous vector. .br .B vtmv_mul2(), vtmv_mul3() calculate the result of the transpose of the incoming vector multiplied by the incoming matrix multiplied by the incoming vector (2d respectively 3d homogeneous coordinates) .br .B vv_inprod2(), vv_inprod3() calculates the geometrical innerproduct (vector . vector) of .I vectorA and .I vectorB. .br .B m_inv2(), m_inv3() calculates the inverse of .I matrix. It is an error if the matrix in singular. .br .B m_tra2(), m_tra3() calculates the transpose .I matrix. (2d respectively 3d homogeneous coordinates) .br .B mm_add2(), mm_sub2(), mm_add3(), mm_sub3() calculates the result of .I matrixA + respectively - .I matrixB. This operation is unspecified in the sense of homogeneous coordinates; the matrices are taken in their normal, mathematial sense. .br .B mm_mul2(), mm_mul3() calculates the result of .I matrixA*matrixB (2d respectively 3d homogeneous coordinates) .br .B mtmm_mul2(), mtmm_mul3() calculates the result of the transpose of the incoming .I matrixA multiplied by .I matrixB multiplied by .I matrixA (2d respectively 3d homogeneous coordinates) .br .B sm_mul2(), sm_mul3() calculates the result of .I scalar*matrix (2d respectively 3d homogeneous coordinates) .br .B mv_mul2(), mv_mul3() calculates the result of .I matrix*vector (2d respectively 3d homogeneous coordinates) .br .B sv_mul2(), sv_mul3() calculates the result of .I scalar*vector. (2d respectively 3d homogeneous coordinates) .br .B v_homo2(), v_homo3() homogenize .I vector so that the .I w component becomes 1.0 but the length of the vector in homogeneous coordinates stays the same. (2d respectively 3d homogeneous coordinates) .br .B v_norm2(), v_norm3() normalises the incoming vector so the length of the cartesian vector becomes 1.0. The homogeneous length stays the same. (2d respectively 3d homogeneous coordinates) .br .B vv_add2(), vv_sub2(), vv_add3(), vv_sub3() calculates the result of .I vectorA + respectively - .I vectorB. These operations are done in the mathematical sense. Be careful with homogeneous coordinates, as not every possible input makes sense. .br .B vvt_mul2(), vvt_mul3() calculates the result of .I vectorA multiplied by the transpose of .I vectorB (2d respectively 3d homogeneous coordinates) .br .B vv_cross3() calculates the geometrical crossproduct ( .I vectorA x vectorB) of two vectors (3d homogeneous coordinates) .LP .I /* level4 : Elementary transformations */ .LP .B miraxis2(), miraxis3() calculates the mirror matrix with respect to .I axis. (2d respectively 3d homogeneous coordinates) .br .B mirorg2(), mirorg3() calculates the mirror matrix relative to the origin. (2d respectively 3d homogeneous coordinates) .br .B mirplane3() calculates the mirror matrix relative to a plane. (3d homogeneous coordinates) .br .B rot2() calculates the rotation matrix over .I rotation relative to the origin. (2d homogeneous coordinates) .br .B rot3() calculates the rotation matrix over .I rotation along .I axis. (3d homogeneous coordinates) .br .B scaorg2(), scaorg3() calculates the matrix of scaling with .I scale relative to the origin. (2d respectively 3d homogeneous coordinates) .br .B scaplane3() calculates the matrix of scaling with .I scale relative to a plane of which .I plane is the normal. (3d homogeneous coordinates) .br .B scaxis2(), scaxis3() calculates the matrix of scaling with .I scale relative to the line given by .I axis. (2d respectively 3d homogeneous coordinates) .br .B transl2(), transl3() calculates the translation matrix over .I translation. (2d respectively 3d homogeneous coordinates) .br .B prjorthaxis() calculates the orthographic projection matrix along .I axis. (3d homogeneous coordinates) .br .B prjpersaxis() calculates the perspective projection with along .I axis The focus is in the origin. The projection plane is on distance 1.0 before the camera. (3d homogeneous coordinates) .SH CAVEATS Vector addition and subtraction and matrix addition and substraction are not defined for homogeneous coordinates. One can add and subtract a point vector and a free vector, but you have to normalise the point vector first. The result of the subtraction of two point vectors is a free vector. .LP Calculating the determinant of a matrix and the length of a vector is unspecified in the sense of homogeneous coordinates .SH RETURN VALUES There are six types of return values: .B void, double, *hvec3_t, *hvec2_t, *hmat3_t and *hmat2_t. .SH SEE ALSO graphadd(3), graphmat++(3), fmatpinv(3TV), malloc(3V), Graphics and matrix routines. .SH NOTE Library file is .B /usr/local/lib/libgraphmat.a .SH AUTHOR Hans Gringhuis. .br Klamer Schutte clippoly-pl11/graphmat.c0100644000076400010400000011244110210651410016421 0ustar KlamerAdministratorsstatic char rcs_id[] = "$Header: /cvsroot/clippoly/clippoly/graphmat.c,v 1.5 2005/02/28 17:21:12 klamer Exp $"; /* $Log: graphmat.c,v $ Revision 1.5 2005/02/28 17:21:12 klamer Changed to have g++ 3.2.3 run silently using g++ -ansi -pedantic -Wall -Wno-unused -Wno-reorder. Change use of (libg++) String to ANSI C++ string. * Revision 1.8 1993/01/28 15:25:47 klamer * Changed scaxis: now is scaled along the axis; the line-mirror behaviour * is now deleted. * * Revision 1.7 1993/01/18 16:28:54 klamer * added inclusion of err.h. * Added return value to mm_add3 * Simplified v_norm3 * Changed prjorthaxis3. Tricky -- check for results. * Deleted unused variables in prjpersaxis. * * Revision 1.6 1992/03/26 16:33:05 klamer * prjpersaxis corrected for Z_AXIS (implemented proper). * * Revision 1.5 1992/03/25 15:13:41 klamer * made lint complain less. * * Revision 1.4 1992/01/29 16:19:41 aartjan * bugs in rot3() and vv_inprod3() fixed * * Revision 1.3 1992/01/29 08:45:21 aartjan * sv_mul bug fixed; vv_inprod optimized * graphmat.c - 3d graphics and associated matrix and vector routines in homogeneous coordinates. Author : Hans Gringhuis */ #include #include static int default_gm_error(); /***** initialisation of general error-routine ******/ int (*gm_error)() = default_gm_error; /****** General error-routine ******/ static int default_gm_error(gm_errno, gm_func) gm_error_t gm_errno; char *gm_func; { switch(gm_errno) { case NOMEM : fatal("Graphmat-error : Memory allocation failure in function : %s\n", gm_func); case DIV0 : fatal("Graphmat-error : Division by zero in function : %s\n", gm_func); case MATSING : fatal("Graphmat-error : Matrix is singular in function : %s\n", gm_func); default : fatal("Graphmat-error : Undefined error in function : %s\n", gm_func); }; } /****** Level 2 : Data initialisation ******/ hmat2_t * m_cpy2(m_source, m_result) const hmat2_t *m_source; hmat2_t *m_result; { m_result = gm_ALLOC(hmat2_t, m_result, "m_cpy2()"); *m_result = *m_source; return m_result; } hmat2_t * m_unity2(m_result) hmat2_t *m_result; { int i, j; m_result = gm_ALLOC(hmat2_t, m_result, "m_unity2()"); for(i=0; i<3; i++) for(j=0; j<3; j++) m_elem(*m_result, i, j) = (i != j) ? 0.0 : 1.0; return m_result; } hvec2_t * v_cpy2(v_source, v_result) const hvec2_t *v_source; hvec2_t *v_result; { v_result = gm_ALLOC(hvec2_t, v_result, "v_cpy2"); *v_result = *v_source; return v_result; } hvec2_t * v_fill2(x, y, w, v_result) double x, y, w; hvec2_t *v_result; { v_result = gm_ALLOC(hvec2_t, v_result, "v_fill2()"); v_x(*v_result) = x; v_y(*v_result) = y; v_w(*v_result) = w; return v_result; } hvec2_t * v_unity2(axis, v_result) b_axis axis; hvec2_t *v_result; { v_result = gm_ALLOC(hvec2_t, v_result, "v_unity2()"); if(axis == X_AXIS) { v_x(*v_result) = 1.0; v_y(*v_result) = 0.0; } else { v_x(*v_result) = 0.0; v_y(*v_result) = 1.0; }; v_w(*v_result) = 1.0; return v_result; } hvec2_t * v_zero2(v_result) hvec2_t *v_result; { v_result = gm_ALLOC(hvec2_t, v_result, "v_zero2()"); v_x(*v_result) = v_y(*v_result) = 0.0; v_w(*v_result) = 1.0; return v_result; } hmat3_t * m_cpy3(m_source, m_result) const hmat3_t *m_source; hmat3_t *m_result; { m_result = gm_ALLOC(hmat3_t, m_result, "m_cpy3()"); *m_result = *m_source; return m_result; } hmat3_t * m_unity3(m_result) hmat3_t *m_result; { int i, j; m_result = gm_ALLOC(hmat3_t, m_result, "m_unity3()"); for(i=0; i<4; i++) for(j=0; j<4; j++) m_elem(*m_result, i, j) = (i != j) ? 0.0 : 1.0; return m_result; } hvec3_t * v_cpy3(v_source, v_result) const hvec3_t *v_source; hvec3_t *v_result; { v_result = gm_ALLOC(hvec3_t, v_result, "v_cpy3()"); *v_result = *v_source; return v_result; } hvec3_t * v_fill3(x, y, z, w, v_result) double x, y, z, w; hvec3_t *v_result; { v_result = gm_ALLOC(hvec3_t, v_result, "v_fill3()"); v_x(*v_result) = x; v_y(*v_result) = y; v_z(*v_result) = z; v_w(*v_result) = w; return v_result; } hvec3_t * v_unity3(axis, v_result) b_axis axis; hvec3_t *v_result; { v_result = gm_ALLOC(hvec3_t, v_result, "v_unity3()"); switch(axis) { case X_AXIS : v_x(*v_result) = 1.0; v_y(*v_result) = v_z(*v_result) = 0.0; break; case Y_AXIS : v_y(*v_result) = 1.0; v_x(*v_result) = v_z(*v_result) = 0.0; break; default : v_z(*v_result) = 1.0; v_x(*v_result) = v_y(*v_result) = 0.0; break; }; v_w(*v_result) = 1.0; return v_result; } hvec3_t * v_zero3(v_result) hvec3_t *v_result; { v_result = gm_ALLOC(hvec3_t, v_result, "v_zero3()"); v_x(*v_result) = v_y(*v_result) = v_z(*v_result) = 0.0; v_w(*v_result) = 1.0; return v_result; } /****** Level 3 : Basic lineair algebra : 2D homogeneous coordinates ******/ double m_det2(matrix) const hmat2_t *matrix; { return m_elem(*matrix,0,0) * (m_elem(*matrix,1,1) * m_elem(*matrix,2,2) - m_elem(*matrix,1,2) * m_elem(*matrix,2,1)) - m_elem(*matrix,1,0) * (m_elem(*matrix,0,1) * m_elem(*matrix,2,2) - m_elem(*matrix,0,2) * m_elem(*matrix,2,1)) + m_elem(*matrix,2,0) * (m_elem(*matrix,0,1) * m_elem(*matrix,1,2) - m_elem(*matrix,0,2) * m_elem(*matrix,1,1)); } double v_len2(vector) const hvec2_t *vector; { double result; result = ((sqrt(v_x(*vector) * v_x(*vector) + v_y(*vector) * v_y(*vector)))); return v_w(*vector) != 0.0 ? result / v_w(*vector) : result; } double vtmv_mul2(vector, matrix) const hvec2_t *vector; const hmat2_t *matrix; { return ((v_x(*vector) * m_elem(*matrix, 0, 0) + v_y(*vector) * m_elem(*matrix, 1, 0) + v_w(*vector) * m_elem(*matrix, 2, 0)) * v_x(*vector)) + ((v_x(*vector) * m_elem(*matrix, 0, 1) + v_y(*vector) * m_elem(*matrix, 1, 1) + v_w(*vector) * m_elem(*matrix, 2, 1)) * v_y(*vector)) + ((v_x(*vector) * m_elem(*matrix, 0, 2) + v_y(*vector) * m_elem(*matrix, 1, 2) + v_w(*vector) * m_elem(*matrix, 2, 2)) * v_w(*vector)); } double vv_inprod2(vectorA, vectorB) const hvec2_t *vectorA; const hvec2_t *vectorB; { double result, div; result = v_x(*vectorA) * v_x(*vectorB) + v_y(*vectorA) * v_y(*vectorB); div = 1.0; if(v_w(*vectorA) != 0.0 && v_w(*vectorA) != 1.0) div *= v_w(*vectorA); if(v_w(*vectorB) != 0.0 && v_w(*vectorB) != 1.0) div *= v_w(*vectorB); if(div!=1.0) return result/div; return result; } /* Used by "m_inv2()" */ static void submultiples2(m_input, m_result, rownr, workingrow) hmat2_t *m_input, *m_result; int rownr, workingrow; { int i; double subtractionfactor; if((subtractionfactor = m_elem(*m_input, workingrow, rownr)) != 0.0) { for(i=rownr; i<3; i++) m_elem(*m_input,workingrow,i) -= m_elem(*m_input,rownr,i) * subtractionfactor; for(i=0; i<3; i++) m_elem(*m_result,workingrow,i) -= m_elem(*m_result,rownr,i) * subtractionfactor; }; } /* Used by "m_inv2()" */ static void interchangerow2(m_input, m_result, rownr) hmat2_t *m_input, *m_result; int rownr; { int nextelement = rownr+1, i; double buffer; while(m_elem(*m_input, nextelement, rownr) == 0.0) if(++nextelement == 3) gm_error(MATSING, "m_inv2()"); /* interchange one rowelement with an element of */ /* a row with a nonzeroentry in the same column */ for(i=0; i<3; i++) { buffer = m_elem(*m_input, nextelement, i); m_elem(*m_input, nextelement, i) = m_elem(*m_input, rownr, i); m_elem(*m_input, rownr, i) = buffer; buffer = m_elem(*m_result, nextelement, i); m_elem(*m_result, nextelement, i) = m_elem(*m_result, rownr, i); m_elem(*m_result, rownr, i) = buffer; }; } /* Used by m_inv2()" */ static void reduce_row2(m_input, m_result, rownr) hmat2_t *m_input, *m_result; int rownr; { int i; double factor; if(m_elem(*m_input, rownr, rownr) == 0.0) /* interchange this row with another row to bring a nonzero entry in the main diagonal */ interchangerow2(m_input, m_result, rownr); /* introduce a leading one by dividing the whole row */ factor = m_elem(*m_input, rownr, rownr); for(i=rownr; i<3; i++) m_elem(*m_input, rownr, i) /= factor; for(i=0; i<3; i++) m_elem(*m_result, rownr, i) /= factor; for(i=0; i<3; i++) if(i != rownr) /* subtract suitable multiples of this row to the other rows */ /* so that all other entries in this column become zeros. */ submultiples2(m_input, m_result, rownr, i); } /****** Based on invmatrix.c, project ESPRIT 612 by Th. Koster. ******/ hmat2_t * m_inv2(matrix, m_result) const hmat2_t *matrix; hmat2_t *m_result; { hmat2_t m_input; int i, j; m_result = gm_ALLOC(hmat2_t, m_result, "m_inv2()"); for(i=0; i<3; i++) for(j=0; j<3; j++) m_elem(*m_result, i, j) = (i!=j) ? 0.0 : 1.0; /* save contence of matrix */ m_input = *matrix; /* reduce row for row to transform the */ /* input matrix to an elementary matrix */ for(i=0;i<3;i++) /* reduce this row to a row of an elementary matrix */ reduce_row2(&m_input, m_result, i); return m_result; } hmat2_t * m_tra2(matrix, m_result) const hmat2_t *matrix; hmat2_t *m_result; { m_result = gm_ALLOC(hmat2_t, m_result, "m_tra2()"); if(m_result != matrix) { int i,j; for(i=0; i<3; i++) for(j=0; j<3; j++) m_elem(*m_result, i, j) = m_elem(*matrix, j, i); } else { double buf[3]; buf[0] = m_elem(*matrix, 1, 0); buf[1] = m_elem(*matrix, 2, 0); buf[2] = m_elem(*matrix, 2, 1); m_elem(*m_result, 1, 0) = m_elem(*matrix, 0, 1); m_elem(*m_result, 2, 0) = m_elem(*matrix, 0, 2); m_elem(*m_result, 2, 1) = m_elem(*matrix, 1, 2); m_elem(*m_result, 0, 1) = buf[0]; m_elem(*m_result, 0, 2) = buf[1]; m_elem(*m_result, 1, 2) = buf[2]; }; return m_result; } hmat2_t * mm_add2(matrixA, matrixB, m_result) const hmat2_t *matrixA; const hmat2_t *matrixB; hmat2_t *m_result; { int row, col; m_result = gm_ALLOC(hmat2_t, m_result, "mm_add2()"); for(row=0; row<3; row++) for(col=0; col<3; col++) m_elem(*m_result, row, col) = m_elem(*matrixA, row, col) + m_elem(*matrixB, row, col); return m_result; } hmat2_t * mm_mul2(matrixA, matrixB, m_result) const hmat2_t *matrixA; const hmat2_t *matrixB; hmat2_t *m_result; { int row, col, which_matrix; /* Is m_result used in place \ and if which matrix equals \ m_result */ hmat2_t buf; if(m_result == matrixA) { m_result = &buf; which_matrix = 1; } else if(m_result == matrixB) { m_result = &buf; which_matrix = 2; } else { m_result = gm_ALLOC(hmat2_t, m_result, "mm_mul2()"); which_matrix = 0; }; for(row=0; row<3; row++) for(col=0; col<3; col++) m_elem(*m_result, row, col) = m_elem(*matrixA, row, 0) * m_elem(*matrixB, 0, col) + m_elem(*matrixA, row, 1) * m_elem(*matrixB, 1, col) + m_elem(*matrixA, row, 2) * m_elem(*matrixB, 2, col); switch(which_matrix) { case 0 : return m_result; case 1 : /* m_cpy2(m_result, matrixA); */ *(hmat2_t *)matrixA = *m_result; return (hmat2_t *)matrixA; case 2 : /* m_cpy2(m_result, matrixB); */ *(hmat2_t *)matrixB = *m_result; return (hmat2_t *)matrixB; }; error("This should not happen! %s %d\n", __FILE__, __LINE__ ); return m_result; /* garbage... */ } hmat2_t * mm_sub2(matrixA, matrixB, m_result) const hmat2_t *matrixA; const hmat2_t *matrixB; hmat2_t *m_result; { int row, col; m_result = gm_ALLOC(hmat2_t, m_result, "mm_sub2()"); for(row=0; row<3; row++) for(col=0; col<3; col++) m_elem(*m_result, row, col) = m_elem(*matrixA, row, col) - m_elem(*matrixB, row, col); return m_result; } hmat2_t * mtmm_mul2(matrixA, matrixB, m_result) const hmat2_t *matrixA; const hmat2_t *matrixB; hmat2_t *m_result; { hmat2_t help; m_result = gm_ALLOC(hmat2_t, m_result, "mtmm_mul2()"); m_tra2(matrixA, &help); mm_mul2(&help, matrixB, &help); mm_mul2(&help, matrixA, m_result); return m_result; } hmat2_t * sm_mul2(scalar, matrix, m_result) double scalar; const hmat2_t *matrix; hmat2_t *m_result; { int row, col; m_result = gm_ALLOC(hmat2_t, m_result, "sm_mul2()"); for(row=0; row<3; row++) for(col=0; col<3; col++) m_elem(*m_result, row, col) = scalar * m_elem(*matrix, row, col); return m_result; } hmat2_t * vvt_mul2(vectorA, vectorB, m_result) const hvec2_t *vectorA; const hvec2_t *vectorB; hmat2_t *m_result; { int row, col; m_result = gm_ALLOC(hmat2_t, m_result, "vvt_mul2()"); for(row=0; row<3; row++) for(col=0; col<3; col++) m_elem(*m_result, row, col) = v_elem(*vectorA, row) * v_elem(*vectorB, col); return m_result; } hvec2_t * mv_mul2(matrix, vector, v_result) const hmat2_t *matrix; const hvec2_t *vector; hvec2_t *v_result; { int row, inplace; hvec2_t buf; if(v_result == vector) { v_result = &buf; inplace = 1; } else { v_result = gm_ALLOC(hvec2_t, v_result, "mv_mul2()"); inplace = 0; }; for(row=0; row<3; row++) v_elem(*v_result, row) = m_elem(*matrix, row, 0) * v_elem(*vector, 0) + m_elem(*matrix, row, 1) * v_elem(*vector, 1) + m_elem(*matrix, row, 2) * v_elem(*vector, 2); if(inplace) { /* v_cpy2(v_result, vector); */ *(hvec2_t *)vector = *v_result; return (hvec2_t *)vector; }; return v_result; } hvec2_t * sv_mul2(scalar, vector, v_result) double scalar; const hvec2_t *vector; hvec2_t *v_result; { v_result = gm_ALLOC(hvec2_t, v_result, "sv_mul2()"); v_x(*v_result) = v_x(*vector) * scalar; v_y(*v_result) = v_y(*vector) * scalar; v_w(*v_result) = v_w(*vector); return v_result; } hvec2_t * v_homo2(vector, v_result) const hvec2_t *vector; hvec2_t *v_result; { v_result = gm_ALLOC(hvec2_t, v_result, "v_homo2()"); v_x(*v_result) = gm_DIV(v_x(*vector), v_w(*vector), "v_homo2()"); v_y(*v_result) = v_y(*vector) / v_w(*vector); v_w(*v_result) = 1.0; return v_result; } hvec2_t * v_norm2(vector, v_result) const hvec2_t *vector; hvec2_t *v_result; { double length = sqrt(v_x(*vector) * v_x(*vector) + v_y(*vector) * v_y(*vector)); v_result = gm_ALLOC(hvec2_t, v_result, "v_norm2()"); v_x(*v_result) = gm_DIV(v_x(*vector), length, "v_norm2()"); v_y(*v_result) = v_y(*vector) / length; v_w(*v_result) = v_w(*vector) / length; return v_result; } hvec2_t * vv_add2(vectorA, vectorB, v_result) const hvec2_t *vectorA; const hvec2_t *vectorB; hvec2_t *v_result; { v_result = gm_ALLOC(hvec2_t, v_result, "vv_add2()"); v_x(*v_result) = v_x(*vectorA) + v_x(*vectorB); v_y(*v_result) = v_y(*vectorA) + v_y(*vectorB); v_w(*v_result) = v_w(*vectorA) + v_w(*vectorB); return v_result; } hvec2_t * vv_sub2(vectorA, vectorB, v_result) const hvec2_t *vectorA; const hvec2_t *vectorB; hvec2_t *v_result; { v_result = gm_ALLOC(hvec2_t, v_result, "vv_sub2()"); v_x(*v_result) = v_x(*vectorA) - v_x(*vectorB); v_y(*v_result) = v_y(*vectorA) - v_y(*vectorB); v_w(*v_result) = v_w(*vectorA) - v_w(*vectorB); return v_result; } /****** Level 3 : Basic lineair algebra : 3D homogeneous coordinates ******/ /***** Function is optimized, see below !!! double m_det3(matrix) const hmat3_t *matrix; { hmat2_t det2; double result=0.0; int col, count, row, row_det2, factor=1.0; for(count=0; count<4; count++) { row_det2 = 0; for(row=0; row<4; row++) if(count != row) { for(col=1; col<4; col++) m_elem(det2, row_det2, col-1) = m_elem(*matrix, row, col); row_det2++; }; result += m_elem(*matrix, count, 0) * m_det2(&det2) * factor; factor = -factor; }; return result; } */ /* used by m_det3() */ /* return the under-determinant of a 4*4 matrix */ static double det2_dyn(matrix, row_not) const hmat3_t *matrix; int row_not; { int row[3], count, help=0; for(count=0; count<4; count++) if(count != row_not) row[help++] = count; return m_elem(*matrix,row[0],1) * (m_elem(*matrix,row[1],2) * m_elem(*matrix,row[2],3) - m_elem(*matrix,row[1],3) * m_elem(*matrix,row[2],2)) - m_elem(*matrix,row[1],1) * (m_elem(*matrix,row[0],2) * m_elem(*matrix,row[2],3) - m_elem(*matrix,row[0],3) * m_elem(*matrix,row[2],2)) + m_elem(*matrix,row[2],1) * (m_elem(*matrix,row[0],2) * m_elem(*matrix,row[1],3) - m_elem(*matrix,row[0],3) * m_elem(*matrix,row[1],2)); } double m_det3(matrix) const hmat3_t *matrix; { double result=0.0; int row, factor=-1; for(row=0; row<4; row++) result += m_elem(*matrix, row, 0) * det2_dyn(matrix, row) * (factor *= -1); return result; } double v_len3(vector) const hvec3_t *vector; { double result; result = ((sqrt(v_x(*vector) * v_x(*vector) + v_y(*vector) * v_y(*vector) + v_z(*vector) * v_z(*vector)))); return v_w(*vector) != 0.0 ? result / v_w(*vector) : result; } double vtmv_mul3(vector, matrix) const hvec3_t *vector; const hmat3_t *matrix; { return ((v_x(*vector) * m_elem(*matrix, 0, 0) + v_y(*vector) * m_elem(*matrix, 1, 0) + v_z(*vector) * m_elem(*matrix, 2, 0) + v_w(*vector) * m_elem(*matrix, 3, 0)) * v_x(*vector)) + ((v_x(*vector) * m_elem(*matrix, 0, 1) + v_y(*vector) * m_elem(*matrix, 1, 1) + v_z(*vector) * m_elem(*matrix, 2, 1) + v_w(*vector) * m_elem(*matrix, 3, 1)) * v_y(*vector)) + ((v_x(*vector) * m_elem(*matrix, 0, 2) + v_y(*vector) * m_elem(*matrix, 1, 2) + v_z(*vector) * m_elem(*matrix, 2, 2) + v_w(*vector) * m_elem(*matrix, 3, 2)) * v_z(*vector)) + ((v_x(*vector) * m_elem(*matrix, 0, 3) + v_y(*vector) * m_elem(*matrix, 1, 3) + v_z(*vector) * m_elem(*matrix, 2, 3) + v_w(*vector) * m_elem(*matrix, 3, 3)) * v_w(*vector)); } double vv_inprod3(vectorA, vectorB) const hvec3_t *vectorA; const hvec3_t *vectorB; { double result, div; result = v_x(*vectorA) * v_x(*vectorB) + v_y(*vectorA) * v_y(*vectorB) + v_z(*vectorA) * v_z(*vectorB); div = 1.0; if(v_w(*vectorA) != 0.0 && v_w(*vectorA) != 1.0) div *= v_w(*vectorA); if(v_w(*vectorB) != 0.0 && v_w(*vectorB) != 1.0) div *= v_w(*vectorB); if (div != 1.0) return result/div; return result; } /* Used by "m_inv3()" */ static void submultiples3(m_input, m_result, rownr, workingrow) hmat3_t *m_input, *m_result; int rownr, workingrow; { int i; double subtractionfactor; if((subtractionfactor = m_elem(*m_input, workingrow, rownr)) != 0.0) { for(i=rownr; i<4; i++) m_elem(*m_input,workingrow,i) -= m_elem(*m_input,rownr,i) * subtractionfactor; for(i=0; i<4; i++) m_elem(*m_result,workingrow,i) -= m_elem(*m_result,rownr,i) * subtractionfactor; }; } /* Used by "m_inv3()" */ static void interchangerow3(m_input, m_result, rownr) hmat3_t *m_input, *m_result; int rownr; { int nextelement = rownr+1, i; double buffer; while(m_elem(*m_input, nextelement, rownr) == 0.0) if(++nextelement == 4) gm_error(MATSING, "m_inv3()"); /* interchange one rowelement with an element of */ /* a row with a nonzeroentry in the same column */ for(i=0; i<4; i++) { buffer = m_elem(*m_input, nextelement, i); m_elem(*m_input, nextelement, i) = m_elem(*m_input, rownr, i); m_elem(*m_input, rownr, i) = buffer; buffer = m_elem(*m_result, nextelement, i); m_elem(*m_result, nextelement, i) = m_elem(*m_result, rownr, i); m_elem(*m_result, rownr, i) = buffer; }; } /* Used by "m_inv3()" */ static void reduce_row3(m_input, m_result, rownr) hmat3_t *m_input, *m_result; int rownr; { int i; double factor; if(m_elem(*m_input, rownr, rownr) == 0.0) /* interchange this row with another row to bring a nonzero entry in the main diagonal */ interchangerow3(m_input, m_result, rownr); /* introduce a leading one by dividing the whole row */ factor = m_elem(*m_input, rownr, rownr); for(i=rownr; i<4; i++) m_elem(*m_input, rownr, i) /= factor; for(i=0; i<4; i++) m_elem(*m_result, rownr, i) /= factor; for(i=0; i<4; i++) if(i != rownr) /* subtract suitable multiples of this row to the other rows */ /* so that all other entries in this column become zeros. */ submultiples3(m_input, m_result, rownr, i); } /****** Based on invmatrix.c, project ESPRIT 612 by Th. Koster. ******/ hmat3_t * m_inv3(matrix, m_result) const hmat3_t *matrix; hmat3_t *m_result; { hmat3_t m_input; int i; m_result = m_unity3(m_result); /* save contence of matrix */ m_input = *matrix; /* reduce row for row to transform the */ /* input matrix to an elementary matrix */ for(i=0;i<4;i++) /* reduce this row to a row of an elementary matrix */ reduce_row3(&m_input, m_result, i); return m_result; } hmat3_t * m_tra3(matrix, m_result) const hmat3_t *matrix; hmat3_t *m_result; { m_result = gm_ALLOC(hmat3_t, m_result, "m_tra3()"); if(m_result != matrix) { int i, j; m_result = gm_ALLOC(hmat3_t, m_result, "m_tra3()"); for(i=0; i<4; i++) for(j=0; j<4; j++) m_elem(*m_result, i, j) = m_elem(*matrix, j, i); } else { double buf[6]; buf[0] = m_elem(*matrix, 1, 0); buf[1] = m_elem(*matrix, 2, 0); buf[2] = m_elem(*matrix, 2, 1); buf[3] = m_elem(*matrix, 3, 0); buf[4] = m_elem(*matrix, 3, 1); buf[5] = m_elem(*matrix, 3, 2); m_elem(*m_result, 1, 0) = m_elem(*matrix, 0, 1); m_elem(*m_result, 2, 0) = m_elem(*matrix, 0, 2); m_elem(*m_result, 2, 1) = m_elem(*matrix, 1, 2); m_elem(*m_result, 3, 0) = m_elem(*matrix, 0, 3); m_elem(*m_result, 3, 1) = m_elem(*matrix, 1, 3); m_elem(*m_result, 3, 2) = m_elem(*matrix, 2, 3); m_elem(*m_result, 0, 1) = buf[0]; m_elem(*m_result, 0, 2) = buf[1]; m_elem(*m_result, 0, 3) = buf[3]; m_elem(*m_result, 1, 2) = buf[2]; m_elem(*m_result, 1, 3) = buf[4]; m_elem(*m_result, 2, 3) = buf[5]; }; return m_result; } hmat3_t * mm_add3(matrixA, matrixB, m_result) const hmat3_t *matrixA; const hmat3_t *matrixB; hmat3_t *m_result; { int row, col; m_result = gm_ALLOC(hmat3_t, m_result, "mm_add3()"); for(row=0; row<4; row++) for(col=0; col<4; col++) m_elem(*m_result, row, col) = m_elem(*matrixA, row, col) + m_elem(*matrixB, row, col); return m_result; } hmat3_t * mm_mul3(matrixA, matrixB, m_result) const hmat3_t *matrixA; const hmat3_t *matrixB; hmat3_t *m_result; { int row, col, which_matrix; hmat3_t buf; if(m_result == matrixA) { m_result = &buf; which_matrix = 1; } else if(m_result == matrixB) { m_result = &buf; which_matrix = 2; } else { m_result = gm_ALLOC(hmat3_t, m_result, "mm_mul3()"); which_matrix = 0; }; for(row=0; row<4; row++) for(col=0; col<4; col++) m_elem(*m_result, row, col) = m_elem(*matrixA, row, 0) * m_elem(*matrixB, 0, col) + m_elem(*matrixA, row, 1) * m_elem(*matrixB, 1, col) + m_elem(*matrixA, row, 2) * m_elem(*matrixB, 2, col) + m_elem(*matrixA, row, 3) * m_elem(*matrixB, 3, col); switch(which_matrix) { case 0 : return m_result; case 1 : /* m_cpy3(m_result, matrixA); */ * (hmat3_t *)matrixA = *m_result; return (hmat3_t *)matrixA; case 2 : /* m_cpy3(m_result, matrixB); */ *(hmat3_t *)matrixB = *m_result; return (hmat3_t *)matrixB; }; error("This should not happen! %s %d\n", __FILE__, __LINE__ ); return m_result; /* garbage... */ } hmat3_t * mm_sub3(matrixA, matrixB, m_result) const hmat3_t *matrixA; const hmat3_t *matrixB; hmat3_t *m_result; { int row, col; m_result = gm_ALLOC(hmat3_t, m_result, "mm_sub3()"); for(row=0; row<4; row++) for(col=0; col<4; col++) m_elem(*m_result, row, col) = m_elem(*matrixA, row, col) - m_elem(*matrixB, row, col); return m_result; } hmat3_t * mtmm_mul3(matrixA, matrixB, m_result) const hmat3_t *matrixA; const hmat3_t *matrixB; hmat3_t *m_result; { hmat3_t help; m_result = gm_ALLOC(hmat3_t, m_result, "mtmm_mul3()"); m_tra3(matrixA, &help); mm_mul3(&help, matrixB, &help); mm_mul3(&help, matrixA, m_result); return m_result; } hmat3_t * sm_mul3(scalar, matrix, m_result) double scalar; const hmat3_t *matrix; hmat3_t *m_result; { int row, col; m_result = gm_ALLOC(hmat3_t, m_result, "sm_mul3()"); for(row=0; row<4; row++) for(col=0; col<4; col++) m_elem(*m_result, row, col) = scalar * m_elem(*matrix, row, col); return m_result; } hvec3_t * mv_mul3(matrix, vector, v_result) const hmat3_t *matrix; const hvec3_t *vector; hvec3_t *v_result; { int row, inplace; hvec3_t buf; if(v_result == vector) { v_result = &buf; inplace = 1; } else { v_result = gm_ALLOC(hvec3_t, v_result, "mv_mul3()"); inplace = 0; }; for(row=0; row<4; row++) v_elem(*v_result, row) = m_elem(*matrix, row, 0) * v_elem(*vector, 0) + m_elem(*matrix, row, 1) * v_elem(*vector, 1) + m_elem(*matrix, row, 2) * v_elem(*vector, 2) + m_elem(*matrix, row, 3) * v_elem(*vector, 3); if(inplace) { v_cpy3(v_result, (hvec3_t *)vector); return (hvec3_t *) vector; }; return v_result; } hvec3_t * sv_mul3(scalar, vector, v_result) double scalar; const hvec3_t *vector; hvec3_t *v_result; { v_result = gm_ALLOC(hvec3_t, v_result, "sv_mul3()"); v_x(*v_result) = v_x(*vector) * scalar; v_y(*v_result) = v_y(*vector) * scalar; v_z(*v_result) = v_z(*vector) * scalar; v_w(*v_result) = v_w(*vector); return v_result; } hvec3_t * v_homo3(vector, v_result) const hvec3_t *vector; hvec3_t *v_result; { v_result = gm_ALLOC(hvec3_t, v_result, "v_homo3()"); v_x(*v_result) = gm_DIV(v_x(*vector), v_w(*vector), "v_homo3()"); v_y(*v_result) = v_y(*vector) / v_w(*vector); v_z(*v_result) = v_z(*vector) / v_w(*vector); v_w(*v_result) = 1.0; return v_result; } hvec3_t * v_norm3(vector, v_result) const hvec3_t *vector; hvec3_t *v_result; { double length = sqrt(v_x(*vector) * v_x(*vector) + v_y(*vector) * v_y(*vector) + v_z(*vector) * v_z(*vector)); v_result = gm_ALLOC(hvec3_t, v_result, "v_norm3()"); /* length = sqrt(v_x(*vector) * v_x(*vector) + // v_y(*vector) * v_y(*vector) + // v_z(*vector) * v_z(*vector)); */ v_x(*v_result) = gm_DIV(v_x(*vector), length, "v_norm2()"); v_y(*v_result) = v_y(*vector) / length; v_z(*v_result) = v_z(*vector) / length; v_w(*v_result) = v_w(*vector) / length; return v_result; } hvec3_t * vv_add3(vectorA, vectorB, v_result) const hvec3_t *vectorA; const hvec3_t *vectorB; hvec3_t *v_result; { v_result = gm_ALLOC(hvec3_t, v_result, "vv_add3()"); v_x(*v_result) = v_x(*vectorA) + v_x(*vectorB); v_y(*v_result) = v_y(*vectorA) + v_y(*vectorB); v_z(*v_result) = v_z(*vectorA) + v_z(*vectorB); v_w(*v_result) = v_w(*vectorA) + v_w(*vectorB); return v_result; } hvec3_t * vv_cross3(vectorA, vectorB, v_result) const hvec3_t *vectorA; const hvec3_t *vectorB; hvec3_t *v_result; { int which_vec; /* Is v_result used in place, if so which \ vectors are equal ? */ hvec3_t buf; if(v_result == vectorA) { v_result = &buf; which_vec = 1; } else if(v_result == vectorB) { v_result = &buf; which_vec = 2; } else { v_result = gm_ALLOC(hvec3_t, v_result, "vv_cross3()"); which_vec = 0; }; v_x(*v_result) = v_y(*vectorA) * v_z(*vectorB) - v_z(*vectorA) * v_y(*vectorB); v_y(*v_result) = v_z(*vectorA) * v_x(*vectorB) - v_x(*vectorA) * v_z(*vectorB); v_z(*v_result) = v_x(*vectorA) * v_y(*vectorB) - v_y(*vectorA) * v_x(*vectorB); v_w(*v_result) = v_w(*vectorA) * v_w(*vectorB); switch(which_vec) { case 0 : return v_result; case 1 : /* v_cpy3(v_result, vectorA); */ *(hvec3_t *)vectorA = *v_result; return (hvec3_t *)vectorA; case 2 : /* v_cpy3(v_result, vectorB); */ *(hvec3_t *)vectorB = *v_result; return (hvec3_t *)vectorB; }; error("This should not happen! %s %d\n", __FILE__, __LINE__ ); return v_result; /* garbage... */ } hvec3_t * vv_sub3(vectorA, vectorB, v_result) const hvec3_t *vectorA; const hvec3_t *vectorB; hvec3_t *v_result; { v_result = gm_ALLOC(hvec3_t, v_result, "vv_sub3()"); v_x(*v_result) = v_x(*vectorA) - v_x(*vectorB); v_y(*v_result) = v_y(*vectorA) - v_y(*vectorB); v_z(*v_result) = v_z(*vectorA) - v_z(*vectorB); v_w(*v_result) = v_w(*vectorA) - v_w(*vectorB); return v_result; } hmat3_t * vvt_mul3(vectorA, vectorB, m_result) const hvec3_t *vectorA; const hvec3_t *vectorB; hmat3_t *m_result; { int row, col; m_result = gm_ALLOC(hmat3_t, m_result, "vvt_mul3()"); for(row=0; row<4; row++) for(col=0; col<4; col++) m_elem(*m_result, row, col) = v_elem(*vectorA, row) * v_elem(*vectorB, col); return m_result; } /****** Level 4 : Elementary transformations ******/ hmat2_t * miraxis2(axis, m_result) b_axis axis; hmat2_t *m_result; { int i, j; m_result = gm_ALLOC(hmat2_t, m_result, "miraxis2()"); for(i=0; i<3; i++) for(j=0; j<3; j++) m_elem(*m_result, i, j) = (i != j) ? 0.0 : 1.0; if(axis == X_AXIS) m_elem(*m_result, 1, 1) = -1.0; else m_elem(*m_result, 0, 0) = -1.0; return m_result; } hmat2_t * mirorig2(m_result) hmat2_t *m_result; { int i, j; m_result = gm_ALLOC(hmat2_t, m_result, "mirorig()"); for(i=0; i<3; i++) for(j=0; j<3; j++) m_elem(*m_result, i, j) = (i != j) ? 0.0 : -1.0; m_elem(*m_result, 2, 2) = 1.0; return m_result; } hmat2_t * rot2(rotation, m_result) double rotation; hmat2_t *m_result; { m_result = gm_ALLOC(hmat2_t, m_result, "rot2()"); m_elem(*m_result, 0, 0) = m_elem(*m_result, 1, 1) = cos(rotation); m_elem(*m_result, 1, 0) = sin(rotation); m_elem(*m_result, 0, 1) = -m_elem(*m_result, 1, 0); m_elem(*m_result, 2, 0) = m_elem(*m_result, 2, 1) = m_elem(*m_result, 0, 2) = m_elem(*m_result, 1, 2) = 0.0; m_elem(*m_result, 2, 2) = 1.0; return m_result; } hmat2_t * scaorig2(scale, m_result) double scale; hmat2_t *m_result; { int i, j; m_result = gm_ALLOC(hmat2_t, m_result, "scaorig2()"); for(i=0; i<3; i++) for(j=0; j<3; j++) m_elem(*m_result, i, j) = (i != j) ? 0.0 : scale; m_elem(*m_result, 2, 2) = 1.0; return m_result; } hmat2_t * scaxis2(scale, axis, m_result) double scale; b_axis axis; hmat2_t *m_result; { #ifdef notdef int i, j; m_result = gm_ALLOC(hmat2_t, m_result, "miraxis2()"); for(i=0; i<3; i++) for(j=0; j<3; j++) m_elem(*m_result, i, j) = (i != j) ? 0.0 : scale; #else m_result = m_unity2(m_result); #endif if(axis == X_AXIS) m_elem(*m_result, 1, 1) = scale; else m_elem(*m_result, 0, 0) = scale; return m_result; } hmat2_t * transl2(translation, m_result) const hvec2_t *translation; hmat2_t *m_result; { int i, j; m_result = gm_ALLOC(hmat2_t, m_result, "transl2()"); for(i=0; i<3; i++) for(j=0; j<2; j++) m_elem(*m_result, i, j) = (i != j) ? 0.0 : 1.0; m_elem(*m_result, 0, 2) = v_x(*translation); m_elem(*m_result, 1, 2) = v_y(*translation); m_elem(*m_result, 2, 2) = 1.0; return m_result; } hmat3_t * miraxis3(axis, m_result) b_axis axis; hmat3_t *m_result; { int i,j; m_result = gm_ALLOC(hmat3_t, m_result, "miraxis3()"); for(i=0; i<4; i++) for(j=0; j<4; j++) m_elem(*m_result, i, j) = (i != j) ? 0.0 : (i != (int)axis) ? 1.0 : -1.0; m_elem(*m_result, 3, 3) = 1.0; return m_result; } hmat3_t * mirorig3(m_result) hmat3_t *m_result; { int i, j; m_result = gm_ALLOC(hmat3_t, m_result, "mirorig3()"); for(i=0; i<4; i++) for(j=0; j<4; j++) m_elem(*m_result, i, j) = (i != j) ? 0.0 : -1.0; m_elem(*m_result, 3, 3) = 1.0; return m_result; } hmat3_t * mirplane3(plane, m_result) b_axis plane; hmat3_t *m_result; { int i, j; m_result = gm_ALLOC(hmat3_t, m_result, "mirplane3()"); for(i=0; i<4; i++) for(j=0; j<4; j++) m_elem(*m_result, i, j) = (i != j) ? 0.0 : 1.0; m_elem(*m_result, (int)plane, (int)plane) = -1.0; return m_result; } hmat3_t * prjorthaxis(axis, m_result) b_axis axis; hmat3_t *m_result; { #ifndef notdef /* An orthographic projection, handled similar to a perspective * projection, is a unity operator! * So the coordinate of the axis over which is projected is the * distance from the projection plane to the input vector */ m_result = m_unity3(m_result); #else /* notdef */ int i, j; m_result = gm_ALLOC(hmat3_t, m_result, "prjorthaxis()"); for(i=0; i<4; i++) for(j=0; j<4; j++) m_elem(*m_result, i, j) = (i!=j) ? 0.0 : 1.0; m_elem(*m_result, (int)axis, (int)axis) = 0.0; #endif /* notdef */ return m_result; } hmat3_t * prjpersaxis(axis, m_result) b_axis axis; hmat3_t *m_result; { #ifdef notdef hvec3_t x, y, z, viewdir; int i; #endif m_result = m_unity3(m_result); m_elem(*m_result,3,3) = 0.0; switch(axis) { case X_AXIS : m_elem(*m_result,3,0) = 1.0; break; case Y_AXIS : m_elem(*m_result,3,1) = 1.0; break; case Z_AXIS : m_elem(*m_result,3,2) = 1.0; break; }; return m_result; } hmat3_t * rot3(rotation, axis, m_result) double rotation; b_axis axis; hmat3_t *m_result; { int i, j; m_result = gm_ALLOC(hmat3_t, m_result, "rot3()"); for(i=0; i<4; i++) for(j=0; j<4; j++) m_elem(*m_result, i, j) = (i!=j) ? 0.0 : 1.0; i = ((int)axis + 1)%3; j = ((int)axis + 2)%3; m_elem(*m_result, i, i) = m_elem(*m_result, j, j) = cos(rotation); m_elem(*m_result, j, i) = sin(rotation); m_elem(*m_result, i, j) = -m_elem(*m_result, j, i); return m_result; } hmat3_t * scaorig3(scale, m_result) double scale; hmat3_t *m_result; { int i, j; m_result = gm_ALLOC(hmat3_t, m_result, "scaorig2()"); for(i=0; i<4; i++) for(j=0; j<4; j++) m_elem(*m_result, i, j) = (i != j) ? 0.0 : scale; m_elem(*m_result, 3, 3) = 1.0; return m_result; } hmat3_t * scaplane3(scale, plane, m_result) double scale; b_axis plane; hmat3_t *m_result; { int i, j; m_result = gm_ALLOC(hmat3_t, m_result, "scaplane3()"); for(i=0; i<4; i++) for(j=0; j<4; j++) m_elem(*m_result, i, j) = (i != j) ? 0.0 : 1.0; m_elem(*m_result, (int)plane, (int)plane) = scale; return m_result; } hmat3_t * scaxis3(scale, axis, m_result) double scale; b_axis axis; hmat3_t *m_result; { #ifdef notdef int i,j; m_result = gm_ALLOC(hmat3_t, m_result, "scaxis3()"); for(i=0; i<4; i++) for(j=0; j<4; j++) m_elem(*m_result, i, j) = (i != j) ? 0.0 : (i != (int)axis) ? -1.0 : scale; m_elem(*m_result, 3, 3) = 1.0; #else m_result = m_unity3(m_result); m_elem(*m_result, axis, axis) = scale; #endif return m_result; } hmat3_t * transl3(translation, m_result) const hvec3_t *translation; hmat3_t *m_result; { int i, j; m_result = gm_ALLOC(hmat3_t, m_result, "transl2()"); for(i=0; i<4; i++) for(j=0; j<3; j++) m_elem(*m_result, i, j) = (i != j) ? 0.0 : 1.0; m_elem(*m_result, 0, 3) = v_x(*translation); m_elem(*m_result, 1, 3) = v_y(*translation); m_elem(*m_result, 2, 3) = v_z(*translation); m_elem(*m_result, 3, 3) = 1.0; return m_result; } clippoly-pl11/graphmat.h0100644000076400010400000002414310210704445016436 0ustar KlamerAdministrators/* * tutvis library * Copyright (C) 1993 University of Twente * klamer@mi.el.utwente.nl * 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. */ /* graphmat.h Author: Hans Gringhuis graphmat - 3d graphics and associated matrix and vector routines */ /* * $Log: graphmat.h,v $ * Revision 1.6 2005/02/28 21:12:05 klamer * Made changes such that gcc 3.4.2 compiles silent with -ansi -pedantic -Wall. * * Revision 1.5 2005/02/28 17:21:12 klamer * Changed to have g++ 3.2.3 run silently using g++ -ansi -pedantic -Wall -Wno-unused -Wno-reorder. * Change use of (libg++) String to ANSI C++ string. * * Revision 1.6 1992/10/16 16:16:47 klamer * Gave anonymous structures and unions names; * This to circumvent bug in gdb4.5. * * Revision 1.5 1992/09/11 15:08:09 klamer * deleted const on first argument of gm_alloc. * added const to v_len2() call. * * Revision 1.4 1992/05/19 07:41:49 klamer * gm_dummy is no longer defined if C++ is used. * C++ is more efficient now! * * Revision 1.3 1992/05/11 13:10:54 klamer * Added const in prototypes for const arguments. * * Revision 1.2 1992/05/07 14:48:47 klamer * made C++ compatible. * */ #ifndef GRAPHMAT_INCLUDE #define GRAPHMAT_INCLUDE /****** Other includes ******/ #ifdef __cplusplus #include #include #include #else #ifndef FILE #include #endif #ifndef __malloc_h #include #endif #ifndef __math_h #include #endif #endif /****** DEFINES ******/ /* macro's for accessing the data elements of a vector or a matrix */ #define m_elem(mat, i, j) ((mat).m[(i)][(j)]) #define v_elem(vec, i) ((vec).a[(int)(i)]) #define v_x(vec) ((vec).s.x) #define v_y(vec) ((vec).s.y) #define v_z(vec) ((vec).s.z) #define v_w(vec) ((vec).s.w) /* #define gm_NEW(type, ptr, func) \ (((gm_dummy = malloc(sizeof(type))) == NULL) ? \ ((type *)gm_error(NOMEM, func)) : \ (type *)gm_dummy) */ typedef enum { DIV0, NOMEM, MATSING } gm_error_t; #ifdef __cplusplus extern "C" void gm_error( int, const char * ); #ifdef __GNUG__ #pragma interface #endif inline void * gm_alloc( /*const*/ void *ptr, const char *func, int len ) { if (ptr != 0) return ptr; else { void *gm_dummy; if ((gm_dummy = malloc(len)) == NULL) return gm_error(NOMEM,func), (void *)0; else return gm_dummy; } } #define gm_ALLOC(type, ptr, func) ((type *) \ gm_alloc(ptr, func, sizeof(type)) #else /****** Globals ******/ char *gm_dummy; /* used for memory allocation in gm_ALLOC() */ /* check if ptr is NULL, if so then allocate memory else return ptr */ #define gm_ALLOC(type, ptr, func) (((ptr) == NULL) ? \ ((gm_dummy = malloc(sizeof(type))) == NULL) ? \ ((type *)gm_error(NOMEM, func)) : \ (type *)gm_dummy : (ptr)) #endif /* if ptr is NULL then deallocate used space pointed by ptr */ #define gm_FREE(ptr) if((ptr) != NULL) free((char *)(ptr)) /* divide num by div if div != 0 else gm_error() */ #define gm_DIV(num, div, func) (((div) != 0.0) ? ((num) / (div)) : gm_error(DIV0, (func))) /****** Level 1 : data definition ******/ typedef union hvec2_t { double a[3]; struct hvec2_s { double x, y, w; } s; } hvec2_t; typedef union hvec3_t { double a[4]; struct hvec3_s { double x, y, z, w; } s; } hvec3_t; typedef struct hmat2_t { double m[3][3]; } hmat2_t; typedef struct hmat3_t { double m[4][4]; } hmat3_t; typedef enum { X_AXIS, Y_AXIS, Z_AXIS } b_axis; /****** Level 2 : Data initialisation ******/ #define m_free2(matrix) gm_FREE(matrix) #define v_free2(vector) gm_FREE(vector) #define m_free3(matrix) gm_FREE(matrix) #define v_free3(vector) gm_FREE(vector) #ifndef __cplusplus #define m_alloc2(m_result) gm_ALLOC(hmat2_t, (m_result), "m_alloc2()") #define v_alloc2(v_result) gm_ALLOC(hvec2_t, (v_result), "v_alloc2()") #define m_alloc3(m_result) gm_ALLOC(hmat3_t, (m_result), "m_alloc3()") #define v_alloc3(v_result) gm_ALLOC(hvec3_t, (v_result), "v_alloc3()") #else inline void * Alloc(unsigned int x ) { void *res; res = malloc(x); if (res == 0) gm_error(NOMEM,"Alloc"); return res; } inline hmat2_t * m_alloc2(hmat2_t *r) { if (r) return r; else return (hmat2_t *) Alloc(sizeof(hmat2_t)); } inline hmat3_t * m_alloc3(hmat3_t *r) { if (r) return r; else return (hmat3_t *) Alloc(sizeof(hmat3_t)); } inline hvec2_t * v_alloc2(hvec2_t *r) { if (r) return r; else return (hvec2_t *) Alloc(sizeof(hvec2_t)); } inline hvec3_t * v_alloc3(hvec3_t *r) { if (r) return r; else return (hvec3_t *) Alloc(sizeof(hvec3_t)); } #endif /****** FUNCTION DEFINITIONS ******/ #if defined(__STDC__) || defined(__cplusplus) # define P_(s) s #else # define P_(s) () #endif #ifdef __cplusplus extern "C" { #define C__ } #else #define C__ #endif hmat2_t *m_cpy2 P_((const hmat2_t *m_source, hmat2_t *m_result)); hmat2_t *m_unity2 P_((hmat2_t *m_result)); hvec2_t *v_cpy2 P_((const hvec2_t *v_source, hvec2_t *v_result)); hvec2_t *v_fill2 P_((double x, double y, double w, hvec2_t *v_result)); hvec2_t *v_unity2 P_((b_axis axis, hvec2_t *v_result)); hvec2_t *v_zero2 P_((hvec2_t *v_result)); hmat3_t *m_cpy3 P_((const hmat3_t *m_source, hmat3_t *m_result)); hmat3_t *m_unity3 P_((hmat3_t *m_result)); hvec3_t *v_cpy3 P_((const hvec3_t *v_source, hvec3_t *v_result)); hvec3_t *v_fill3 P_((double x, double y, double z, double w, hvec3_t *v_result)); hvec3_t *v_unity3 P_((b_axis axis, hvec3_t *v_result)); hvec3_t *v_zero3 P_((hvec3_t *v_result)); double m_det2 P_((const hmat2_t *matrix)); double v_len2 P_((const hvec2_t *vector)); double vtmv_mul2 P_((const hvec2_t *vector, const hmat2_t *matrix)); double vv_inprod2 P_((const hvec2_t *vectorA, const hvec2_t *vectorB)); hmat2_t *m_inv2 P_((const hmat2_t *matrix, hmat2_t *m_result)); hmat2_t *m_tra2 P_((const hmat2_t *matrix, hmat2_t *m_result)); hmat2_t *mm_add2 P_((const hmat2_t *matrixA, const hmat2_t *matrixB, hmat2_t *m_result)); hmat2_t *mm_mul2 P_((const hmat2_t *matrixA, const hmat2_t *matrixB, hmat2_t *m_result)); hmat2_t *mm_sub2 P_((const hmat2_t *matrixA, const hmat2_t *matrixB, hmat2_t *m_result)); hmat2_t *mtmm_mul2 P_((const hmat2_t *matrixA, const hmat2_t *matrixB, hmat2_t *m_result)); hmat2_t *sm_mul2 P_((double scalar, const hmat2_t *matrix, hmat2_t *m_result)); hmat2_t *vvt_mul2 P_((const hvec2_t *vectorA, const hvec2_t *vectorB, hmat2_t *m_result)); hvec2_t *mv_mul2 P_((const hmat2_t *matrix, const hvec2_t *vector, hvec2_t *v_result)); hvec2_t *sv_mul2 P_((double scalar, const hvec2_t *vector, hvec2_t *v_result)); hvec2_t *v_homo2 P_((const hvec2_t *vector, hvec2_t *v_result)); hvec2_t *v_norm2 P_((const hvec2_t *vector, hvec2_t *v_result)); hvec2_t *vv_add2 P_((const hvec2_t *vectorA, const hvec2_t *vectorB, hvec2_t *v_result)); hvec2_t *vv_sub2 P_((const hvec2_t *vectorA, const hvec2_t *vectorB, hvec2_t *v_result)); double m_det3 P_((const hmat3_t *matrix)); double v_len3 P_((const hvec3_t *vector)); double vtmv_mul3 P_((const hvec3_t *vector, const hmat3_t *matrix)); double vv_inprod3 P_((const hvec3_t *vectorA, const hvec3_t *vectorB)); hmat3_t *m_inv3 P_((const hmat3_t *matrix, hmat3_t *m_result)); hmat3_t *m_tra3 P_((const hmat3_t *matrix, hmat3_t *m_result)); hmat3_t *mm_add3 P_((const hmat3_t *matrixA, const hmat3_t *matrixB, hmat3_t *m_result)); hmat3_t *mm_mul3 P_((const hmat3_t *matrixA, const hmat3_t *matrixB, hmat3_t *m_result)); hmat3_t *mm_sub3 P_((const hmat3_t *matrixA, const hmat3_t *matrixB, hmat3_t *m_result)); hmat3_t *mtmm_mul3 P_((const hmat3_t *matrixA, const hmat3_t *matrixB, hmat3_t *m_result)); hmat3_t *sm_mul3 P_((double scalar, const hmat3_t *matrix, hmat3_t *m_result)); hvec3_t *mv_mul3 P_((const hmat3_t *matrix, const hvec3_t *vector, hvec3_t *v_result)); hvec3_t *sv_mul3 P_((double scalar, const hvec3_t *vector, hvec3_t *v_result)); hvec3_t *v_homo3 P_((const hvec3_t *vector, hvec3_t *v_result)); hvec3_t *v_norm3 P_((const hvec3_t *vector, hvec3_t *v_result)); hvec3_t *vv_add3 P_((const hvec3_t *vectorA, const hvec3_t *vectorB, hvec3_t *v_result)); hvec3_t *vv_cross3 P_((const hvec3_t *vectorA, const hvec3_t *vectorB, hvec3_t *v_result)); hvec3_t *vv_sub3 P_((const hvec3_t *vectorA, const hvec3_t *vectorB, hvec3_t *v_result)); hmat3_t *vvt_mul3 P_((const hvec3_t *vectorA, const hvec3_t *vectorB, hmat3_t *m_result)); hmat2_t *miraxis2 P_((b_axis axis, hmat2_t *m_result)); hmat2_t *mirorig2 P_((hmat2_t *m_result)); hmat2_t *rot2 P_((double rotation, hmat2_t *m_result)); hmat2_t *scaorig2 P_((double scale, hmat2_t *m_result)); hmat2_t *scaxis2 P_((double scale, b_axis axis, hmat2_t *m_result)); hmat2_t *transl2 P_((const hvec2_t *translation, hmat2_t *m_result)); hmat3_t *miraxis3 P_((b_axis axis, hmat3_t *m_result)); hmat3_t *mirorig3 P_((hmat3_t *m_result)); hmat3_t *mirplane3 P_((b_axis plane, hmat3_t *m_result)); hmat3_t *prjorthaxis P_((b_axis axis, hmat3_t *m_result)); hmat3_t *prjpersaxis P_((b_axis axis, hmat3_t *m_result)); hmat3_t *rot3 P_((double rotation, b_axis axis, hmat3_t *m_result)); hmat3_t *scaorig3 P_((double scale, hmat3_t *m_result)); hmat3_t *scaplane3 P_((double scale, b_axis plane, hmat3_t *m_result)); hmat3_t *scaxis3 P_((double scale, b_axis axis, hmat3_t *m_result)); hmat3_t *transl3 P_((const hvec3_t *translation, hmat3_t *m_result)); C__ #undef C__ #undef P_ #endif clippoly-pl11/in_file0100644000076400010400000000006510210642561016007 0ustar KlamerAdministrators1 -1 0 1 2 1 PolyMagic 0 0 1 2 2 0 PolyMagic clippoly-pl11/in_file.test0100644000076400010400000000050410210642561016763 0ustar KlamerAdministrators0.043677 0.0036737 0.0490363 -0.0524051 0.00302704 -0.0568021 -0.00233231 -0.000723313 PolyMagic 0.043677 0.0036737 0.0213455 0.00153953 0.0180227 0.00206061 0.0237406 0.0385219 0.0850047 0.0289144 0.0792868 -0.00754689 0.0442238 -0.00204827 PolyMagic clippoly-pl11/in_file.wrong0100644000076400010400000000006510210642561017142 0ustar KlamerAdministrators1 -1 2 1 0 1 PolyMagic 0 0 2 0 1 2 PolyMagic clippoly-pl11/lgpl.texinfo0100644000076400010400000006307610210642561017026 0ustar KlamerAdministrators@ifset lgpl-appendix @appendix GNU LIBRARY GENERAL PUBLIC LICENSE @end ifset @ifclear lgpl-appendix @unnumbered GNU LIBRARY GENERAL PUBLIC LICENSE @end ifclear @center Version 2, June 1991 @display Copyright @copyright{} 1991 Free Software Foundation, Inc. 675 Mass Ave, Cambridge, MA 02139, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the library GPL. It is numbered 2 because it goes with version 2 of the ordinary GPL.] @end display @unnumberedsec Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software---to make sure the software is free for all its users. This license, the Library General Public License, applies to some specially designated Free Software Foundation software, and to any other libraries whose authors decide to use it. You can use it for your libraries, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library, or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link a program with the library, you must provide complete object files to the recipients so that they can relink them with the library, after making changes to the library and recompiling it. And you must show them these terms so they know their rights. Our method of protecting your rights has two steps: (1) copyright the library, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the library. Also, for each distributor's protection, we want to make certain that everyone understands that there is no warranty for this free library. If the library is modified by someone else and passed on, we want its recipients to know that what they have is not the original version, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that companies distributing free software will individually obtain patent licenses, thus in effect transforming the program into proprietary software. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License, which was designed for utility programs. This license, the GNU Library General Public License, applies to certain designated libraries. This license is quite different from the ordinary one; be sure to read it in full, and don't assume that anything in it is the same as in the ordinary license. The reason we have a separate public license for some libraries is that they blur the distinction we usually make between modifying or adding to a program and simply using it. Linking a program with a library, without changing the library, is in some sense simply using the library, and is analogous to running a utility program or application program. However, in a textual and legal sense, the linked executable is a combined work, a derivative of the original library, and the ordinary General Public License treats it as such. Because of this blurred distinction, using the ordinary General Public License for libraries did not effectively promote software sharing, because most developers did not use the libraries. We concluded that weaker conditions might promote sharing better. However, unrestricted linking of non-free programs would deprive the users of those programs of all benefit from the free status of the libraries themselves. This Library General Public License is intended to permit developers of non-free programs to use free libraries, while preserving your freedom as a user of such programs to change the free libraries that are incorporated in them. (We have not seen how to achieve this as regards changes in header files, but we have achieved it as regards changes in the actual functions of the Library.) The hope is that this will lead to faster development of free libraries. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a ``work based on the library'' and a ``work that uses the library''. The former contains code derived from the library, while the latter only works together with the library. Note that it is possible for a library to be covered by the ordinary General Public License rather than by this special one. @iftex @unnumberedsec TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION @end iftex @ifinfo @center TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION @end ifinfo @enumerate @item This License Agreement applies to any software library which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Library General Public License (also called ``this License''). Each licensee is addressed as ``you''. A ``library'' means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The ``Library'', below, refers to any such software library or work which has been distributed under these terms. A ``work based on the Library'' means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term ``modification''.) ``Source code'' for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. @item You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. @item You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: @enumerate @item The modified work must itself be a software library. @item You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. @item You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. @item If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) @end enumerate These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. @item You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. @item You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. @item A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a ``work that uses the Library''. Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a ``work that uses the Library'' with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a ``work that uses the library''. The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a ``work that uses the Library'' uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. @item As an exception to the Sections above, you may also compile or link a ``work that uses the Library'' with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: @enumerate @item Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable ``work that uses the Library'', as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) @item Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. @item If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. @item Verify that the user has already received a copy of these materials or that you have already sent this user a copy. @end enumerate For an executable, the required form of the ``work that uses the Library'' must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. @item You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: @enumerate @item Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. @item Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. @end enumerate @item You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. @item You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. @item Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. @item If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. @item If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. @item The Free Software Foundation may publish revised and/or new versions of the Library General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and ``any later version'', you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. @item If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. @iftex @heading NO WARRANTY @end iftex @ifinfo @center NO WARRANTY @end ifinfo @item BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY ``AS IS'' WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. @item IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. @end enumerate @iftex @heading END OF TERMS AND CONDITIONS @end iftex @ifinfo @center END OF TERMS AND CONDITIONS @end ifinfo @page @unnumberedsec How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the ``copyright'' line and a pointer to where the full notice is found. @smallexample @var{one line to give the library's name and a brief idea of what it does.} Copyright (C) @var{year} @var{name of author} 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. @end smallexample Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a ``copyright disclaimer'' for the library, if necessary. Here is a sample; alter the names: @example Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. @var{signature of Ty Coon}, 1 April 1990 Ty Coon, President of Vice @end example That's all there is to it! clippoly-pl11/Makefile0100644000076400010400000000156010210704444016117 0ustar KlamerAdministrators#CCC = g++ -B/usr/local/lib/gcc-lib/sparc-sun-solaris2.3/rotd/ CCC = g++ -fno-implicit-templates #CCC = CC # You can use gcc as a C compiler if cc doesn't work CC = gcc #CC = cc -cckr CCFLAGS = -Wall -g -I. -DGEN_TEMPLATES #CCFLAGS = -g -I. CFLAGS = -g -I. # Uncomment the next four lines if your make does not know about .cc # C++ files (like the SGI make) .SUFFIXES: .o .c .cc .cc.o: $(CCC) $(CCFLAGS) -c $< OBJ = nclip.o primitives.o posadder.o poly.o test.o poly_io.o templates.o LIBOBJ = err.o graphadd.o graphmat.o graphmat++.o prog: ${OBJ} ${LIBOBJ} ${CCC} $(CCFLAGS) -o prog ${OBJ} ${LIBOBJ} -lm purify: ${OBJ} ${LIBOBJ} purify -collector=/usr/local/lib/gcc-lib/sun4/2.4.5/ld \ ${CCC} -o prog ${OBJ} ${LIBOBJ} -lm test: prog prog < in_file > out_file diff -b out_file.dist out_file clean: rm -f *.o prog core out_file clippoly-pl11/nclip.cc0100644000076400010400000004427010210651410016072 0ustar KlamerAdministratorsstatic const char rcs_id[] = "$Header: /cvsroot/clippoly/clippoly/nclip.cc,v 1.5 2005/02/28 17:21:12 klamer Exp $"; // nclip: a polygon clip library // Copyright (C) 1993 University of Twente // klamer@mi.el.utwente.nl // 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. // $Log: nclip.cc,v $ // Revision 1.5 2005/02/28 17:21:12 klamer // Changed to have g++ 3.2.3 run silently using g++ -ansi -pedantic -Wall -Wno-unused -Wno-reorder. // Change use of (libg++) String to ANSI C++ string. // // Revision 1.2 1994/01/04 12:55:37 klamer // Added DEBUG_NCLIP support. // Make intersect call itself again if the polygons change. // New function label_shared2, called from label_shared. // Major changes in label_shared. // Make_poly depends on inproducts now rather than on angles. // Make sure starting polygons are clockwise oriented. // // Revision 1.1 1992/12/07 10:46:35 klamer // Initial revision // #ifdef __GNUG__ #pragma implementation #endif #include #include #include #include #include #include #include #include #include "nclip.h" #ifdef DEBUG1 #include #include #endif #ifdef DEBUG_NCLIP #include "poly_io.h" #include #include #include static ofstream db("debugnc"); #endif static const char h_rcs_id[] = NCLIP_H; // Intersect Edge a & b, and return the intersection point in p1 and p2. // The return value means the number of intersections. Two intersections // mean that a and b are on the same line, the intersection points are in that // case the extrema of the joint line segment int intersect( const Edge &a, const Edge &b, Point &p1, Point &p2 ) { hvec2_t s1, s2; int ret = v_inters2( a.p1().hvec(), a.p2().hvec(), b.p1().hvec(), b.p2().hvec(), &s1, &s2 ); switch(ret) {case 2: p2 = s2; // Fall Through case 1: p1 = s1; } return ret; } // calculate all the intersections between a and b. Add the intersection points // to a and b. // returns total number of intersections found. int intersect( Poly &a, Poly &b ) { PolyIter a_iter( a ); int res = 0, res2 = 0; while( a_iter() ) { PolyIter b_iter( b ); while( b_iter() ) { Point intersect1, intersect2; int cnt = intersect( a_iter.edge(), b_iter.edge(), intersect1, intersect2 ); res += cnt; if (cnt) { res2 += PolyIter::add_point( a_iter, b_iter, intersect1 ); if (cnt >= 2) { res2 += PolyIter::add_point( a_iter, b_iter, intersect2 ); } } } } if (res2 != 0) return res + intersect(a,b); return res; } // Check whether line p1-p2 is inside the polygon pointed by pn. p1 should equal pn. // if inside do a_iter.set_inside() else a_iter.set_none(), as it is outside void label_shared2( PolyIter &pi, const Point &p1, const Point &p2, const PolyNode &pn ) { assert(p1 == pn.point()); Point prev = pn.prevnode().point(), next = pn.nextnode().point(); // The *dir are direction vectors! Point cdir = p2 - p1, pdir = p1 - prev, ndir = next - p1; int p_c = (pdir.x() * cdir.y() - pdir.y() * cdir.x()) >= 0, n_c = (ndir.x() * cdir.y() - ndir.y() * cdir.x()) >= 0, p_n = (pdir.x() * ndir.y() - pdir.y() * ndir.x()) >= 0; if (p_n) // pn points to a concave corner? { if (p_c && n_c) pi.set_none(); else pi.set_inside(); } else { if (p_c || n_c) pi.set_none(); else pi.set_inside(); } } // label the edges from polygon a with respect to polygon b. possible // labels are: shared, inside and none. inside means that the edge is inside // b, none means outside, and shared means that b has the same edge. void label_shared( Poly & a, const Poly & b ) { PolyIter a_iter( a ); while(a_iter()) { const PolyNode *b1, *b2; if ((b1 = a_iter.node()->link()) && (b2 = a_iter.nextnode()->link())) { // Seems shared -- but check // that b1 and b2 are also connected! if ((b.nextnode(b1) == b2) || (b.nextnode(b2) == b1)) { a_iter.set_shared(); continue; } /* else if (b.has_point( a_iter.edge().middle() )) a_iter.set_inside(); else a_iter.set_none(); */ //continue; } #ifdef notdef if (b1) { // So a_iter.node() shares a point with b if (b.has_point(a_iter.nextnode().point())) a_iter.set_inside(); else a_iter.set_none(); } else { // The current node is not on b if (b.has_point(a_iter.node().point())) a_iter.set_inside(); else a_iter.set_none(); } //if (b.has_point( a_iter.edge().middle() )) // a_iter.set_inside(); //else // a_iter.set_none(); #else if (b1) label_shared2(a_iter, a_iter.node()->point(), a_iter.nextnode()->point(), *b1 ); //warning("NYI %s %d\n", __FILE__, __LINE__); else if ((b2 = a_iter.nextnode()->link())) label_shared2(a_iter, a_iter.nextnode()->point(), a_iter.node()->point(), *b2 ); //warning("NYI %s %d\n", __FILE__, __LINE__); else { int in1 = b.has_point(a_iter.node()->point()), in2 = b.has_point(a_iter.nextnode()->point()); if (in1 != in2) error("This should not happen! %s %d\n", __FILE__, __LINE__ ); if (in1) a_iter.set_inside(); else a_iter.set_none(); } #endif } } // In the two make_poly functions (second one below this one) a new // polygon is added to polylist. done contains a list of edge which // already are assigned to a polygon, and thus do not belong to this // polygon (as the directed edge a->b is only part of one clockwise // oriented polygon.) The second make_poly function is a recursive function // which finishes the work initiated in the first. void make_poly( const Point &point, DirPolyIter &follow, PolyPList &polylist, NodePEdgeList &done ) { NodePEdge edge( follow ); if (done.contains(edge)) // Ignore if this edge already is done. return; // Make new polygon. start with only one point & edge Poly *new_poly = new Poly( follow.point(), &follow.poly(), follow.edgestate() ); // finish the construction of the polygon. if (make_poly( point, point, follow, done, new_poly )) { // We want only clockwise oriented polygons! if (new_poly->orientation() != ClockWise) delete new_poly; else polylist.add( new_poly ); } else // Will never happen when only one is returned... delete new_poly; } // second part of make_poly. Continue adding points to new_poly until // start_point is reached, and thus the polygon is complete. follow is used // to get the next point of the polygon. If the next point is an intersection // between the two original polygons, decide whether the other polygon // should be followed. This is done by selecting the smallest angle. int make_poly( const Point &start_point, const Point &point, DirPolyIter &follow, NodePEdgeList &done, Poly * new_poly ) { done.add( NodePEdge( follow ) ); follow.next(); // if (follow.point() == start_point) // return 1; double cur_angle = angle( point, follow.point(), follow.nextpoint() ); assert(cur_angle != 0); IterDirection dir = NONE; if (follow.link()) { double other_angle = angle( point, follow.point(), follow.linknextpoint() ); Point d1 = follow.linknextpoint() - follow.point(), d2 = follow.nextpoint() - follow.point(), d3 = follow.point() - point; double inp = d1.x() * d2.y() - d2.x() * d1.y(), inp2 = d1.x() * d3.y() - d3.x() * d1.y(); int lf = inp > 0, ld = inp2 > 0, df = (d3.x() * d2.y() - d2.x() * d3.y()) > 0, condition = (lf + ld + df) >= 2; // if (inp2 = 0) // Similar to other_angle = 0 if (point == follow.linknextpoint()) condition = 0; assert((cur_angle != other_angle) || (inp != 0) || (follow.linknextpoint() == follow.nextpoint())); assert((other_angle != 0) || (inp2 != 0) || (follow.linknextpoint() == point)); //assert((cur_angle == other_angle) || // ((((cur_angle - other_angle) > 0)) // ^ condition)); #ifdef notdef if ((other_angle != 0) && (other_angle == cur_angle ? inp > 0 : other_angle < cur_angle)) { assert(condition); #else if (condition) { #endif cur_angle = other_angle; dir = FORWARD; d2 = d1; } //else //assert(!condition); other_angle = angle( point, follow.point(), follow.linkprevpoint() ); d1 = follow.linkprevpoint() - follow.point(); // d2 = follow.nextpoint() - follow.point(); inp = d1.x() * d2.y() - d2.x() * d1.y(); inp2 = d1.x() * d3.y() - d3.x() * d1.y(); lf = inp > 0; ld = inp2 > 0; df = (d3.x() * d2.y() - d2.x() * d3.y()) > 0; condition = (lf + ld + df) >= 2; // if (inp2 = 0) if (point == follow.linkprevpoint()) condition = 0; assert((cur_angle != other_angle) || (inp != 0) || (follow.linkprevpoint() == follow.nextpoint())); assert((other_angle != 0) || (inp2 != 0) || (follow.linkprevpoint() == point)); //assert((cur_angle == other_angle) || // ((((cur_angle - other_angle) > 0)) // ^ condition)); #ifdef notdef if ((other_angle != 0) && (other_angle == cur_angle ? inp > 0 : other_angle < cur_angle)) { assert(condition); #else if (condition) { #endif // No need to update cur_angle dir = BACKWARD; } //else // assert(!condition); } if (dir != NONE) { DirPolyIter next_iter( follow, dir ); if (follow.point() == start_point) if (new_poly->nextnode(new_poly->firstnode())->point() == next_iter.nextpoint()) return 1; new_poly->add( next_iter.point(), &next_iter.poly(), next_iter.edgestate() ); return make_poly( start_point, follow.point(), next_iter, done, new_poly ); } else { // Continue using follow if (follow.point() == start_point) if (new_poly->nextnode(new_poly->firstnode())->point() == follow.nextpoint()) return 1; new_poly->add( follow.point(), &follow.poly(), follow.edgestate() ); return make_poly( start_point, follow.point(), follow, done, new_poly ); } } // a and b are two polygons with their intersection points added. // return in polylist all polygons which are 1) inside a and b or 2) // inside a and outside b or 3) outside a and inside b void iter_mesh( const Poly &a, const Poly &b, NodePEdgeList &done, PolyPList &polylist ) { ConstPolyIter iter( a ); int first = 1; while(iter()) { const PolyNode *cur = iter.node(); DirPolyIter a_iter( a, cur, b, FORWARD ); make_poly( cur->point(), a_iter, polylist, done ); if (first) { // On first point in a polygon you should go backwards first = 0; DirPolyIter a_bw_iter( a, cur, b, BACKWARD ); make_poly( cur->point(), a_bw_iter, polylist, done ); } if (cur->link()) { DirPolyIter b_fw_iter( b, cur->link(), a, FORWARD ); if (b_fw_iter.edgestate() != Shared) make_poly( cur->point(), b_fw_iter, polylist, done ); DirPolyIter b_bw_iter( b, cur->link(), a, BACKWARD); if (b_bw_iter.edgestate() != Shared) make_poly( cur->point(), b_bw_iter, polylist, done ); } } } // Determine in which class the polygons in in_list fall. This can be // inside a but outside b; than the poygon will be put in a_min_b. // Inside b but outside a will put the the polygon in b_min_a. // Inside both a and b will put the polygon in a_and_b. void assign_polys( const Poly &a, const Poly &b, const PolyPList &in_list, PolyPList &a_min_b, PolyPList &b_min_a, PolyPList &a_and_b ) { #ifdef DEBUG1 cout << "a: " << &a << endl; cout << a; cout << "b: " << &b << endl; cout << b; #endif PolyPListIter iter( in_list ); while(iter()) { Poly *poly = iter.val(); ConstPolyIter p_i( *poly ); // PosAdder has a class with the states True, False and Unkown. // An error (exception) will occur if True of False is set() // if its state is not Unknown. PosAdder a_parent, b_parent; #ifdef DEBUG1 cout << *poly; #endif while(p_i()) { #ifdef DEBUG1 cout << (*p_i.node()) << p_i.parent(a) << ',' << p_i.parent(b) << endl; #endif // The next two statements collect evidence about // the parenthood. This is done on the basis of // the edge state (shared, none, inside). a_parent.set(p_i.parent(a)); b_parent.set(p_i.parent(b)); } #ifdef notdef if (a_parent() == True && b_parent() == True) a_and_b.add(poly); else if (a_parent() == True) a_min_b.add(poly); else if (a_parent() == UnKnown && b_parent() == UnKnown) // a and b had all sides shared -- // so probably they are similar a_and_b.add(poly); else { assert( b_parent() == True ); b_min_a.add(poly); } #else if (a_parent() == TrueFalse || b_parent() == TrueFalse) // probably not a nor b -- so skip delete poly; else if (a_parent() != False && b_parent() != False) a_and_b.add(poly); else if (a_parent() == True) a_min_b.add(poly); // else if (a_parent() == UnKnown && b_parent() == UnKnown) // // a and b had all sides shared -- // // so probably they are similar // a_and_b.add(poly); else { // If the next assertion failes it could be that // the polygon is not a and not b. assert( b_parent() == True ); b_min_a.add(poly); } #endif } } void poly_min_poly( const Poly &a, const Poly &b, PolyPList &a_min_b ) { // b is inside a. // This means we have to split a, as we don't allow polygons with holes. // Split a in three parts: left of b, b and right of b // Split over line top from b, bottom from b. Point top(b.firstpoint()), bottom(b.firstpoint()); const PolyNode *top_node = b.firstnode(), *bottom_node = b.firstnode(); ConstPolyIter b_iter(b); while(b_iter()) if (b_iter.point() > top) { top = b_iter.point(); top_node = b_iter.node(); } else if (b_iter.point() < bottom) { bottom = b_iter.point(); bottom_node = b_iter.node(); } assert( top_node != bottom_node ); // Find an element of a, so that a line from that point to top does // not intersect with another edge of a, and this point is bigger as // top // Do the same for bottom, at the same time. ConstPolyIter a_iter(a); const PolyNode *a_top_node = 0, *a_bottom_node = 0; while(a_iter()) { Point cur(a_iter.point()); if (!( ((cur > top) && (a_top_node == 0)) || ((cur < bottom) && (a_bottom_node == 0)) )) continue; Edge edge(cur, ((cur > top) ? top : bottom)); ConstPolyIter a_iter2(a); int do_intersect = 0; while(a_iter2()) { if ((a_iter2.point() == cur) || (a_iter2.nextpoint() == cur)) continue; Point dummy1,dummy2; if (intersect(edge,Edge(a_iter2.point(),a_iter2.nextpoint()), dummy1, dummy2 )) { do_intersect = 1; break; } } if (do_intersect == 0) if (cur > top) a_top_node = a_iter.node(); else a_bottom_node = a_iter.node(); if ((a_top_node != 0) && (a_bottom_node != 0)) break; } assert((a_top_node != 0) && (a_bottom_node != 0)); assert(a_top_node->point() > top); assert(a_bottom_node->point() < bottom); Poly *left = new Poly(a_top_node->point()); DirPolyIter b_back(b,top_node,a,BACKWARD); add_until( left, bottom, b_back ); left->add(bottom); DirPolyIter a_forw(a,a_bottom_node,b,FORWARD); add_until( left, a_top_node->point(), a_forw); a_min_b.add( left ); Poly *right = new Poly(top); add_until( right, a_bottom_node->point(), a_forw ); right->add(a_bottom_node->point()); add_until( right, top, b_back ); a_min_b.add(right); } void add_until( Poly *polyp, const Point &point, DirPolyIter &dpi ) { do { polyp->add(dpi.point()); dpi.next(); } while(dpi.point() != point); } // clip the polygons a_org and b_org in the classes a_min_b, b_min_a and // a_and_b (see above for the meanings). void clip_poly( const Poly &a_org, const Poly &b_org, PolyPList &a_min_b, PolyPList &b_min_a, PolyPList &a_and_b ) { Poly a( a_org ), b( b_org ); // a and b can change, so protect a.make_prev(); if (a.orientation() != ClockWise) { a.revert(); a.make_prev(); } b.make_prev(); if (b.orientation() != ClockWise) { b.revert(); b.make_prev(); } int nr_intersect = intersect( a, b ); if (nr_intersect == 0) { // Two case are possible: a and b are disjunct, // or one is inside the other. if (a.has_point(b.firstpoint())) { // b is inside a a_and_b.add( new Poly(b) ); poly_min_poly( a, b, a_min_b ); } else if (b.has_point(a.firstpoint())) { // a inside b a_and_b.add( new Poly(a) ); poly_min_poly( b, a, b_min_a ); } else { // a and b are disjunct a_min_b.add( new Poly(a) ); b_min_a.add( new Poly(b) ); } return; } label_shared( a, b ); label_shared( b, a ); #ifdef DEBUG_NCLIP // static ofstream db("debugnc"); ostream &alias = db; alias << setprecision(20); db << "a:\n" << a; db << "b:\n" << b; #endif NodePEdgeList done(100); PolyPList polylist; iter_mesh( a, b, done, polylist ); iter_mesh( b, a, done, polylist ); assign_polys( a, b, polylist, a_min_b, b_min_a, a_and_b ); } clippoly-pl11/nclip.h0100644000076400010400000000460110210651410015726 0ustar KlamerAdministrators// nclip: a polygon clip library // Copyright (C) 1993 Klamer Schutte // klamer@mi.el.utwente.nl // 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. #ifndef NCLIP_H #define NCLIP_H "$Header: /cvsroot/clippoly/clippoly/nclip.h,v 1.5 2005/02/28 17:21:12 klamer Exp $" // $Log: nclip.h,v $ // Revision 1.5 2005/02/28 17:21:12 klamer // Changed to have g++ 3.2.3 run silently using g++ -ansi -pedantic -Wall -Wno-unused -Wno-reorder. // Change use of (libg++) String to ANSI C++ string. // // Revision 1.1 1993/10/27 14:43:51 klamer // Initial revision // // Revision 1.1 1993/10/27 14:43:51 klamer // Initial revision // // Revision 1.1 1992/12/07 10:46:35 klamer // Initial revision // #ifdef _GNUG__ #pragma interface #endif class Poly; // class PolyPList; class Edge; class DirPolyIter; // class PolyNodePList; class Point; // class NodePEdgeList; void clip_poly( const Poly &a, const Poly &b, PolyPList &a_min_b, PolyPList &b_min_a, PolyPList &a_and_b ); int intersect( const Edge &a, const Edge &b, Point &p1, Point &p2 ); int intersect( Poly &a, Poly &b ); void label_shared( Poly & a, const Poly & b ); void make_poly( const Point &point, DirPolyIter &follow, PolyPList &polylist, NodePEdgeList &done ); int make_poly( const Point &start_point, const Point &point, DirPolyIter &follow, NodePEdgeList &done, Poly * new_poly ); void assign_polys( const Poly &a, const Poly &b, const PolyPList &in_list, PolyPList &a_min_b, PolyPList &b_min_a, PolyPList &a_and_b ); void poly_min_poly( const Poly &a, const Poly &b, PolyPList &a_min_b ); void add_until( Poly *, const Point &, DirPolyIter & ); #endif /* NCLIP_H */ clippoly-pl11/out_file.dist0100644000076400010400000000043210210642561017150 0ustar KlamerAdministratorsa_min_b: 1 -1 0.5 0 1.5 0 PolyMagic 0.25 0.5 0 1 0.5 1 PolyMagic 1.5 1 2 1 1.75 0.5 PolyMagic b_min_a: 0.5 0 0 0 0.25 0.5 PolyMagic 0.5 1 1 2 1.5 1 PolyMagic 1.75 0.5 2 0 1.5 0 PolyMagic a_and_b: 0.5 0 0.25 0.5 0.5 1 1.5 1 1.75 0.5 1.5 0 PolyMagic clippoly-pl11/patchlevel.h0100644000076400010400000000002710214341544016756 0ustar KlamerAdministrators#define PATCHLEVEL 11 clippoly-pl11/poly.cc0100644000076400010400000002656510214324255015767 0ustar KlamerAdministratorsstatic const char rcs_id[] = "$Header: /cvsroot/clippoly/clippoly/poly.cc,v 1.7 2005/03/11 14:18:21 klamer Exp $"; // nclip: a polygon clip library // Copyright (C) 1993 University of Twente // klamer@mi.el.utwente.nl // 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. // $Log: poly.cc,v $ // Revision 1.7 2005/03/11 14:18:21 klamer // Fixed namespace clash for abs(double) happening in RedHat 7.2 linux i386. // // Revision 1.6 2005/02/28 21:12:05 klamer // Made changes such that gcc 3.4.2 compiles silent with -ansi -pedantic -Wall. // // Revision 1.5 2005/02/28 17:21:12 klamer // Changed to have g++ 3.2.3 run silently using g++ -ansi -pedantic -Wall -Wno-unused -Wno-reorder. // Change use of (libg++) String to ANSI C++ string. // // Revision 1.2 1994/01/04 12:55:37 klamer // Made copy constructor of PolyNode a dummy, and added one which also // sets parent. // Make orientation use area rather than angles. // Added Poly::revert() member. // PolyIter::add: start with check whether current point already is in // polygon. // PolyIter::add_point(): now returns number of nodes added. // ConstPolyIter::parent(const Poly &): Changed conditions. // // Revision 1.1 1993/10/27 14:44:07 klamer // Initial revision // // Revision 1.1 1992/12/07 10:46:35 klamer // Initial revision // #ifdef __GNUG__ #pragma implementation #endif #include #include #include "poly.h" #include "posadder.h" //#include "boundingbox.h" //#include "poly_use.h" static const char h_rcs_id[] = POLY_H; #ifndef M_PI #define M_PI 3.14159265358979323846 /* pi */ #endif PolyNode::PolyNode( const PolyNode &) { // Argh! use constructor which sets parent! error("This should not happen %s %d\n", __FILE__, __LINE__ ); } PolyNode::PolyNode( const PolyNode © , const Poly *parent ) : p(copy.p), prev(0), _link(0), _parent_poly( parent), _edgestate( Unknown ) { if (copy.next) next = new PolyNode( *copy.next, parent ); else next = 0; } PolyNode::~PolyNode() { if (next) delete next; } const Poly * PolyNode::parent_poly() const { assert(_parent_poly != 0); return _parent_poly; } NodePEdge::NodePEdge( const DirPolyIter &dpi ) { const PolyNode *node = dpi.node(), *link = node->link(); if (link) if (link < node) n1 = link; else n1 = node; else n1 = node; node = dpi.nextnode(); link = node->link(); if (link) if (link < node) n2 = link; else n2 = node; else n2 = node; } void Poly::make_prev() const { PolyIter iter(*(Poly *)this); PolyNode *last = 0; while(iter()) { iter.node()->prev = last; last = iter.node(); } ((Poly *)this)->prev = last; } const PolyNode * Poly::nextnode(const PolyNode *node) const { if (node->next) return node->next; return list; } const PolyNode * Poly::prevnode(const PolyNode *node) const { assert(prev); if (node->prev) return node->prev; return prev; } void Poly::add( const Point &p, const Poly *parent, EdgeState edgestate ) { if (!prev) make_prev(); PolyNode *new_node = new PolyNode( p, parent, edgestate ); new_node->prev = prev; new_node->next = 0; assert( prev->next == 0 ); prev->next = new_node; prev = new_node; } Orientation Poly::orientation() const { if (!prev) make_prev(); ConstPolyIter iter(*this); double tot_angle = 0; double area = 0; Point first; int first_flag = 1; while(iter()) { tot_angle += angle( iter.prevpoint(), iter.point(), iter.nextpoint() ) - M_PI; if (first_flag) { first_flag = 0; first = iter.point(); continue; } // Point &p1 = iter.point(), &p2 = iter.nextpoint(); // NOTE: last step in iter also is not needed! Point p1 = iter.point() - first, p2 = iter.nextpoint() - first; area += p1.x() * p2.y() - p2.x() * p1.y(); } area /= 2.0; assert(area != 0); assert((area * tot_angle > 0) || (fabs(fabs(tot_angle) - M_PI * 2.0) > 0.0001)); #ifndef notdef if (area < 0) return ClockWise; else return CounterClockWise; #else if (tot_angle < 0) { assert(tot_angle < -M_PI * 1.9999); assert(tot_angle > -M_PI * 2.0001); return ClockWise; } else { assert(tot_angle > M_PI * 1.9999); assert(tot_angle < M_PI * 2.0001); return CounterClockWise; } #endif } double Poly::area() const { if (!prev) make_prev(); ConstPolyIter iter(*this); double ret = 0; Point first; int first_flag = 1; while(iter()) { if (first_flag) { first_flag = 0; first = iter.point(); continue; } Point p1 = iter.point() - first, p2 = iter.nextpoint() - first; ret += p1.x() * p2.y() - p2.x() * p1.y(); } return ret / 2.0; } void Poly::revert() { if (!prev) make_prev(); PolyNode *next; for(PolyNode *cur = list; cur != 0; cur = next) { next = cur->next; cur->next = cur->prev; cur->prev = next; } PolyNode *tmp = prev; prev = list; list = tmp; // warning("NYI %s %d\n", __FILE__, __LINE__); } int intersect_right( const Edge &edge, const Point &point ) { if ((edge.p1().y() >= point.y()) && (edge.p2().y() >= point.y())) return 0; if ((edge.p1().y() < point.y()) && (edge.p2().y() < point.y())) return 0; if (edge.p1().y() == edge.p2().y()) return 0; // Tricky! This could give errors! double x = (point.y() - edge.p1().y()) * (edge.p2().x() - edge.p1().x()) / (edge.p2().y() - edge.p1().y()) + edge.p1().x(); if (x > point.x()) // Tricky! Is >= better? return 1; return 0; } // is point inside *this? int Poly::has_point( const Point &point ) const { PolyIter iter( *(Poly *)((void *)this) ); int cnt = 0; while(iter()) cnt += intersect_right( iter.edge(), point ); return cnt % 2; } double Poly::xmin() const { ConstPolyIter iter(*this); iter(); double res = iter.point().x(); while(iter()) { double c = iter.point().x(); if (c < res) res = c; } return res; } double Poly::xmax() const { ConstPolyIter iter(*this); iter(); double res = iter.point().x(); while(iter()) { double c = iter.point().x(); if (c > res) res = c; } return res; } double Poly::ymin() const { ConstPolyIter iter(*this); iter(); double res = iter.point().y(); while(iter()) { double c = iter.point().y(); if (c < res) res = c; } return res; } double Poly::ymax() const { ConstPolyIter iter(*this); iter(); double res = iter.point().y(); while(iter()) { double c = iter.point().y(); if (c > res) res = c; } return res; } PolyIter::PolyIter( Poly &_poly ) : poly(_poly), app_next(poly.list) { } int PolyIter::operator() () { cur = app_next; if (cur != 0) { app_next = cur->next; return 1; } else return 0; } PolyNode * PolyIter::add( const Point &point, int &new_point ) { PolyIter chk(poly); while(chk()) if (point == chk.node()->point()) return chk.node(); if (point == cur->p) warning("This should not happen! %s, %d\n", __FILE__, __LINE__ ); // return cur; double d = len( cur->p - point ); assert( d <= len( cur->p - AppNext()->p ) ); PolyNode *last = cur, *p = next( cur ); for( ;d > len( cur->p - p->p ); last = p, p = next( p )) ; // Go to next node, as next node is on same side as current node if (p->p == point) warning("This should not happen! %s, %d\n", __FILE__, __LINE__ ); // return p; p = new PolyNode( point, &poly, last->next ); new_point++; last->next = p; if (p->next) p->next->prev = p; else if (poly.prev) { assert(poly.prev == last); poly.prev = p; } p->prev = last; return p; } int PolyIter::add_point( PolyIter &a, PolyIter &b, const Point &p ) { int res = 0; PolyNode *node_a = a.add( p, res ); PolyNode *node_b = b.add( p, res ); assert((node_a->_link == 0) || (node_a->_link == node_b)); node_a->_link = node_b; assert((node_b->_link == 0) || (node_b->_link == node_a)); node_b->_link = node_a; return res; } ConstPolyIter::ConstPolyIter( const Poly &_poly ) : polyiter( *(Poly *)(void *)&_poly ) { } LogicStates ConstPolyIter::parent(const Poly &poly) { switch(node()->edgestate()) {case None: if (&poly == node()->parent_poly()) return True; else { if (node()->link() != 0) return UnKnown; // Prob. True else return False; } case Shared: return UnKnown; case Inside: if (&poly == node()->parent_poly()) return UnKnown; else { if (node()->link() != 0) return UnKnown; else return True; } case Unknown: default: fatal("This should not happen %s %d\n", __FILE__, __LINE__); } return UnKnown; } DirPolyIter::DirPolyIter( const Poly &poly, const PolyNode *node, const Poly &link, IterDirection dir ) : _poly(poly), _linkpoly(link), _dir(dir), _node(node) { if (! _poly.prev) _poly.make_prev(); if (!_linkpoly.prev) _linkpoly.make_prev(); } DirPolyIter::DirPolyIter( const DirPolyIter &dpi, IterDirection dir ) : _poly(dpi.linkpoly()), _linkpoly( dpi._poly ), _dir(dir), _node( dpi.node()->link() ) { if (! _poly.prev) _poly.make_prev(); if (!_linkpoly.prev) _linkpoly.make_prev(); } const PolyNode * DirPolyIter::nextnode() const { switch(dir()) {case FORWARD: return _poly.nextnode(node()); case BACKWARD: return _poly.prevnode(node()); default: assert(0); } return 0; // Should not be reached } const PolyNode * DirPolyIter::prevnode() const { switch(dir()) {case FORWARD: return _poly.prevnode(node()); case BACKWARD: return _poly.nextnode(node()); default: assert(0); } return 0; // Should not be reached } EdgeState DirPolyIter::edgestate() const { if (dir() == FORWARD) return node()->edgestate(); return nextnode()->edgestate(); } #ifdef notdef int Poly::intersect_table( int hor, Vec &intersection_table, double h ) { ConstPolyIter iter(*this); iter(); BoundingBox bbox(iter.point()); while(iter()) bbox.add(iter.point()); Point left( hor ? bbox.xmin()-1 : 0, hor ? 0 : bbox.ymin()-1 ), right( hor ? bbox.xmax()+1 : 0, hor ? 0 : bbox.ymax()+1 ); if (hor) left.y() = right.y() = h; else left.x() = right.x() = h; int nr_inters; if (hor) create_intersection_table(*this, left, right, nr_inters, intersection_table, x, y ); else create_intersection_table(*this, left, right, nr_inters, intersection_table, y, x ); return nr_inters; } #endif clippoly-pl11/poly.h0100644000076400010400000002076110210704445015620 0ustar KlamerAdministrators// nclip: a polygon clip library // Copyright (C) 1993 Klamer Schutte // klamer@mi.el.utwente.nl // 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. #ifndef POLY_H #define POLY_H "$Header: /cvsroot/clippoly/clippoly/poly.h,v 1.6 2005/02/28 21:12:05 klamer Exp $" // $Log: poly.h,v $ // Revision 1.6 2005/02/28 21:12:05 klamer // Made changes such that gcc 3.4.2 compiles silent with -ansi -pedantic -Wall. // // Revision 1.5 2005/02/28 17:21:12 klamer // Changed to have g++ 3.2.3 run silently using g++ -ansi -pedantic -Wall -Wno-unused -Wno-reorder. // Change use of (libg++) String to ANSI C++ string. // // Revision 1.2 1994/01/04 12:55:37 klamer // Changed PolyNode constructors. // Added Poly::revert() member. // // Revision 1.1 1993/10/27 14:43:52 klamer // Initial revision // // Revision 1.2 1992/12/07 13:32:35 klamer // Deleted comments from Poly::Poly(const Point &) in-class defined // constructor. // // Revision 1.1 1992/12/07 10:46:35 klamer // Initial revision // #ifdef __GNUG__ #pragma interface #endif #include #ifndef PRIMITIVES_H #include #endif #ifndef SET_H #include #endif #ifndef POSADDER_H #include #endif int intersect_right( const Edge &edge, const Point &point ); enum EdgeState { Unknown, None, Shared, Inside }; // enum LogicStates; class Vec; class PolyNode { friend class Poly; friend class PolyIter; friend class ConstPolyIter; friend std::ostream &operator<<(std::ostream &, const PolyNode &); public: PolyNode *link() { return _link; } const PolyNode *link() const { return _link; } const Point &point() const { return p; } EdgeState edgestate() const { return _edgestate; } const PolyNode &prevnode() const; // { return *_parent_poly->prevnode(this); } const PolyNode &nextnode() const; // { return *_parent_poly->nextnode(this); } private: PolyNode( const PolyNode © ); // Don't use PolyNode( const PolyNode ©, const Poly *parent ); PolyNode( const Point &point, const Poly *parent, PolyNode *tail = 0) : p( point ), next( tail ), prev(0), _link( 0 ), _parent_poly( parent ), _edgestate( ::Unknown ) { } PolyNode( const Point &point, const Poly *parent, EdgeState es ) : p( point ), next( 0 ), prev(0), _link( 0 ), _parent_poly( parent ), _edgestate( es ) { } ~PolyNode(); void operator=( PolyNode node ); // Don't use it! Point p; PolyNode *next, *prev; PolyNode *_link; const Poly *_parent_poly; const Poly *parent_poly() const; EdgeState _edgestate; }; class DirPolyIter; class NodePEdge { const PolyNode *n1, *n2; friend class Set; friend class RSet; NodePEdge() { } public: NodePEdge( const PolyNode *n_1, const PolyNode *n_2 ) : n1( n_1 ), n2( n_2 ) { } NodePEdge( const DirPolyIter &dpi ); int operator==( const NodePEdge &cmp ) const { return (n1 == cmp.n1) && (n2 == cmp.n2); } }; typedef Set PolyNodePList; typedef SetIter PolyNodePListIter; typedef RSet NodePEdgeList; typedef RSetIter NodePEdgeListIter; enum Orientation { ClockWise, CounterClockWise }; class Poly { private: friend class PolyIter; friend class DirPolyIter; PolyNode *list, *prev; Poly &operator=( const Poly © ); // Don't use it! public: Poly( const Poly © ) : list( new PolyNode( *copy.list, this ) ), prev( 0 ) { } // Poly( const PolyNode *copy, const Poly *parent ) // : list( new PolyNode( copy, parent ) ), prev(0) // { } Poly( const Point &p, const Poly *parent, EdgeState es ) : list( new PolyNode( p, parent, es ) ), prev(0) { } Poly( const Point &p ) // : list( new PolyNode( &PolyNode(p), 0 ) ), prev(0) : list( new PolyNode( p, this ) ), prev(0) { } ~Poly() { delete list; } void add( const Point &p, const Poly *parent, EdgeState es ); void add( const Point &p ) { add( p, 0, ::Unknown ); } // 0 or this ??? int has_point( const Point &point ) const; // point inside *this? const PolyNode *nextnode( const PolyNode *node ) const; Orientation orientation() const; double area() const; void revert(); void make_prev() const; const PolyNode *prevnode( const PolyNode *node ) const; const Point &firstpoint() const { return list->point(); } const PolyNode *firstnode() const { return list; } double xmin() const; double xmax() const; double ymin() const; double ymax() const; int intersect_table( int hor, Vec &it, double h ); }; inline const PolyNode & PolyNode::prevnode() const { return *_parent_poly->prevnode(this); } inline const PolyNode & PolyNode::nextnode() const { return *_parent_poly->nextnode(this); } typedef Set PolyPList; typedef SetIter PolyPListIter; class PolyIter { Poly &poly; PolyNode *cur, *app_next; PolyNode *AppNext() { return (app_next != 0) ? app_next : poly.list; } const PolyNode *AppNext() const { return (app_next != 0) ? app_next : poly.list; } PolyNode *next(PolyNode *node) { return (node->next != 0) ? node->next : poly.list; } PolyNode *add( const Point &point, int &new_point ); PolyNode *add( const Point &point ) { int dummy; return add(point, dummy); } public: PolyIter( Poly &poly ); void reset() { app_next = poly.list; } int operator() (); PolyNode *node() { return cur; } const PolyNode *node() const { return cur; } const PolyNode *nextnode() const { return AppNext(); } const PolyNode *prevnode() const { return poly.prevnode(node()); } Edge edge() const { return Edge( cur->p, AppNext()->p ); } static int add_point( PolyIter &a, PolyIter &b, const Point &p ); void set_shared() { cur->_edgestate = ::Shared; } void set_inside() { cur->_edgestate = ::Inside; } void set_none() { cur->_edgestate = ::None; } }; enum IterDirection { FORWARD, BACKWARD, NONE }; class DirPolyIter { const Poly &_poly, &_linkpoly; const IterDirection _dir; const PolyNode *_node; IterDirection dir() const { return _dir; } const Poly &linkpoly() const { return _linkpoly; } const PolyNode *prevnode() const; public: DirPolyIter( const Poly &poly, const PolyNode *node, const Poly &link, IterDirection dir ); // Continue on link DirPolyIter( const DirPolyIter &dpi, IterDirection dir ); void next() { _node = nextnode(); } const PolyNode *node() const { return _node; } const PolyNode *nextnode() const; const PolyNode *link() const { return node()->link(); } const Point &point() const { return node()->point(); } const Point &nextpoint() const { return nextnode()->point(); } const Point &linknextpoint() const { return linkpoly().nextnode(link())->point(); } const Point &linkprevpoint() const { return linkpoly().prevnode(link())->point(); } const Poly &poly() const { return _poly; } EdgeState edgestate() const; }; class ConstPolyIter { PolyIter polyiter; const PolyNode *prevnode() const { return polyiter.prevnode(); } const PolyNode *nextnode() const { return polyiter.nextnode(); } public: ConstPolyIter( const Poly &poly ); int operator() () { return polyiter(); } const PolyNode *node() const { return polyiter.node(); } LogicStates parent(const Poly &poly); const Point &point() const { return node()->point(); } const Point &prevpoint() const { return prevnode()->point(); } const Point &nextpoint() const { return nextnode()->point(); } Edge edge() const { return polyiter.edge(); } }; #endif /* POLY_H */ clippoly-pl11/poly_io.cc0100644000076400010400000000744510210651410016442 0ustar KlamerAdministratorsstatic const char rcs_id[] = "$Header: /cvsroot/clippoly/clippoly/poly_io.cc,v 1.5 2005/02/28 17:21:12 klamer Exp $"; // nclip: a polygon clip library // Copyright (C) 1993 University of Twente // klamer@mi.el.utwente.nl // 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. // $Log: poly_io.cc,v $ // Revision 1.5 2005/02/28 17:21:12 klamer // Changed to have g++ 3.2.3 run silently using g++ -ansi -pedantic -Wall -Wno-unused -Wno-reorder. // Change use of (libg++) String to ANSI C++ string. // // Revision 1.1 1992/12/07 10:46:35 klamer // Initial revision // #ifdef __GNUG__ #pragma implementation #endif #include #include #include #include #include #include #include //#include "poly3node.h" //#include "poly3.h" //#include "poly2.h" #include "poly_io.h" static const char h_rcs_id[] = POLY_IO_H; using namespace std; Poly * read_poly( istream &in ) { Point p; in >> p; Poly *new_poly = new Poly( p ); while( in >> p ) new_poly->add( p ); string magic; in.clear(); in >> magic; if (magic != POLY_MAGIC) fatal("read_poly: wrong magic (%s)\n", magic.c_str()); return new_poly; } istream & operator>>(istream &in, Point &p) { double x, y; in >> x >> y; if (!in) // Failure? return in; p = Point(x,y); return in; } std::ostream & operator<<(std::ostream &out, const PolyPList &pl) { PolyPListIter iter(pl); while(iter()) out << *iter.val(); return out; } std::ostream & operator<<(std::ostream &out, const Poly &poly) { ConstPolyIter iter(poly); while(iter()) out << (iter.point()); out << POLY_MAGIC << endl; return out; } std::ostream & operator<<(std::ostream &out, const PolyNode &poly) { out << poly.p << "next: " << poly.next << " prev: " << poly.prev << " link: " << poly._link << " state: " << poly.edgestate() << " parent: " << (void *) poly._parent_poly << endl; return out; } std::ostream & operator<<(std::ostream &out, const Point &p) { out << p.x() << '\t' << p.y() << endl; return out; } std::ostream & operator<<(std::ostream &out, enum LogicStates state) { switch(state) {case UnKnown: out << "UnKnown"; break; case True: out << "True"; break; case False: out << "False"; break; case TrueFalse: out << "TrueFalse"; break; default: error("<<: Unknown value in LogicStates: %d\n", (int)state); out << (int)state; } return out; } std::ostream & operator<<(std::ostream &out, enum EdgeState state) { switch(state) {case Unknown: out << "Unknown"; break; case None: out << "None"; break; case Shared: out << "Shared"; break; case Inside: out << "Inside"; break; default: error("<<: Unknown value in LogicStates: %d\n", (int)state); out << (int)state; } return out; } std::ostream & operator<<(std::ostream&out, const hvec3_t &v) { out << v_x(v) << ", " << v_y(v) << ", " << v_z(v) << ", " << v_w(v); return out; } clippoly-pl11/poly_io.h0100644000076400010400000000376010210651410016300 0ustar KlamerAdministrators#ifndef POLY_IO_H #define POLY_IO_H "$Header: /cvsroot/clippoly/clippoly/poly_io.h,v 1.5 2005/02/28 17:21:12 klamer Exp $" // nclip: a polygon clip library // Copyright (C) 1993 Klamer Schutte // klamer@mi.el.utwente.nl // 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. // $Log: poly_io.h,v $ // Revision 1.5 2005/02/28 17:21:12 klamer // Changed to have g++ 3.2.3 run silently using g++ -ansi -pedantic -Wall -Wno-unused -Wno-reorder. // Change use of (libg++) String to ANSI C++ string. // // Revision 1.1 1992/12/07 10:46:35 klamer // Initial revision // #ifdef __GNUG__ #pragma interface #endif #include #include #define POLY_MAGIC "PolyMagic" class Poly; class Point; class PolyNode; union hvec3_t; Poly *read_poly( std::istream & ); std::istream &operator>>(std::istream &, Point &); std::ostream &operator<<(std::ostream &, const Poly &); std::ostream &operator<<(std::ostream &, const PolyPList &); std::ostream &operator<<(std::ostream &, const PolyNode &); std::ostream &operator<<(std::ostream &, const Point &); std::ostream &operator<<(std::ostream &, enum EdgeState); std::ostream &operator<<(std::ostream &, enum LogicStates); std::ostream &operator<<(std::ostream &, const hvec3_t &); #endif /* POLY_IO_H */ clippoly-pl11/posadder.cc0100644000076400010400000000406610210651410016565 0ustar KlamerAdministratorsstatic const char rcs_id[] = "$Header: /cvsroot/clippoly/clippoly/posadder.cc,v 1.5 2005/02/28 17:21:12 klamer Exp $"; // nclip: a polygon clip library // Copyright (C) 1993 University of Twente // klamer@mi.el.utwente.nl // 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. // $Log: posadder.cc,v $ // Revision 1.5 2005/02/28 17:21:12 klamer // Changed to have g++ 3.2.3 run silently using g++ -ansi -pedantic -Wall -Wno-unused -Wno-reorder. // Change use of (libg++) String to ANSI C++ string. // // Revision 1.2 1994/01/04 12:55:37 klamer // *** empty log message *** // // Revision 1.1 1993/10/27 14:44:10 klamer // Initial revision // // Revision 1.1 1992/12/07 10:46:35 klamer // Initial revision // #ifdef __GNUG__ #pragma implementation #endif #include #include "posadder.h" static const char h_rcs_id[] = POSADDER_H; void PosAdder::set(LogicStates boolean) { if (val == TrueFalse) return; switch(boolean) {case UnKnown: break; case TrueFalse: val = TrueFalse; break; case True: if (val == False) //error("Conflict in PosAdder::set (False, True)\n"); val = TrueFalse; else val = True; break; case False: if (val == True) //error("Conflict in PosAdder::set (True, False)\n"); val = TrueFalse; else val = False; break; } } clippoly-pl11/posadder.h0100644000076400010400000000336010210651410016423 0ustar KlamerAdministrators#ifndef POSADDER_H #define POSADDER_H "$Header: /cvsroot/clippoly/clippoly/posadder.h,v 1.5 2005/02/28 17:21:12 klamer Exp $" // nclip: a polygon clip library // Copyright (C) 1993 Klamer Schutte // klamer@mi.el.utwente.nl // 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. // $Log: posadder.h,v $ // Revision 1.5 2005/02/28 17:21:12 klamer // Changed to have g++ 3.2.3 run silently using g++ -ansi -pedantic -Wall -Wno-unused -Wno-reorder. // Change use of (libg++) String to ANSI C++ string. // // Revision 1.1 1993/10/27 14:43:55 klamer // Initial revision // // Revision 1.1 1993/10/27 14:43:55 klamer // Initial revision // // Revision 1.1 1992/12/07 10:46:35 klamer // Initial revision // #ifdef __GNUG__ #pragma interface #endif enum LogicStates { UnKnown, True, False, TrueFalse }; class PosAdder { LogicStates val; public: PosAdder() : val( UnKnown ) { } void set( LogicStates boolean ); LogicStates operator() () const { return val; } }; #endif /* POSADDER_H */ clippoly-pl11/primitives.cc0100644000076400010400000000453510210651410017160 0ustar KlamerAdministratorsstatic const char rcs_id[] = "$Header: /cvsroot/clippoly/clippoly/primitives.cc,v 1.5 2005/02/28 17:21:12 klamer Exp $"; // nclip: a polygon clip library // Copyright (C) 1993 University of Twente // klamer@mi.el.utwente.nl // 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. // $Log: primitives.cc,v $ // Revision 1.5 2005/02/28 17:21:12 klamer // Changed to have g++ 3.2.3 run silently using g++ -ansi -pedantic -Wall -Wno-unused -Wno-reorder. // Change use of (libg++) String to ANSI C++ string. // // Revision 1.2 1994/01/04 12:55:37 klamer // Loosened assertion in angle() from angle < 2 pi to angle <= 2 pi. // // Revision 1.1 1993/10/27 14:44:13 klamer // Initial revision // // Revision 1.1 1992/12/07 10:46:35 klamer // Initial revision // #ifdef __GNUG__ #pragma implementation #endif #include #include #ifndef M_PI #define M_PI 3.14159265358979323846 /* pi */ #endif #include #include "primitives.h" static const char h_rcs_id[] = PRIMITIVES_H; const int PointList::def_len = 16; PointList::PointList( int nr ) : len( nr ), cur( 0 ), points( new Point[ nr ] ) { assert( nr > 0 ); } PointList::~PointList() { delete [] points; } void PointList::add( const Point &add ) { if (cur + 1 >= len) fatal("PointList::add: Array too short (%d)\n", len); points[cur] = add; } double angle(const Point &p1, const Point &p2, const Point &p3) { Point d1 = p1 - p2, d2 = p3 - p2; double res = atan( d2 ) - atan( d1 ); if (res < 0) res += M_PI * 2; assert( res >= 0 ); assert( res <= M_PI * 2 ); return res; } clippoly-pl11/primitives.h0100644000076400010400000001121410210651410017012 0ustar KlamerAdministrators#ifndef PRIMITIVES_H #define PRIMITIVES_H "$Header: /cvsroot/clippoly/clippoly/primitives.h,v 1.5 2005/02/28 17:21:12 klamer Exp $" // nclip: a polygon clip library // Copyright (C) 1993 Klamer Schutte // klamer@mi.el.utwente.nl // 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. // $Log: primitives.h,v $ // Revision 1.5 2005/02/28 17:21:12 klamer // Changed to have g++ 3.2.3 run silently using g++ -ansi -pedantic -Wall -Wno-unused -Wno-reorder. // Change use of (libg++) String to ANSI C++ string. // // Revision 1.1 1993/10/27 14:43:55 klamer // Initial revision // // Revision 1.1 1993/10/27 14:43:55 klamer // Initial revision // // Revision 1.1 1992/12/07 10:46:35 klamer // Initial revision // #ifdef __GNUG__ #pragma interface #endif #include #include #ifndef GRAPHMAT_INCLUDE #include #endif class Point { double _x, _y; public: Point() { } Point( double x, double y ) : _x(x), _y(y) { } Point( const hvec2_t &h ) : _x(v_x(h)), _y(v_y(h)) { } double x() const { return _x; } double &x() { return _x; } double y() const { return _y; } double &y() { return _y; } // operator hvec2_t(); // Does crash g++ 2.2.1 when used :-( hvec2_t hvec() const // { hvec2_t res; v_fill2( x(), y(), 1.0, &res ); return res; } { hvec2_t res; v_x(res) = x(); v_y(res) = y(); v_w(res) = 1; return res; } const Point &operator=( const hvec2_t © ) { _x = v_x(copy); _y = v_y( copy); return *this; } const Point &operator=( const Point © ) { _x = copy.x(); _y = copy.y(); return *this; } }; inline Point operator+( const Point &p1, const Point &p2 ) { return Point( p1.x() + p2.x(), p1.y() + p2.y() ); } inline Point operator-( const Point &p1, const Point &p2 ) { return Point( p1.x() - p2.x(), p1.y() - p2.y() ); } inline double len( const Point p ) { return sqrt( p.x() * p.x() + p.y() * p.y() ); } inline Point operator/( const Point &p, double div ) { return Point( p.x() / div, p.y() / div ); } inline int operator==( const Point &p1, const Point &p2 ) { return (p1.x() == p2.x()) && (p1.y() == p2.y()); } inline int operator!=( const Point &p1, const Point &p2 ) { return (p1.x() != p2.x()) || (p1.y() != p2.y()); } inline int operator<( const Point &p1, const Point &p2 ) { return (p1.y() < p2.y()) || ((p1.y() == p2.y()) && (p1.x() < p2.x())); } inline int operator>( const Point &p1, const Point &p2 ) { return (p1.y() > p2.y()) || ((p1.y() == p2.y()) && (p1.x() > p2.x())); } double angle( const Point &p1, const Point &p2, const Point &p3 ); inline double atan( const Point &p ) { assert( (p.x() != 0) || (p.y() != 0) ); return atan2( p.y(), p.x() ); } inline Point point(const hvec3_t &p) { hvec3_t pn; v_homo3( &p, &pn ); return Point( v_x(pn), v_y(pn) ); } class PointList { friend class PointListIter; int len, cur; Point *points; static const int def_len; // = 16; // Make copy constructor and assignment unusable PointList( PointList © ); PointList &operator=( const PointList © ); public: PointList( int nr = def_len ); ~PointList(); void add( const Point &add ); }; class PointListIter { const PointList &pl; int cnt; public: PointListIter( const PointList &list ) : pl( list ), cnt( -1 ) { } int operator() () { if (++cnt < pl.cur) return 1; else return 0; } const Point &point() const { return pl.points[cnt]; } }; class Edge { Point point1, point2; // int shared; public: Edge( const Point &p1, const Point &p2 ) //, int share = -1 ) : point1( p1 ), point2( p2 ) //, shared( share ) { } Point middle() const { return (point1 + point2) / 2.0; } // void set_shared( int val ) // { shared = val; } const Point &p1() const { return point1; } const Point &p2() const { return point2; } }; #endif /* PRIMITIVES_H */ clippoly-pl11/README0100644000076400010400000000515010210642561015337 0ustar KlamerAdministratorsIf you don't have g++, but a cfront based compiler like Sun C++ 3.0, then you should compile the files from the CC subdirectory to this directory. The String.{cc,h} files are not a complete implementation of a String class; they only provide what is used in the file poly_io.cc. For a good String class you can try the libg++ library (which I assume is installed if you have g++.) Also, rename Makefile.CC to Makefile. If you don't have g++ nor a cfront based compiler then you are on your own. Compilers which are know to work: g++ 2.4 -> 2.6.0 g++ 2.6.1 has a bug in constructor sysntax which break this code. Sun C++ 2.1, 3, 4 Irix CC on Irix 5.2 A bug which reveals itself on Ultrix mips machines is known. The fix will be incorporated in this code some day. Before compiling, skim through the Makefile. Three differences can be made: - Changing the C compiler. Standard is cc. gcc -traditional can be used on systems with proper header files (this excludes SunOS 4.1.X). Ansi C compilers give warnings on the C files, as they are in K&R C, and the header files are ANSI C / C++. - Adding the notion of a .cc file as a C++ source file. Some make's (like SGI's) do not standard recognize a .cc file as C++ - Patching libg++. Early versions of libg++ 2.5 (notably, 2.5.1 and 2.5.2) suffered a bug which caused the test porgram to hang. If you add sbscan.cc to the program (replacing the one in libg++) this bug is fixed. Better off course is to upgrade to a more recent libg++! Note that libg++ 2.4.X does not have this bug, and can be used without (known) problems. In this directory you can find the test program for the nclip library. In this directory is: lgpl.texinfo: texinfo style version of the copyright statement. test.cc: The wrapper in which we can test. Reads two clockwise oriented polygons from stdin, and clips those. Results comes on stdout. Examples format for input can be found in in_file. nclip.cc: The actual clip routine. Only file in the nclip library which is decent documented. nclip.h nclip.cc poly.cc poly.h poly_io.cc poly_io.h posadder.cc posadder.h primitives.cc primitives.h set.h: The rest of the nclip library. Not of real interest, but needed to get nclip running. sbscan.cc: Part of libg++. It is a patched version of a file from libg++ 2.5.1 err.* graph*: files, part of our standard , in-house library. Not likely to have big errors. They even come with documentation! (*.3, nroff (== UNIX man) format) They should be compiled with a K&R C compiler (like gcc -traditional.) CLASSES: Some documentation about the classes used. clippoly-pl11/set.h0100644000076400010400000001116010210651410015412 0ustar KlamerAdministrators#ifndef SET_H #define SET_H "$Header: /cvsroot/clippoly/clippoly/set.h,v 1.5 2005/02/28 17:21:12 klamer Exp $" // $Log: set.h,v $ // Revision 1.5 2005/02/28 17:21:12 klamer // Changed to have g++ 3.2.3 run silently using g++ -ansi -pedantic -Wall -Wno-unused -Wno-reorder. // Change use of (libg++) String to ANSI C++ string. // // Revision 1.3 1994/11/09 08:08:23 schutte // constness fixes. // Code cleanup. // // Revision 1.2 1994/01/04 12:55:37 klamer // Made default size 64 instead of 16. // Renamed len to _len. // // Revision 1.1 1993/10/27 14:43:58 klamer // Initial revision // // Revision 1.3 1993/10/27 14:28:05 klamer // Version as used in itool. // // Revision 1.2 1993/01/18 14:56:18 klamer // Spie version. // // Revision 1.1 1992/12/07 10:46:35 klamer // Initial revision // #ifdef __GNUG__ #ifndef GEN_TEMPLATES #pragma interface #endif #endif #ifndef assert #include #endif #ifdef sgi #ifdef __GNUG__ #define INLINE inline #else #define INLINE // Nothing // The CC with Irix 5.2 is too stupid for these inline's #endif #else #define INLINE inline #endif template class SetIter; template class RSetIter; template class Set { friend class SetIter; T *data; int _len, used; T operator[](int cnt) const { return data[cnt]; } void operator=(const Set &); // Don't use it! void _resize(); public: Set( int size = 64 ) : data( new T [size] ), _len(size), used(0) { } ~Set() { delete [] data; } int contains( T elem ) const { return seek( elem ) >= 0; } int seek( T elem ) const { SetIter iter(*this); while(iter()) if (iter.val() == elem) return iter.cnt(); return -1; } void add( T elem ) { if (!contains(elem)) { if (used + 1 >= _len) _resize(); data[used] = elem; used++; } } void del( T elem ) { int i = seek(elem); if (i >= 0) { data[i] = data[used-1]; used--; } } int empty() const { return used == 0; } T first() { assert(used > 0); return data[0]; } int length() const { return used; } }; template void Set::_resize() { T *new_data = new T [_len * 2]; for(int i = 0; i < _len; i++) new_data[i] = data[i]; delete [] data; data = new_data; _len *= 2; } template class SetIter { int _cnt; const Set &_set; const Set &set() { return _set; } public: SetIter( const Set &set ) : _cnt(-1), _set(set) { } INLINE int operator() (); #ifdef notdef { if (cnt() >= (_set.used-1)) return 0; _cnt++; return 1; } #endif inline T val() const; #ifdef notdef { return _set[_cnt]; } #endif int cnt() const { return _cnt; } }; template INLINE int SetIter::operator() () { if (cnt() >= (_set.used-1)) return 0; _cnt++; return 1; } template inline T SetIter::val() const { return _set[_cnt]; } template class RSet { friend class RSetIter; T *data; int _len, used; T &operator[](int cnt) { return data[cnt]; } void operator=(const RSet &); // Don't use it! void _resize(); public: RSet( int size = 64 ) : data( new T [size] ), _len(size), used(0) { } ~RSet() { delete [] data; } int contains( const T &elem ) const { return seek( elem ) >= 0; } int seek( const T &elem ) const { for(int i = 0; i < used; i++) if (data[i] == elem) return i; return -1; } void add( const T &elem ) { if (!contains(elem)) { if (used +1 >= _len) _resize(); data[used] = elem; used++; } } int length() const { return used; } void clear() { used = 0; } }; template void RSet::_resize() { T *new_data = new T [_len * 2]; for(int i = 0; i < _len; i++) new_data[i] = data[i]; delete [] data; data = new_data; _len *= 2; } template class RSetIter { int _cnt; const RSet &_set; const RSet &set() { return _set; } public: RSetIter( const RSet &set ) : _cnt(-1), _set(set) { } INLINE int operator() (); #ifdef notdef { if (_cnt >= (_set.used-1)) return 0; _cnt++; return 1; } #endif const T &val() const { return _set.data[_cnt]; } int cnt() const { return _cnt; } }; template INLINE int RSetIter::operator() () { if (_cnt >= (_set.used-1)) return 0; _cnt++; return 1; } #endif /* SET_H */ clippoly-pl11/t10100644000076400010400000000063610210647233014733 0ustar KlamerAdministrators -6 -12 -5 -12 -5 12 -6 12 PolyMagic -6.040000076293946e+00 -1.124363494873047e+01 -6.000000114440919e+00 -1.131199813842774e+01 -4.896273727416993e+00 -1.292799926757813e+01 -4.831999893188478e+00 1.292435287475586e+01 -5.938339347839356e+00 1.131199954986572e+01 -6.040000076293946e+00 1.113841079711914e+01 PolyMagic clippoly-pl11/t1.out0100644000076400010400000000060710210647233015537 0ustar KlamerAdministratorsa_min_b: -6 12 -5.46626 12 -5.93834 11.312 -6 11.2067 PolyMagic -5.5301 -12 -6 -12 -6 -11.312 PolyMagic b_min_a: -5.46626 12 -4.832 12.9244 -4.89627 -12.928 -5.5301 -12 -5 -12 -5 12 PolyMagic -6 -11.312 -6 -11.312 -6.04 -11.2436 -6.04 11.1384 -6 11.2067 PolyMagic a_and_b: -5.46626 12 -5 12 -5 -12 -5.5301 -12 -6 -11.312 -6 11.2067 -5.93834 11.312 PolyMagic clippoly-pl11/t20100644000076400010400000000726010210647233014734 0ustar KlamerAdministrators -6 -12 6 -12 6 12 -6 12 PolyMagic -8.277779693603517e+00 -4.847999343872072e+00 -7.927209968566896e+00 -6.464000473022463e+00 -7.448631401062013e+00 -8.079999694824220e+00 -7.248000259399415e+00 -8.623224029541017e+00 -6.817340011596681e+00 -9.696000823974611e+00 -6.040000076293946e+00 -1.124363494873047e+01 -6.000000114440919e+00 -1.131199813842774e+01 -4.896273727416993e+00 -1.292799926757813e+01 -4.831999893188478e+00 -1.301112533569336e+01 -3.623999710083009e+00 -1.425591827392578e+01 -3.230938072204591e+00 -1.454400039672852e+01 -2.415999526977540e+00 -1.511193252563477e+01 -1.207999343872071e+00 -1.563492370605469e+01 8.392333974427402e-07 -1.585918975830078e+01 1.207999114990233e+00 -1.580090118408203e+01 2.415999298095702e+00 -1.545498062133789e+01 3.623999481201171e+00 -1.479440475463867e+01 3.936564331054687e+00 -1.454400039672852e+01 4.831999664306640e+00 -1.378045440673828e+01 5.570999984741210e+00 -1.292799926757813e+01 6.039999847412108e+00 -1.232095504760742e+01 6.675385360717772e+00 -1.131199813842774e+01 7.248000030517577e+00 -1.023243118286133e+01 7.498455886840819e+00 -9.696000823974611e+00 8.123055343627929e+00 -8.079999694824220e+00 8.456000213623046e+00 -6.973386535644533e+00 8.602106933593749e+00 -6.464000473022463e+00 8.959420089721679e+00 -4.847999343872072e+00 9.205696945190429e+00 -3.232000122070314e+00 9.351813201904296e+00 -1.616000900268556e+00 9.404005889892577e+00 2.288818343743060e-07 9.364294891357421e+00 1.615999450683592e+00 9.230662231445312e+00 3.232000579833983e+00 8.996884231567382e+00 4.847999801635741e+00 8.652069931030272e+00 6.464000930786131e+00 8.456000213623046e+00 7.160383453369139e+00 8.183857803344726e+00 8.080000152587889e+00 7.569743041992187e+00 9.696000328063963e+00 7.248000030517577e+00 1.038719295501709e+01 6.757033233642577e+00 1.131199954986572e+01 6.039999847412108e+00 1.244501708984375e+01 5.662796859741210e+00 1.292799972534180e+01 4.831999664306640e+00 1.387382053375244e+01 4.028244857788085e+00 1.454399990081787e+01 3.623999481201171e+00 1.486033653259277e+01 2.415999298095702e+00 1.549386810302734e+01 1.207999114990233e+00 1.581515621185303e+01 8.392333974427402e-07 1.585061668395996e+01 -1.207999343872071e+00 1.560486721038818e+01 -2.415999526977540e+00 1.506131576538086e+01 -3.145139808654786e+00 1.454399990081787e+01 -3.623999710083009e+00 1.418689846038818e+01 -4.828847999572755e+00 1.292799972534180e+01 -4.831999893188478e+00 1.292435287475586e+01 -5.938339347839356e+00 1.131199954986572e+01 -6.040000076293946e+00 1.113841079711914e+01 -6.767523880004884e+00 9.696000328063963e+00 -7.248000259399415e+00 8.508264770507811e+00 -7.407690162658692e+00 8.080000152587889e+00 -7.895205612182618e+00 6.464000930786131e+00 -8.254174346923829e+00 4.847999801635741e+00 -8.456000442504884e+00 3.535133590698241e+00 -8.502920265197755e+00 3.232000579833983e+00 -8.654713745117188e+00 1.615999450683592e+00 -8.707243080139161e+00 2.288818343743060e-07 -8.662716979980470e+00 -1.616000900268556e+00 -8.519124145507813e+00 -3.232000122070314e+00 -8.456000442504884e+00 -3.652660140991213e+00 PolyMagic clippoly-pl11/t2.out0100644000076400010400000000256210210647233015542 0ustar KlamerAdministratorsa_min_b: -6 12 -5.46626 12 -5.93834 11.312 -6 11.2067 PolyMagic -5.5301 -12 -6 -12 -6 -11.312 PolyMagic b_min_a: -5.46626 12 -4.832 12.9244 -4.82885 12.928 -3.624 14.1869 -3.14514 14.544 -2.416 15.0613 -1.208 15.6049 8.39233e-07 15.8506 1.208 15.8152 2.416 15.4939 3.624 14.8603 4.02824 14.544 4.832 13.8738 5.6628 12.928 6.04 12.445 6.75703 11.312 7.248 10.3872 7.56974 9.696 8.18386 8.08 8.456 7.16038 8.65207 6.464 8.99688 4.848 9.23066 3.232 9.36429 1.616 9.40401 2.28882e-07 9.35181 -1.616 9.2057 -3.232 8.95942 -4.848 8.60211 -6.464 8.456 -6.97339 8.12306 -8.08 7.49846 -9.696 7.248 -10.2324 6.67539 -11.312 6.04 -12.321 5.571 -12.928 4.832 -13.7805 3.93656 -14.544 3.624 -14.7944 2.416 -15.455 1.208 -15.8009 8.39233e-07 -15.8592 -1.208 -15.6349 -2.416 -15.1119 -3.23094 -14.544 -3.624 -14.2559 -4.832 -13.0111 -4.89627 -12.928 -5.5301 -12 6 -12 6 12 PolyMagic -6 -11.312 -6 -11.312 -6.04 -11.2436 -6.81734 -9.696 -7.248 -8.62322 -7.44863 -8.08 -7.92721 -6.464 -8.27778 -4.848 -8.456 -3.65266 -8.51912 -3.232 -8.66272 -1.616 -8.70724 2.28882e-07 -8.65471 1.616 -8.50292 3.232 -8.456 3.53513 -8.25417 4.848 -7.89521 6.464 -7.40769 8.08 -7.248 8.50826 -6.76752 9.696 -6.04 11.1384 -6 11.2067 PolyMagic a_and_b: -5.46626 12 6 12 6 -12 -5.5301 -12 -6 -11.312 -6 11.2067 -5.93834 11.312 PolyMagic clippoly-pl11/templates.cc0100644000076400010400000000106410210651410016755 0ustar KlamerAdministratorsstatic const char rcs_id[] = "$Header: /cvsroot/clippoly/clippoly/templates.cc,v 1.5 2005/02/28 17:21:12 klamer Exp $"; // $Log: templates.cc,v $ // Revision 1.5 2005/02/28 17:21:12 klamer // Changed to have g++ 3.2.3 run silently using g++ -ansi -pedantic -Wall -Wno-unused -Wno-reorder. // Change use of (libg++) String to ANSI C++ string. // // Revision 1.1 1995/04/27 07:19:20 klamer // Initial revision // #include "set.h" #include "poly.h" template class SetIter; template class Set; template class RSet; clippoly-pl11/test.cc0100644000076400010400000000301310210651410015732 0ustar KlamerAdministrators// nclip: a polygon clip library // Copyright (C) 1993 University of Twente // klamer@mi.el.utwente.nl // 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. #include #include #include "poly.h" #include "poly_io.h" #include "nclip.h" using namespace ::std; void clear(PolyPList &l) { PolyPListIter i(l); while(i()) delete i.val(); } int main(int, char *[]) { Poly *a = read_poly(cin), *b = read_poly(cin); PolyPList a_min_b, b_min_a, a_and_b; // printf("Area a %g b %g\n", a->area(), b->area()); clip_poly( *a, *b, a_min_b, b_min_a, a_and_b ); cout << "a_min_b:\n" << a_min_b; cout << "b_min_a:\n" << b_min_a; cout << "a_and_b:\n" << a_and_b; delete a; delete b; clear(a_min_b); clear(b_min_a); clear(a_and_b); return 0; }