/* ** Function : inDiamond() ** Purpose : test whether a point is in, on or outside diamond ** Arguments: diamond, point ** Returns : -1 if outside, 0 if on, +1 if in diamond ** Notes : */ int inDiamond (struct diamond testDiamond, struct point testPoint) { int retval = 0; int retval2 = 0; retval = PointLine(&testDiamond.eastmost, &testDiamond.top, &testPoint); if (retval >= 0) { retval2 = PointLine(&testDiamond.top, &testDiamond.westmost, &testPoint); if (retval2 == 0) { retval = 0; } else if (retval2 < 0) { return retval2; } retval2 = PointLine(&testDiamond.westmost, &testDiamond.bottom, &testPoint); if (retval2 == 0) { retval = 0; } else if (retval2 < 0) { return retval2; } retval2 = PointLine(&testDiamond.bottom, &testDiamond.eastmost, &testPoint); if (retval2 == 0) { retval = 0; } else if (retval2 < 0) { return retval2; } } return retval; }
BOOL CTyDirection::PointInObj(float x, float y, float errRange) { ASSERT(errRange>=0); if (m_bDelete) return FALSE; if ((x<max(0,__min(m_x0,m_x1)-errRange))&& (y<max(0,__min(m_y0,m_y1)-errRange))&& (x>__max(m_x0,m_x1)+errRange)&& (y>__max(m_y0,m_y1)+errRange)) return FALSE; float dist=PointLine(x,y,m_x0,m_y0,m_x1,m_y1); if (dist>errRange) return FALSE; else return TRUE; }
/* ** Function : ringNesting() ** Purpose : ** Arguments: counter of number of rings, pointer to ring circle ** Returns : pointer to array of nesting information ** Notes : */ int * ringNesting(int ringCnt, struct ring *rings) { int *nesting = (int *)NULL; // struct ring *ringPointers = (struct ring *)NULL; // struct ring *tempPointer = (struct ring *)NULL; int inner; int outer; struct ring *innerRing; struct ring *outerRing; struct point thisPoint; struct point firstPoint; struct point lineStart; struct point lineEnd; struct points *aPoints; struct points *firstLine; struct points *aLine; int isfirstP = 0; int isfirstL = 0; int touching = 0; int i, j; /* work variables */ /* ** This is where we consider the nesting of the various rings. ** We do this by setting up a matrix - ringisin - which takes two ** subscripts. The values in this matrix are: ** -2 ring subscript_1 is NOT in ring subscript_2 ** -1 ring subscript_1 is NOT in ring subscript_2, but touches it ** 0 nesting not decided ** +1 ring subscript_1 is in ring subscript_2, and touches it ** +2 ring subscript_1 is in ring subscript_2 ** ** The nesting of N rings requires us (initially) to make N*(N-1) ** ring-in-ring tests. This is not the most efficient it could be, ** but given the number of rings that (in reality) we are likely ** to encounter simultaneously, it's probably not too bad. ** N 1 2 3 4 5 6 7 8 9 ... ** Tests 0 2 6 12 20 30 42 56 72 ... ** ** Each test tries to determine as quickly as possible the gross ** inclusion and exclusions. If we are looking at rings A and B, ** and asking whether ring A is in ring B then we proceed as follows: ** 1) this algorithm works *only* if ring B is convex ** 2) for each point on ring A: ** i) is this point outside box B? ** yes - A is outside B ** touching - A touches B - test more points ** no - test more points ** ii) is this point inside diamond B? ** yes or touching - test more points ** no - test this point of A against each line in B ** So we have to test a point of A against every line of B only if it ** is both inside B's box and outside B's diamond. */ /* DEBUG PRINT: */ if (tprint != 0) { fprintf(stderr,"\nRing Nesting:\n"); } /* END DEBUG PRINT */ /* Get enough memory for the array: */ nesting = malloc(ringCnt*(ringCnt/*-1*/)*sizeof(int)); /* * If we could not get enough memory, return the NULL pointer */ if (nesting == (int *)NULL) { fprintf(stderr, "ERROR: Could not evaluate ring nesting - no memory\n"); return nesting; } /* * Initialise array to all zeros - indicating not yet calculated */ for (i=0; i<ringCnt; i++) for (j=0; j<ringCnt; j++) *((nesting)+(ringCnt*i+j)) = 0; /* * Now we loop round every ring ("inner") and ask is this in ring "outer", * where "outer" also loops round every ring. * Begin by pointing to the first inner ring: */ innerRing = rings; for (inner=1; inner<=ringCnt; inner++) { /* * Point to first outer ring: */ outerRing = rings; for (outer=1; outer<=ringCnt; outer++) { /* * This loop asks (and answers!) the question: * is "inner" inside "outer"? */ /* Go round each point on ring "inner" * Logic: * 0) default mark inner as inside outer * 1) get the first point of inner * 2) test point against box * if outside box then inner is outside outer; exit (go to 6) * 3) test point against diamond * if inside diamond then still inside - go to 5) * 4) test point against each line of outer * if outside any line, then mark as outside and exit (go to 6) * 5) get next point of inner * if this is the first point again, then exit (go to 6) * otherwise go back to 2) * 6) end of calculation - exit point */ /* 0) Default mark inner as inside outer: */ *((nesting)+(ringCnt*inner+outer)) = 2; /* ...and also that they are NOT touching: */ touching = 0; /* * If the two rings are the same (i.e. inner == outer) then * clearly they nest - and no further tests are needed: */ if (inner == outer) { goto foundnest; } /* 1) Get first point of inner ring */ thisPoint = innerRing->pts->pt; firstPoint = thisPoint; isfirstP = 0; aPoints = innerRing->pts; while (isfirstP == 0) { /* 2) Test point against box */ /* If it is outside the box, then it is outside the ring */ if ( (thisPoint.x > outerRing->ringbox.max.x) || (thisPoint.x < outerRing->ringbox.min.x) || (thisPoint.y > outerRing->ringbox.max.y) || (thisPoint.y < outerRing->ringbox.min.y)) { *((nesting)+(ringCnt*inner+outer)) = -2; goto foundnest; } /* 3) Test point against diamond */ /* If it is inside the diamond, then it is inside the ring */ if ( inDiamond(outerRing->ringdiamond, thisPoint) >=0 ) { *((nesting)+(ringCnt*inner+outer)) = 2; goto foundnest; } /* 4) test point against each line of ring */ /* * So we know that this point is inside the box and outside * the diamond - thus we have to test this point against * every line of the (nominally outer) ring. Tedium. * We go into a loop, testing each line separately. * If we are ever outside the line, then we are also outside * the ring. If we are ever touching the line, then we are * touching the ring. * FOR THE MOMENT we are not checking all of the touching * situations - so we only have "inside" and "outside" (20120416) */ firstLine = outerRing->pts; aLine = firstLine; isfirstL = 0; while (isfirstL == 0) { lineStart = aLine->pt; lineEnd = aLine->next->pt; i = PointLine(&lineStart, &lineEnd, &thisPoint); if (i < 0) { *((nesting)+(ringCnt*inner+outer)) = -2; goto foundnest; } else if (i == 0) { /* * >>>> INSERT MORE CODE HERE >>>> * This is the "touching" case - that is, we know that * the point is on the line (or a projection of that * line). * ?? do we have to determine whether the point is on * a projection of the line?? I think we do - because * only when the point is ON the line do we have the * case of "touching". */ } /* * Get the next line in the sequence, and check whether we * are back to the beginning of the outer ring: */ aLine = aLine->next; if (aLine == firstLine) { isfirstL = 1; } } /* 5) get next point of inner */ aPoints = aPoints->next; thisPoint = aPoints->pt; if ((thisPoint.x == firstPoint.x) && (thisPoint.y == firstPoint.y)) { isfirstP = 1; } } /* 6) end of calculation for *this* inner ring: */ foundnest: /* * If we have the "touching" case, then divide the indicator * by two, to record that fact: */ if (touching != 0) { *((nesting)+(ringCnt*inner+outer)) = *((nesting)+(ringCnt*inner+outer)) / 2; } /* * Now point to the next outer ring, and go back to try it */ outerRing = outerRing->next; //NEW } /* * Now point to the next inner ring, and go back to try it */ innerRing = innerRing->next; } /* DEBUG PRINT: */ if (tprint != 0) { for (inner=1; (inner<=ringCnt); inner++) { for (outer=1; (outer<=ringCnt); outer++) { fprintf(stderr,"Nesting: in=%d out=%d nest=%d\n",inner,outer, *((nesting)+(ringCnt*inner+outer))); } } } /* END DEBUG PRINT */ return nesting; }