/*****************************************************************************1*2* Elmer, A Finite Element Software for Multiphysical Problems3*4* Copyright 1st April 1995 - , CSC - IT Center for Science Ltd., Finland5*6* This library is free software; you can redistribute it and/or7* modify it under the terms of the GNU Lesser General Public8* License as published by the Free Software Foundation; either9* version 2.1 of the License, or (at your option) any later version.10*11* This library is distributed in the hope that it will be useful,12* but WITHOUT ANY WARRANTY; without even the implied warranty of13* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU14* Lesser General Public License for more details.15*16* You should have received a copy of the GNU Lesser General Public17* License along with this library (in file ../LGPL-2.1); if not, write18* to the Free Software Foundation, Inc., 51 Franklin Street,19* Fifth Floor, Boston, MA 02110-1301 USA20*21*****************************************************************************/2223/*******************************************************************************24*25* Clipping routines for MATC graphics.26*27*******************************************************************************28*29* Author: Juha Ruokolainen30*31* Address: CSC - IT Center for Science Ltd.32* Keilaranta 14, P.O. BOX 40533* 02101 Espoo, Finland34* Tel. +358 0 457 272335* Telefax: +358 0 457 230236* EMail: [email protected]37*38* Date: 30 May 199639*40* Modified by:41*42* Date of modification:43*44******************************************************************************/45/**************************************************************************46*47* by Otto Pesonen48*49* Started 08-SEP-88 / OP50* Last edited 16-FEB-89 / OP51*52* Version: 0.053* File : clip.c54*55* Clip a polygon against any bounding box56* An example program.57*58************************************o*************************************/596061/*62* $Id: clip.c,v 1.2 2005/05/27 12:26:19 vierinen Exp $63*64* $Log: clip.c,v $65* Revision 1.2 2005/05/27 12:26:19 vierinen66* changed header install location67*68* Revision 1.1.1.1 2005/04/14 13:29:14 vierinen69* initial matc automake package70*71* Revision 1.2 1998/08/01 12:34:31 jpr72*73* Added Id, started Log.74*75*76*/7778#include "elmer/matc.h"7980/**************************************************************************81Clip a 2D-polygon against clipping box82If all points are inside the clipping box the polygon is trivially83accepted.84Otherwise it is clipped in turn against single clipping edge.8586RETURN: Number of points in the polygon inside the box8788NOTICE! The new number of points may be GRATER than the in origin!89The theoretical number of points newer exceeds twice90the number in origin.91************************************o*************************************/92int clip_poly(int *n,double *x,double *y)93/* int *n; Number of points in polygon */94/* double *x,*y; Coordinate arrays of the polygon */95{96int last, /* Last point code (in/out?) */97this; /* Current point code (in/out?) */98int i,j,k; /* Arrays index (orig, new & temp) */99int nn; /* Internal counter of points */100int eg; /* Current edge for clipping */101int icode; /* Sum of points inside bounding box */102double xx,yy; /* Current point coordinates, i:th */103double cx,cy; /* Coordinates of the clipped point */104double lx,ly; /* Coordinates of the previous point */105double dx,dy; /* Length of the line segment */106107nn = *n;108icode = 0;109last = FALSE;110111for(i=0; i<nn ; i++)112if (x[i]<=CL_XMAX && x[i]>=CL_XMIN &&113y[i]<=CL_YMAX && y[i]>=CL_YMIN) icode++;114if(icode == nn) return(nn); /* All points inside the box! */115116for( eg=0 ; eg<4 ; eg++) /* Loop over all the edges */117{118x[nn] = x[0]; /* Handle the first point */119y[nn] = y[0]; /* this eases the program a lot! */120nn++;121122for(i=j=0 ; i<nn ; i++) /* Loop over the points! */123{124xx=x[i];125yy=y[i];126127this = FALSE;128switch(eg) /* Code the current point */129{130case 0: if (yy <= CL_YMAX) this = TRUE; break;131case 1: if (yy >= CL_YMIN) this = TRUE; break;132case 2: if (xx <= CL_XMAX) this = TRUE; break;133case 3: if (xx >= CL_XMIN) this = TRUE; break;134}135136if(i>0)137{138if((this && !last) || (last && !this))139{140dx = xx-lx;141dy = yy-ly;142switch(eg) /* Cut against edge */143{144case 0:145cx = lx + ((CL_YMAX-ly)*dx)/dy;146cy = CL_YMAX;147break;148case 1:149cx = lx + ((CL_YMIN-ly)*dx)/dy;150cy = CL_YMIN;151break;152case 2:153cy = ly + ((CL_XMAX-lx)*dy)/dx;154cx = CL_XMAX;155break;156case 3:157cy = ly + ((CL_XMIN-lx)*dy)/dx;158cx = CL_XMIN;159break;160}161}162163if(last) /* Decide to store the point(s) */164if(this)165{ x[j]=xx; y[j]=yy; j++; }166else167{ x[j]=cx; y[j]=cy; j++; }168else169if(this)170{171if(j+2 > i) /* Too many points without shift */172{173for(k=nn; k>i ; k--) { x[k]=x[k-1]; y[k]=y[k-1]; }174nn++;175i++; /* Update pointer AND the limit */176}177x[j]=cx; y[j]=cy; j++; /* Store two points */178x[j]=xx; y[j]=yy; j++;179}180}181else182if(this) /* Store the first point */183{ x[j]=xx; y[j]=yy; j++; }184185lx = xx;186ly = yy;187last = this; /* Save the last point */188189}190*n = j;191if(!j) return(j); /* No need to proceed */192nn = j;193}194*n = j;195return(j);196}197198#define NULL_EDGE 0199#define LEFT_EDGE 1200#define RIGHT_EDGE 2201#define BOTTOM_EDGE 4202#define TOP_EDGE 8203204void clip_code(double x, double y, int*c)205{206*c = NULL_EDGE;207208if (x < CL_XMIN)209*c = LEFT_EDGE;210else if (x > CL_XMAX)211*c = RIGHT_EDGE;212213if (y < CL_YMIN)214*c |= BOTTOM_EDGE;215else if (y > CL_YMAX)216*c |= TOP_EDGE;217}218219/*220* Polyline clipping routine. Return value is number of points inside221* clipping limits when first linesegment not totally inside222* the limits is found (the last one is included in the count if it is223* part of a visible line segment). One should call this routine repeatedly224* until all the linesegments in the polyline are handled. Edge crossing225* points of the last linesegment are stored in place of originals.226*/227int clip_line(int *n, double *x, double *y)228{229double xx, yy,230px, py;231232int i,c,c1,c2;233234px = x[0];235py = y[0];236clip_code(px,py,&c1);237for(i = 1; i < *n; i++)238{239clip_code(x[i],y[i],&c2);240if (c1 || c2)241{242while(c1 || c2)243{244if (c1 & c2)245{246*n = i;247return *n;248}249250c = c1 ? c1 : c2;251252if (c & LEFT_EDGE)253{254yy = py+(y[i]-py)*(CL_XMIN-px)/(x[i]-px);255xx = CL_XMIN;256}257else if (c & RIGHT_EDGE)258{259yy = py+(y[i]-py)*(CL_XMAX-px)/(x[i]-px);260xx = CL_XMAX;261}262else if (c & BOTTOM_EDGE)263{264xx = px+(x[i]-px)*(CL_YMIN-py)/(y[i]-py);265yy = CL_YMIN;266}267else if (c & TOP_EDGE)268{269xx = px+(x[i]-px)*(CL_YMAX-py)/(y[i]-py);270yy = CL_YMAX;271}272273if (c == c1)274{275x[i-1] = px = xx;276y[i-1] = py = yy;277clip_code(xx,yy,&c1);278}279else280{281x[i] = xx;282y[i] = yy;283clip_code(xx,yy,&c2);284}285}286*n = i + 1;287return *n;288}289px = x[i];290py = y[i];291c1 = c2;292}293return *n;294}295296297