Screenshot instructions:
Windows
Mac
Red Hat Linux
Ubuntu
Click URL instructions:
Rightclick on ad, choose "Copy Link", then paste here →
(This may not be possible with some types of ads)
You can subscribe to this list here.
2000 
_{Jan}

_{Feb}

_{Mar}

_{Apr}

_{May}
(33) 
_{Jun}

_{Jul}
(30) 
_{Aug}
(2) 
_{Sep}

_{Oct}
(30) 
_{Nov}
(136) 
_{Dec}
(59) 

2001 
_{Jan}
(255) 
_{Feb}
(169) 
_{Mar}
(322) 
_{Apr}
(185) 
_{May}
(33) 
_{Jun}
(89) 
_{Jul}
(47) 
_{Aug}
(59) 
_{Sep}
(40) 
_{Oct}
(31) 
_{Nov}
(74) 
_{Dec}
(84) 
2002 
_{Jan}
(163) 
_{Feb}
(78) 
_{Mar}
(23) 
_{Apr}
(5) 
_{May}
(22) 
_{Jun}
(75) 
_{Jul}
(143) 
_{Aug}
(48) 
_{Sep}
(111) 
_{Oct}
(58) 
_{Nov}
(124) 
_{Dec}
(278) 
2003 
_{Jan}
(106) 
_{Feb}
(276) 
_{Mar}
(354) 
_{Apr}
(97) 
_{May}
(14) 
_{Jun}
(3) 
_{Jul}
(7) 
_{Aug}
(21) 
_{Sep}
(83) 
_{Oct}
(110) 
_{Nov}
(3) 
_{Dec}
(119) 
2004 
_{Jan}
(318) 
_{Feb}
(409) 
_{Mar}
(68) 
_{Apr}
(23) 
_{May}
(105) 
_{Jun}
(147) 
_{Jul}
(69) 
_{Aug}
(53) 
_{Sep}
(23) 
_{Oct}
(14) 
_{Nov}
(15) 
_{Dec}
(63) 
2005 
_{Jan}
(146) 
_{Feb}
(69) 
_{Mar}
(157) 
_{Apr}
(127) 
_{May}
(166) 
_{Jun}
(8) 
_{Jul}
(5) 
_{Aug}
(3) 
_{Sep}
(8) 
_{Oct}
(17) 
_{Nov}
(29) 
_{Dec}
(34) 
2006 
_{Jan}
(3) 
_{Feb}
(4) 
_{Mar}
(1) 
_{Apr}
(70) 
_{May}
(241) 
_{Jun}
(82) 
_{Jul}
(344) 
_{Aug}
(196) 
_{Sep}
(87) 
_{Oct}
(57) 
_{Nov}
(121) 
_{Dec}
(86) 
2007 
_{Jan}
(60) 
_{Feb}
(67) 
_{Mar}
(102) 
_{Apr}
(28) 
_{May}
(13) 
_{Jun}
(29) 
_{Jul}
(38) 
_{Aug}
(56) 
_{Sep}
(91) 
_{Oct}
(89) 
_{Nov}
(50) 
_{Dec}
(68) 
2008 
_{Jan}
(87) 
_{Feb}
(47) 
_{Mar}
(100) 
_{Apr}
(34) 
_{May}
(65) 
_{Jun}
(54) 
_{Jul}
(98) 
_{Aug}
(128) 
_{Sep}
(109) 
_{Oct}
(141) 
_{Nov}
(40) 
_{Dec}
(206) 
2009 
_{Jan}
(176) 
_{Feb}
(226) 
_{Mar}
(134) 
_{Apr}
(84) 
_{May}
(152) 
_{Jun}
(85) 
_{Jul}
(91) 
_{Aug}
(153) 
_{Sep}
(141) 
_{Oct}
(59) 
_{Nov}
(87) 
_{Dec}
(75) 
2010 
_{Jan}
(58) 
_{Feb}
(41) 
_{Mar}
(51) 
_{Apr}
(74) 
_{May}
(81) 
_{Jun}
(39) 
_{Jul}
(30) 
_{Aug}
(43) 
_{Sep}
(76) 
_{Oct}
(59) 
_{Nov}
(62) 
_{Dec}
(52) 
2011 
_{Jan}
(125) 
_{Feb}
(41) 
_{Mar}
(96) 
_{Apr}
(53) 
_{May}
(21) 
_{Jun}
(23) 
_{Jul}
(48) 
_{Aug}
(71) 
_{Sep}
(37) 
_{Oct}
(81) 
_{Nov}
(60) 
_{Dec}
(32) 
2012 
_{Jan}
(51) 
_{Feb}
(23) 
_{Mar}

_{Apr}
(8) 
_{May}
(2) 
_{Jun}

_{Jul}
(8) 
_{Aug}
(25) 
_{Sep}
(4) 
_{Oct}
(32) 
_{Nov}
(17) 
_{Dec}
(2) 
2013 
_{Jan}
(8) 
_{Feb}
(2) 
_{Mar}
(9) 
_{Apr}
(9) 
_{May}
(37) 
_{Jun}
(48) 
_{Jul}
(63) 
_{Aug}
(42) 
_{Sep}
(59) 
_{Oct}
(83) 
_{Nov}
(141) 
_{Dec}
(133) 
2014 
_{Jan}
(57) 
_{Feb}
(58) 
_{Mar}
(58) 
_{Apr}
(25) 
_{May}
(14) 
_{Jun}
(3) 
_{Jul}
(6) 
_{Aug}
(1) 
_{Sep}

_{Oct}

_{Nov}

_{Dec}

S  M  T  W  T  F  S 



1
(5) 
2
(14) 
3
(3) 
4
(6) 
5
(4) 
6
(7) 
7
(12) 
8
(6) 
9
(4) 
10
(1) 
11

12

13

14
(1) 
15
(1) 
16
(2) 
17

18
(2) 
19
(1) 
20

21
(1) 
22
(2) 
23

24
(1) 
25

26

27
(1) 
28
(1) 
29

30

31



From: <airwin@us...>  20091219 23:00:24

Revision: 10725 http://plplot.svn.sourceforge.net/plplot/?rev=10725&view=rev Author: airwin Date: 20091219 23:00:16 +0000 (Sat, 19 Dec 2009) Log Message:  Improved handling of cases where the intersection between two line segments is near the ends of the line segments being tested. This change affects the USE_FILL_INTERSECTION_POLYGON ON case (via a call of notcrossed in both fill_intersection_polygon and pointinpolygon) and USE_FILL_INTERSECTION_POLYGON OFF cases (via the call of notcrossed from pointinpolygon). Improved handling of the end phase of fill_intersection_polygon where polygon 1 and the split of polygon 2 do not cross each other. Bug fixes for fill_intersection_polygon. These changes only affect the case where USE_FILL_INTERSECTION_POLYGON is ON. example 25 results continue to look good for the default USE_FILL_INTERSECTION_POLYGON OFF case. However, there are still some obvious issues (not memory management issues according to valgrind) for the experimental USE_FILL_INTERSECTION_POLYGON ON case. For this case, the example 25 results sometimes fill in the wrong locations, and I am currently working on tracking down and fixing all of these issues. Modified Paths:  trunk/src/plfill.c Modified: trunk/src/plfill.c ===================================================================  trunk/src/plfill.c 20091218 06:27:40 UTC (rev 10724) +++ trunk/src/plfill.c 20091219 23:00:16 UTC (rev 10725) @@ 27,9 +27,42 @@ #define INSIDE( ix, iy ) ( BETW( ix, xmin, xmax ) && BETW( iy, ymin, ymax )) #define DTOR ( PI / 180. ) #define BINC 50 +#define DTOR ( PI / 180. ) +#define BINC 50 +/* Nearborder comparison criterion (NBCC). */ +#define PL_NBCC 2 +/* Variant of BETW that returns true if between or within PL_NBCC of it. */ +#define BETW_NBCC( ix, ia, ib ) ((( ix ) <= ( ia + PL_NBCC ) && ( ix ) >= ( ib  PL_NBCC ))  (( ix ) >= ( ia  PL_NBCC ) && ( ix ) <= ( ib + PL_NBCC ))) +/* Status codes ORed together in the return from notcrossed. + * PL_NOT_CROSSED is set whenever the two line segments definitely + * (i.e., not near the ends or completely apart) do not cross each + * other. + * + * PL_NEAR_A1 is set if the intersect is near (+/ PL_NBCC) the first + * end of line segment A. + * + * PL_NEAR_A2 is set if the intersect is near (+/ PL_NBCC) the second + * end of line segment A. + * + * PL_NEAR_B1 is set if the intersect is near (+/ PL_NBCC) the first + * end of line segment B. + * + * PL_NEAR_B2 is set if the intersect is near (+/ PL_NBCC) the second + * end of line segment B. + * + * PL_PARALLEL is set if the two line segments are parallel with each other. + */ +enum PL_CrossedStatus +{ + PL_NOT_CROSSED = 0x1, + PL_NEAR_A1 = 0x2, + PL_NEAR_A2 = 0x4, + PL_NEAR_B1 = 0x8, + PL_NEAR_B2 = 0x10, + PL_PARALLEL = 0x20 +}; + struct point { PLINT x, y; @@ 65,9 +98,9 @@ const PLINT *if2, PLINT n2 ); static int notintersect( PLINT *xintersect, PLINT *yintersect,  PLINT xA1, PLINT yA1, PLINT xA2, PLINT yA2,  PLINT xB1, PLINT yB1, PLINT xB2, PLINT yB2 ); +notcrossed( PLINT *xintersect, PLINT *yintersect, + PLINT xA1, PLINT yA1, PLINT xA2, PLINT yA2, + PLINT xB1, PLINT yB1, PLINT xB2, PLINT yB2 ); /**\ * void plfill() @@ 1063,12 +1096,13 @@ * through vertex" problem in a numerically robust way. \**/ +/* Temporary until get rid of old code altogether. */ #define NEW_NOTPOINTINPOLYGON_CODE int notpointinpolygon( int n, const PLINT *x, const PLINT *y, PLINT xp, PLINT yp ) { #ifdef NEW_NOTPOINTINPOLYGON_CODE  int i, im1; + int i, im1, ifnotcrossed; int count_crossings = 0; PLINT xmin, xout, yout, xintersect, yintersect; @@ 1092,18 +1126,28 @@ im1 = n  1; for ( i = 0; i < n; i++ ) {  if ( !( x[im1] == x[i] && y[im1] == y[i] ) &&  !notintersect( &xintersect, &yintersect,  x[im1], y[im1], x[i], y[i],  xp, yp, xout, yout ))  count_crossings++; + if ( !( x[im1] == x[i] && y[im1] == y[i] )) + { + ifnotcrossed = notcrossed( &xintersect, &yintersect, + x[im1], y[im1], x[i], y[i], + xp, yp, xout, yout ); + + if ( !ifnotcrossed ) + count_crossings++; + else if ( ifnotcrossed & ( PL_NEAR_A1  PL_NEAR_A2  PL_NEAR_B1  PL_NEAR_B2 )) + return 1; + } im1 = i; }  /* Return the result: an even number of crossings means the  * point is outside the polygon */   return !( count_crossings % 2 ); + /* return 0 if the test point is definitely inside + * (count_crossings odd), return 1 if the test point is near (see + * above logic), and return 2 if the test point is definitely + * outside the border (count_crossings even). */ + if (( count_crossings % 2 ) == 1 ) + return 0; + else + return 2; } #else /* NEW_NOTPOINTINPOLYGON_CODE */ int i; @@ 1236,12 +1280,13 @@ PLINT i1, i1m1, i1wrap, i1wraplast, i2, i2m1, i2wrap, i2wraplast, kk, kkstart1, kkstart21, kkstart22,  k, kstart, range1, range21, range22, nintersect, + k, kstart, range1, range21, range22, ncrossed, nsplit1, nsplit2;  PLINT xintersect[2], yintersect[2], ifintersect; + PLINT xintersect[2], yintersect[2], ifcrossed; PLINT *xsplit1, *ysplit1, *ifsplit1, *xsplit2, *ysplit2, *ifsplit2;  PLINT ifill, nfill = 0; + PLINT ifill, nfill = 0, + ifnotpolygon1inpolygon2, ifnotpolygon2inpolygon1; const PLINT *xfiller, *yfiller; short *xfill, *yfill; @@ 1271,7 +1316,7 @@ } i1m1 = i1start  1;  if ( i1m1 <= 0 ) + if ( i1m1 < 0 ) i1m1 = n1  1; for ( i1 = i1start; i1 < n1; i1++ ) @@ 1297,7 +1342,7 @@ if ( i2 < n2 ) {  plwarn( "fill_intersection_polygon: Internal error; i < n2." ); + plwarn( "fill_intersection_polygon: Internal error; i2 < n2." ); return; } @@ 1356,9 +1401,12 @@ * intersections to be found between polygon 1 and some polygon 2 * split, and in that case we move on to the end phase below. */  nintersect = 0;  i1m1 = n1  1;  i1wrap = 1; + ncrossed = 0; + i1wrap = i1start  1; + if ( i1wrap < 0 ) + i1m1 = n1  1; + else + i1m1 = i1wrap; for ( i1 = i1start; i1 < n1; i1++ ) { i2m1 = n2  1; @@ 1367,34 +1415,23 @@ { if ( !if2[i2] ) {  /* intersect is acted upon only if a series of conditions are met. */  ifintersect = !notintersect(  &xintersect[nintersect], &yintersect[nintersect], + /* ifcrossed true only if there is a definite crossing of + * the two line segments with the intersect not being + * near (+/ PL_NBCC) the ends. ToDo. This test + * must be made more elaborate if the polygons definitely + * cross near one or both of their vertices. */ + ifcrossed = !notcrossed( + &xintersect[ncrossed], &yintersect[ncrossed], x1[i1m1], y1[i1m1], x1[i1], y1[i1], x2[i2m1], y2[i2m1], x2[i2], y2[i2] );  ifintersect = ifintersect && !(  xintersect[nintersect] == x1[i1m1] &&  yintersect[nintersect] == y1[i1m1] );  ifintersect = ifintersect && !(  xintersect[nintersect] == x1[i1] &&  yintersect[nintersect] == y1[i1] );  ifintersect = ifintersect && !(  xintersect[nintersect] == x2[i2m1] &&  yintersect[nintersect] == y2[i2m1] );  ifintersect = ifintersect && !(  xintersect[nintersect] == x2[i2] &&  yintersect[nintersect] == y2[i2] );  if ( ifintersect ) + if ( ifcrossed ) {  /* The above test must be more elaborate if the intersection  * point is a vertex of the first polygon, the second polygon  * or both. ToDo! */  if ( nintersect == 0 ) + if ( ncrossed == 0 ) { i1wraplast = i1wrap; i2wraplast = i2wrap;  nintersect++; + ncrossed++; } else { @@ 1544,53 +1581,81 @@ i1wrap = i1m1; }  if ( nintersect != 0 ) + if ( ncrossed != 0 ) {  plwarn( "fill_intersection_polygon: Internal error; nintersect != 0." ); + plwarn( "fill_intersection_polygon: Internal error; ncrossed != 0." ); return; } /* This end phase is reached only if no intersections are found.  * For this case, the intersection of polygon 2 and 1, must be + * For this case, there are 5 valid and 1 invalid combination of + * the following conditions:the intersection of polygon 2 and 1, must be * either of them (in which case fill with the inner one), or neither * of them (in which case don't fill at all). */  /* Look for first vertex in polygon 2 that is inside polygon 1. */ + /* Classify polygon 1 by looking for first vertex in polygon 1 + * that is definitely inside or outside polygon 2. */ + for ( i1 = 0; i1 < n1; i1++ ) + { + if (( ifnotpolygon1inpolygon2 = + notpointinpolygon( n2, x2, y2, x1[i1], y1[i1] )) != 1 ) + break; + } + + /* Classify polygon 2 by looking for first vertex in polygon 2 + * that is definitely inside or outside polygon 1. */ + ifnotpolygon2inpolygon1 = 1; for ( i2 = 0; i2 < n2; i2++ ) { /* Do not bother checking vertices already known to be on the * boundary with polygon 1. */  if ( !if2[i2] && !notpointinpolygon( n1, x1, y1, x2[i2], y2[i2] )) + if ( !if2[i2] && ( ifnotpolygon2inpolygon1 = + notpointinpolygon( n1, x1, y1, x2[i2], y2[i2] )) != 1 ) break; }  if ( i2 < n2 ) + if ( ifnotpolygon2inpolygon1 == 0 ) {  /* All of polygon 2 inside polygon 1. */  nfill = n2;  xfiller = x2;  yfiller = y2; + /* Polygon 2 definitely inside polygon 1. */ + if ( ifnotpolygon1inpolygon2 != 0 ) + { + nfill = n2; + xfiller = x2; + yfiller = y2; + } + else + plwarn( "fill_intersection_polygon: Internal error; no intersections found but each polygon definitely inside the other!" ); }  else + else if ( ifnotpolygon2inpolygon1 == 1 ) {  /* Look for first vertex in polygon 1 that is inside polygon 2. */  for ( i1 = 0; i1 < n1; i1++ ) + /* Polygon 2 vertices near polygon 1 border. */ + if ( ifnotpolygon1inpolygon2 != 0 ) {  if ( !notpointinpolygon( n2, x2, y2, x1[i1], y1[i1] ))  break; + /* Polygon 1 vertices near polygon 2 border or definitely outside it. */ + nfill = n2; + xfiller = x2; + yfiller = y2; }   if ( i1 < n1 ) + else {  /* All of polygon 1 inside polygon 2 */ + /* Polygon 1 vertices definitely inside polygon 2 border. */ nfill = n1; xfiller = x1; yfiller = y1; }  else + } + else + { + /* Polygon 2 vertices definitely outside polygon 1 border. */ + if ( ifnotpolygon1inpolygon2 != 2 ) { + /* Polygon 1 vertices definitely inside polygon 2 border. */ + nfill = n1; + xfiller = x1; + yfiller = y1; } } + if ( nfill > 0 ) { if (( xfill = (short *) malloc( nfill * sizeof ( short ))) == NULL ) @@ 1614,23 +1679,27 @@ return; } /* Find if an intersection (N.B. including end points) exists between  * straight line segments A and B defined by their endpoints xA1, yA1,  * xA2, yA2, xB1, yB1, xB2, yB2. If not return true (1 if parallel,  * 1 if intersecting away from segments). If true, return false.  * Except for the parallel line case always return the intersection,  * (xintersect, yintersect) via the argument list. */ +/* Returns a 0 status code if the two line segments A, and B defined + * by their end points (xA1, yA1, xA2, yA2, xB1, yB1, xB2, and yB2) + * definitely (i.e., intersection point is not near the ends of either + * of the line segments) cross each other. Otherwise, return a status + * code specifying the type of noncrossing (i.e., completely + * separate, near one of the ends, parallel). Return the actual + * intersection (or average of the x end points and y end points for + * the parallel, not crossed case) via the argument list pointers to + * xintersect and yintersect. */ int notintersect( PLINT * xintersect, PLINT * yintersect,  PLINT xA1, PLINT yA1, PLINT xA2, PLINT yA2,  PLINT xB1, PLINT yB1, PLINT xB2, PLINT yB2 ) +notcrossed( PLINT * xintersect, PLINT * yintersect, + PLINT xA1, PLINT yA1, PLINT xA2, PLINT yA2, + PLINT xB1, PLINT yB1, PLINT xB2, PLINT yB2 ) { PLFLT factor, fxintersect, fyintersect; /* These variables are PLFLT not for precision, but to * avoid integer overflows if they were typed as PLINT. */ PLFLT xA2A1, yA2A1, xB2B1, yB2B1; PLFLT xB1A1, yB1A1, xB2A1, yB2A1; + PLINT status = 0; /* * Two linear equations to be solved for x and y. * y = ((x  xA1)*yA2 + (xA2  x)*yA1)/(xA2  xA1) @@ 1658,49 +1727,60 @@ if ( fabs( factor ) == 0. ) { /* Two line segments are parallel */  /* For this case check for an intersect for each of the end  * points of A segment against the B segment. */  fxintersect = xA1;  fyintersect = yA1;  if ( BETW( fxintersect, xB1, xB2 ) && BETW( fyintersect, yB1, yB2 )) + status = status  PL_PARALLEL; + /* Choice of intersect is arbitrary in this case. Choose A1 if + * that lies near or in B. Otherwise, choose A2 if that lies near + * or in B. Otherwise, choose the average point. */ + if (( BETW_NBCC( xA1, xB1, xB2 ) && BETW_NBCC( yA1, yB1, yB2 ))) {  *xintersect = fxintersect;  *yintersect = fyintersect;  return 0; + fxintersect = xA1; + fyintersect = yA1; }  else + else if (( BETW_NBCC( xA2, xB1, xB2 ) && BETW_NBCC( yA2, yB1, yB2 ))) { fxintersect = xA2; fyintersect = yA2;  if ( BETW( fxintersect, xB1, xB2 ) && BETW( fyintersect, yB1, yB2 ))  {  *xintersect = fxintersect;  *yintersect = fyintersect;  return 0;  }  else  {  /* parallel and no intersect. */  return 1;  } } + else + { + fxintersect = 0.25 * ( xA1 + xA2 + xB1 + xB2 ); + fyintersect = 0.25 * ( yA1 + yA2 + yB1 + yB2 ); + } }  xB1A1 = xB1  xA1;  yB1A1 = yB1  yA1;  xB2A1 = xB2  xA1;  yB2A1 = yB2  yA1; + else + { + xB1A1 = xB1  xA1; + yB1A1 = yB1  yA1; + xB2A1 = xB2  xA1; + yB2A1 = yB2  yA1;  factor = ( xB1A1 * yB2A1  yB1A1 * xB2A1 ) / factor;  fxintersect = factor * xA2A1 + xA1; + factor = ( xB1A1 * yB2A1  yB1A1 * xB2A1 ) / factor; + fxintersect = factor * xA2A1 + xA1; + fyintersect = factor * yA2A1 + yA1; + } + /* The "redundant" x and y segment range checks (which include near the + * end points) are needed for the vertical and the horizontal cases. */ + if (( BETW_NBCC( fxintersect, xA1, xA2 ) && BETW_NBCC( fyintersect, yA1, yA2 )) && + ( BETW_NBCC( fxintersect, xB1, xB2 ) && BETW_NBCC( fyintersect, yB1, yB2 ))) + { + /* The intersect is close (within +/ PL_NBCC) to an end point or + * corresponds to a definite crossing of the two line segments. + * Find out which. */ + if ( fabs( fxintersect  xA1 ) <= PL_NBCC && fabs( fyintersect  yA1 ) <= PL_NBCC ) + status = status  PL_NEAR_A1; + else if ( fabs( fxintersect  xA2 ) <= PL_NBCC && fabs( fyintersect  yA2 ) <= PL_NBCC ) + status = status  PL_NEAR_A2; + else if ( fabs( fxintersect  xB1 ) <= PL_NBCC && fabs( fyintersect  yB1 ) <= PL_NBCC ) + status = status  PL_NEAR_B1; + else if ( fabs( fxintersect  xB2 ) <= PL_NBCC && fabs( fyintersect  yB2 ) <= PL_NBCC ) + status = status  PL_NEAR_B2; + /* N.B. if none of the above conditions hold then status remains at + * zero to signal we have a definite crossing. */ + } + else + status = status  PL_NOT_CROSSED; *xintersect = fxintersect;  fyintersect = factor * yA2A1 + yA1; *yintersect = fyintersect;  /* The "redundant" x and y segment range checks (which include end points)  * are needed for the vertical and the horizontal cases. */  if (( BETW( fxintersect, xA1, xA2 ) && BETW( fyintersect, yA1, yA2 )) &&  ( BETW( fxintersect, xB1, xB2 ) && BETW( fyintersect, yB1, yB2 )))  return 0;  else  return 1; + return status; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. 