// Start a move to the value setpoint: AMControl::FailureExplanation CLSMDriveMotorControl::move(double Setpoint) { if(isMoving()) { if(!allowsMovesWhileMoving()) { AMErrorMon::debug(this, AMPVCONTROL_COULD_NOT_MOVE_WHILE_MOVING, QString("AMPVControl: Could not move %1 (%2) to %3, because the control is already moving.").arg(name()).arg(writePV_->pvName()).arg(setpoint_)); return AlreadyMovingFailure; } if(!moveInProgress()) { // the control is already moving, but it's not one of our moves. In this situation, there is no way that we can start a move and be assured that we'll be notified when OUR move finishes. AMErrorMon::debug(this, AMPVCONTROL_COULD_NOT_MOVE_WHILE_MOVING_EXTERNAL, QString("AMPVControl: Could not move %1 (%2) to %3, because the control is already moving.").arg(name()).arg(writePV_->pvName()).arg(setpoint_)); return AlreadyMovingFailure; } // Otherwise: This control supports mid-move updates, and we're already moving. We just need to update the setpoint and send it. setpoint_ = writeUnitConverter()->convertToRaw(Setpoint); writePV_->setValue(setpoint_); // since the settling phase is considered part of a move, it's OK to be here while settling... But for Acquaman purposes, this will be considered a single re-targetted move, even though the hardware will see two. If we're settling, disable the settling timer, because we only want to respond to the end of the second move. if(settlingInProgress_) { settlingInProgress_ = false; settlingTimer_.stop(); } emit moveReTargetted(); // re-targetted moves will emit moveReTargetted(), although no moveSucceeded()/moveFailed() will be issued for the initial move. } else { settlingInProgress_ = false; stopInProgress_ = false; moveInProgress_ = false; // Flag that "our" move started: startInProgress_ = true; // This is our new target: setpoint_ = writeUnitConverter()->convertToRaw(Setpoint); // Special case: "null move" should complete immediately. Use only if moveStartTolerance() is non-zero, and the move distance is within moveStartTolerance(). if(moveStartTolerance() != 0 && fabs(setpoint()-value()) < moveStartTolerance()) { startInProgress_ = false; moveInProgress_ = true; emit moveStarted(); moveInProgress_ = false; emit moveSucceeded(); } // Normal move: else { // Issue the move command: writePV_->setValue(setpoint_); // start the timer to check if our move failed to start: moveStartTimer_.start(int(moveStartTimeout_*1000.0)); } } return NoFailure; }
void AMPVwStatusAndUnitConversionControl::setUnitConverters(AMAbstractUnitConverter *readUnitConverter, AMAbstractUnitConverter* writeUnitConverter) { double oldValue = value(); double oldSetpoint = setpoint(); delete readConverter_; readConverter_ = readUnitConverter; if(writeConverter_) delete writeConverter_; writeConverter_ = writeUnitConverter; double newValue = value(); double newSetpoint = setpoint(); setUnits(readConverter_->units()); if(newValue != oldValue) emit valueChanged(newValue); if(newSetpoint != oldSetpoint) emit setpointChanged(newSetpoint); }
void plD_line_ljii(PLStream *pls, short x1a, short y1a, short x2a, short y2a) { PLDev *dev = (PLDev *) pls->dev; int i; int xx1 = x1a, yy1 = y1a, xx2 = x2a, yy2 = y2a; PLINT x1b, y1b, x2b, y2b; PLFLT length, fx, fy, dx, dy; /* Take mirror image, since PCL expects (0,0) to be at top left */ yy1 = dev->ymax - (yy1 - dev->ymin); yy2 = dev->ymax - (yy2 - dev->ymin); /* Rotate by 90 degrees */ plRotPhy(ORIENTATION, dev->xmin, dev->ymin, dev->xmax, dev->ymax, &xx1, &yy1); plRotPhy(ORIENTATION, dev->xmin, dev->ymin, dev->xmax, dev->ymax, &xx2, &yy2); x1b = xx1, x2b = xx2, y1b = yy1, y2b = yy2; length = (PLFLT) sqrt((double) ((x2b - x1b) * (x2b - x1b) + (y2b - y1b) * (y2b - y1b))); if (length == 0.) length = 1.; dx = (xx2 - xx1) / length; dy = (yy2 - yy1) / length; fx = xx1; fy = yy1; setpoint((PLINT) xx1, (PLINT) yy1); setpoint((PLINT) xx2, (PLINT) yy2); for (i = 1; i <= (int) length; i++) setpoint((PLINT) (fx += dx), (PLINT) (fy += dy)); }
// This is used to handle the timeout of a move start: void CLSMDriveMotorControl::onMoveStartTimeout() { moveStartTimer_.stop(); // This is only meaningful if one of our moves is in progress. if(startInProgress_) { // give up on this move: startInProgress_ = false; // Special case: only applies if moveTimeoutTolerance_ != 0 AND we've gotten within moveTimeoutTolerance_ of the setpoint. if(moveTimeoutTolerance() != 0.0 && fabs(setpoint() - value()) < moveTimeoutTolerance_) { moveInProgress_ = true; emit moveStarted(); moveInProgress_ = false; emit moveSucceeded(); } else { // The move didn't start within our allowed start period. That counts as a move failed. emit moveFailed(AMControl::TimeoutFailure); } } }
void* ThreadFunction2(void* port) { int secondcounter = 0; int outtransition = 0; int state = (int)(HASH("de.cau.cs.kieler.simplerailctrl.impl.SetPointImpl@7c26a0ba (initial: true) (point: [POINT_19, POINT_20, POINT_23, POINT_24], direction: BRANCH)")); if (DEBUGCONTROLLER) printf("Thread 'org.eclipse.internal.xpand2.type.XpandIterator@432dbb4b' started.\n"); while(1) { if (DEBUGCONTROLLER) printf("Entering state %d.\n",state); //escape if railway system is down if (!railway_alive(railway)) { if (DEBUGCONTROLLER) printf("Railway system down - terminating thread.\n"); exit(EXIT_FAILURE); }//end if //all states if (state == -1) {} else if (state == ((int)(HASH("de.cau.cs.kieler.simplerailctrl.impl.SetSpeedImpl@73b61aea (initial: false) (track: [IC_JCT_0, IC_LN_0, IC_LN_1, IC_LN_2, IC_LN_3, IC_LN_4, IC_LN_5, IC_ST_0, IC_ST_2, IC_ST_4], speed: 100, direction: FWD)")))) { P(2); // GET THE GLOBALLOCK if (DEBUGCONTROLLER) printf("State %d (de.cau.cs.kieler.simplerailctrl.impl.SetSpeedImpl@73b61aea (initial: false) (track: [IC_JCT_0, IC_LN_0, IC_LN_1, IC_LN_2, IC_LN_3, IC_LN_4, IC_LN_5, IC_ST_0, IC_ST_2, IC_ST_4], speed: 100, direction: FWD)) entered.\n",(int)(HASH("de.cau.cs.kieler.simplerailctrl.impl.SetSpeedImpl@73b61aea (initial: false) (track: [IC_JCT_0, IC_LN_0, IC_LN_1, IC_LN_2, IC_LN_3, IC_LN_4, IC_LN_5, IC_ST_0, IC_ST_2, IC_ST_4], speed: 100, direction: FWD)"))); //state1 entry code (SET SPEED) settrack(railway, IC_JCT_0, FWD, 100); setsignal(railway, IC_JCT_0, FIRST, OFF); setsignal(railway, IC_JCT_0, SECOND, GREEN); settrack(railway, IC_LN_0, FWD, 100); setsignal(railway, IC_LN_0, FIRST, OFF); setsignal(railway, IC_LN_0, SECOND, GREEN); settrack(railway, IC_LN_1, FWD, 100); setsignal(railway, IC_LN_1, FIRST, OFF); setsignal(railway, IC_LN_1, SECOND, GREEN); settrack(railway, IC_LN_2, FWD, 100); setsignal(railway, IC_LN_2, FIRST, OFF); setsignal(railway, IC_LN_2, SECOND, GREEN); settrack(railway, IC_LN_3, FWD, 100); setsignal(railway, IC_LN_3, FIRST, OFF); setsignal(railway, IC_LN_3, SECOND, GREEN); settrack(railway, IC_LN_4, FWD, 100); setsignal(railway, IC_LN_4, FIRST, OFF); setsignal(railway, IC_LN_4, SECOND, GREEN); settrack(railway, IC_LN_5, FWD, 100); setsignal(railway, IC_LN_5, FIRST, OFF); setsignal(railway, IC_LN_5, SECOND, GREEN); settrack(railway, IC_ST_0, FWD, 100); setsignal(railway, IC_ST_0, FIRST, OFF); setsignal(railway, IC_ST_0, SECOND, GREEN); settrack(railway, IC_ST_2, FWD, 100); setsignal(railway, IC_ST_2, FIRST, OFF); setsignal(railway, IC_ST_2, SECOND, GREEN); settrack(railway, IC_ST_4, FWD, 100); setsignal(railway, IC_ST_4, FIRST, OFF); setsignal(railway, IC_ST_4, SECOND, GREEN); V(2); // RELEASE THE GLOBALLOCK //state1 transitions code secondcounter = 0; while(1) { P(2); // GET THE GLOBALLOCK outtransition = 0; if ((DEBUGCONTROLLER)&&(!(secondcounter%10))) printf("Transition wait (%d seconds).\n",secondcounter/10); outtransition = 1; //test for contact-events if ((getcontact_sync(railway,IC_ST_2,FIRST,1) != 0)) { V(2); // RELEASE THE GLOBALLOCK if (DEBUGCONTROLLER) printf("Event-Transition taken.\n"); state = HASH("de.cau.cs.kieler.simplerailctrl.impl.SetSpeedImpl@2af590c6 (initial: false) (track: [IC_ST_0, IC_ST_2], speed: 30, direction: FWD)"); break; } V(2); // RELEASE THE GLOBALLOCK //escape if railway system is down if (!railway_alive(railway)) { if (DEBUGCONTROLLER) printf("Railway system down - terminating thread.\n"); exit(EXIT_FAILURE); }//end if //escape if not outtransitions if (!outtransition) { if (DEBUGCONTROLLER) printf("Final state - terminating thread.\n"); //set localTERMINATED := 1 (so that we not wait on this thread in any next macro-tick any more) localTERMINATED2 = 1; return (void *)1; }//end if secondcounter++; usleep(100000); // sleep for 100ms //set localLOCK := 1 and wait for its reset localLOCK2 = 1; while (localLOCK2 == 1){ if (!railway_alive(railway)) { if (DEBUGCONTROLLER) printf("Railway system down - terminating thread.\n"); exit(EXIT_FAILURE); }//end if usleep(5000); // sleep for 5ms //if (DEBUGCONTROLLER) printf("Thread 2 waiting for next tick.\n"); }//end while }//end while }//end if else if (state == ((int)(HASH("de.cau.cs.kieler.simplerailctrl.impl.SetPointImpl@7c26a0ba (initial: true) (point: [POINT_19, POINT_20, POINT_23, POINT_24], direction: BRANCH)")))) { P(2); // GET THE GLOBALLOCK if (DEBUGCONTROLLER) printf("State %d (de.cau.cs.kieler.simplerailctrl.impl.SetPointImpl@7c26a0ba (initial: true) (point: [POINT_19, POINT_20, POINT_23, POINT_24], direction: BRANCH)) entered.\n",(int)(HASH("de.cau.cs.kieler.simplerailctrl.impl.SetPointImpl@7c26a0ba (initial: true) (point: [POINT_19, POINT_20, POINT_23, POINT_24], direction: BRANCH)"))); //state2 enty code (SET POINT) setpoint(railway, POINT_19, BRANCH); setpoint(railway, POINT_20, BRANCH); setpoint(railway, POINT_23, BRANCH); setpoint(railway, POINT_24, BRANCH); V(2); // RELEASE THE GLOBALLOCK //state2 transitions code secondcounter = 0; while(1) { P(2); // GET THE GLOBALLOCK outtransition = 0; if ((DEBUGCONTROLLER)&&(!(secondcounter%10))) printf("Transition wait (%d seconds).\n",secondcounter/10); outtransition = 1; //test for wait-events if (secondcounter/10 >= 5) { V(2); // RELEASE THE GLOBALLOCK if (DEBUGCONTROLLER) printf("Wait-Transition taken.\n"); state = HASH("de.cau.cs.kieler.simplerailctrl.impl.SetSpeedImpl@73b61aea (initial: false) (track: [IC_JCT_0, IC_LN_0, IC_LN_1, IC_LN_2, IC_LN_3, IC_LN_4, IC_LN_5, IC_ST_0, IC_ST_2, IC_ST_4], speed: 100, direction: FWD)"); break; } V(2); // RELEASE THE GLOBALLOCK //escape if railway system is down if (!railway_alive(railway)) { if (DEBUGCONTROLLER) printf("Railway system down - terminating thread.\n"); exit(EXIT_FAILURE); }//end if //escape if not outtransitions if (!outtransition) { if (DEBUGCONTROLLER) printf("Final state - terminating thread.\n"); //set localTERMINATED := 1 (so that we not wait on this thread in any next macro-tick any more) localTERMINATED2 = 1; return (void *)1; }//end if secondcounter++; usleep(100000); // sleep for 100ms //set localLOCK := 1 and wait for its reset localLOCK2 = 1; while (localLOCK2 == 1){ if (!railway_alive(railway)) { if (DEBUGCONTROLLER) printf("Railway system down - terminating thread.\n"); exit(EXIT_FAILURE); }//end if usleep(5000); // sleep for 5ms //if (DEBUGCONTROLLER) printf("Thread 2 waiting for next tick.\n"); }//end while }//end while }//end if else if (state == ((int)(HASH("de.cau.cs.kieler.simplerailctrl.impl.SetSpeedImpl@2af590c6 (initial: false) (track: [IC_ST_0, IC_ST_2], speed: 30, direction: FWD)")))) { P(2); // GET THE GLOBALLOCK if (DEBUGCONTROLLER) printf("State %d (de.cau.cs.kieler.simplerailctrl.impl.SetSpeedImpl@2af590c6 (initial: false) (track: [IC_ST_0, IC_ST_2], speed: 30, direction: FWD)) entered.\n",(int)(HASH("de.cau.cs.kieler.simplerailctrl.impl.SetSpeedImpl@2af590c6 (initial: false) (track: [IC_ST_0, IC_ST_2], speed: 30, direction: FWD)"))); //state3 entry code (SET SPEED) settrack(railway, IC_ST_0, FWD, 30); setsignal(railway, IC_ST_0, FIRST, OFF); setsignal(railway, IC_ST_0, SECOND, YELLOW); settrack(railway, IC_ST_2, FWD, 30); setsignal(railway, IC_ST_2, FIRST, OFF); setsignal(railway, IC_ST_2, SECOND, YELLOW); V(2); // RELEASE THE GLOBALLOCK //state3 transitions code secondcounter = 0; while(1) { P(2); // GET THE GLOBALLOCK outtransition = 0; if ((DEBUGCONTROLLER)&&(!(secondcounter%10))) printf("Transition wait (%d seconds).\n",secondcounter/10); outtransition = 1; //test for contact-events if ((getcontact_sync(railway,IC_ST_2,SECOND,1) != 0)) { V(2); // RELEASE THE GLOBALLOCK if (DEBUGCONTROLLER) printf("Event-Transition taken.\n"); state = HASH("de.cau.cs.kieler.simplerailctrl.impl.SetSpeedImpl@5ff3cd32 (initial: false) (track: [IC_ST_2], speed: 0, direction: FWD)"); break; } V(2); // RELEASE THE GLOBALLOCK //escape if railway system is down if (!railway_alive(railway)) { if (DEBUGCONTROLLER) printf("Railway system down - terminating thread.\n"); exit(EXIT_FAILURE); }//end if //escape if not outtransitions if (!outtransition) { if (DEBUGCONTROLLER) printf("Final state - terminating thread.\n"); //set localTERMINATED := 1 (so that we not wait on this thread in any next macro-tick any more) localTERMINATED2 = 1; return (void *)1; }//end if secondcounter++; usleep(100000); // sleep for 100ms //set localLOCK := 1 and wait for its reset localLOCK2 = 1; while (localLOCK2 == 1){ if (!railway_alive(railway)) { if (DEBUGCONTROLLER) printf("Railway system down - terminating thread.\n"); exit(EXIT_FAILURE); }//end if usleep(5000); // sleep for 5ms //if (DEBUGCONTROLLER) printf("Thread 2 waiting for next tick.\n"); }//end while }//end while }//end if else if (state == ((int)(HASH("de.cau.cs.kieler.simplerailctrl.impl.SetSpeedImpl@5ff3cd32 (initial: false) (track: [IC_ST_2], speed: 0, direction: FWD)")))) { P(2); // GET THE GLOBALLOCK if (DEBUGCONTROLLER) printf("State %d (de.cau.cs.kieler.simplerailctrl.impl.SetSpeedImpl@5ff3cd32 (initial: false) (track: [IC_ST_2], speed: 0, direction: FWD)) entered.\n",(int)(HASH("de.cau.cs.kieler.simplerailctrl.impl.SetSpeedImpl@5ff3cd32 (initial: false) (track: [IC_ST_2], speed: 0, direction: FWD)"))); //state4 entry code (SET SPEED) settrack(railway, IC_ST_2, FWD, 0); setsignal(railway, IC_ST_2, FIRST, OFF); setsignal(railway, IC_ST_2, SECOND, RED); V(2); // RELEASE THE GLOBALLOCK //state4 transitions code secondcounter = 0; while(1) { P(2); // GET THE GLOBALLOCK outtransition = 0; if ((DEBUGCONTROLLER)&&(!(secondcounter%10))) printf("Transition wait (%d seconds).\n",secondcounter/10); outtransition = 1; //test for wait-events if (secondcounter/10 >= 10) { V(2); // RELEASE THE GLOBALLOCK if (DEBUGCONTROLLER) printf("Wait-Transition taken.\n"); state = HASH("de.cau.cs.kieler.simplerailctrl.impl.SetSpeedImpl@73b61aea (initial: false) (track: [IC_JCT_0, IC_LN_0, IC_LN_1, IC_LN_2, IC_LN_3, IC_LN_4, IC_LN_5, IC_ST_0, IC_ST_2, IC_ST_4], speed: 100, direction: FWD)"); break; } V(2); // RELEASE THE GLOBALLOCK //escape if railway system is down if (!railway_alive(railway)) { if (DEBUGCONTROLLER) printf("Railway system down - terminating thread.\n"); exit(EXIT_FAILURE); }//end if //escape if not outtransitions if (!outtransition) { if (DEBUGCONTROLLER) printf("Final state - terminating thread.\n"); //set localTERMINATED := 1 (so that we not wait on this thread in any next macro-tick any more) localTERMINATED2 = 1; return (void *)1; }//end if secondcounter++; usleep(100000); // sleep for 100ms //set localLOCK := 1 and wait for its reset localLOCK2 = 1; while (localLOCK2 == 1){ if (!railway_alive(railway)) { if (DEBUGCONTROLLER) printf("Railway system down - terminating thread.\n"); exit(EXIT_FAILURE); }//end if usleep(5000); // sleep for 5ms //if (DEBUGCONTROLLER) printf("Thread 2 waiting for next tick.\n"); }//end while }//end while }//end if }//end while }
void plD_line_ljiip(PLStream *pls, short x1a, short y1a, short x2a, short y2a) { PLDev *dev = (PLDev *) pls->dev; int xx1 = x1a, yy1 = y1a, xx2 = x2a, yy2 = y2a; int abs_dx, abs_dy, dx, dy, incx, incy; int i, j, width, residual; PLFLT tmp; width = MIN(pls->width, MAX_WID); /* Take mirror image, since PCL expects (0,0) to be at top left */ yy1 = dev->ymax - (yy1 - dev->ymin); yy2 = dev->ymax - (yy2 - dev->ymin); /* Rotate by 90 degrees */ plRotPhy(ORIENTATION, dev->xmin, dev->ymin, dev->xmax, dev->ymax, &xx1, &yy1); plRotPhy(ORIENTATION, dev->xmin, dev->ymin, dev->xmax, dev->ymax, &xx2, &yy2); dx = xx2 - xx1; dy = yy2 - yy1; if (dx < 0) { abs_dx = -dx; incx = -1; } else { abs_dx = dx; incx = 1; } if (dy < 0) { abs_dy = -dy; incy = -1; } else { abs_dy = dy; incy = 1; } /* make pixel width narrower for diag lines */ if (abs_dy <= abs_dx) { if (abs_dx == 0) tmp = 1.0; else tmp = 1.0 - (PLFLT) abs_dy / abs_dx; } else { tmp = 1.0 - (PLFLT) abs_dx / abs_dy; } width = floor(0.5 + width * (tmp*tmp*tmp*(1.0-0.707107) + 0.707107)); if (width < 1) width = 1; if (width > 1) { for (i = 0; i < width; i++) { for (j = 0; j < width; j++) { setpoint((PLINT) (xx1+i), (PLINT) (yy1+j)); setpoint((PLINT) (xx2+i), (PLINT) (yy2+j)); } } } if (abs_dx >= abs_dy) { residual = -(abs_dx >> 1); if (width == 1) { for (i = 0; i <= abs_dx; i++, xx1 += incx) { setpoint((PLINT) (xx1), (PLINT) (yy1)); if ((residual += abs_dy) >= 0) { residual -= abs_dx; yy1 += incy; } } } else { for (i = 0; i <= abs_dx; i++, xx1 += incx) { for (j = 0; j < width; j++) { setpoint((PLINT) (xx1), (PLINT) (yy1+j)); setpoint((PLINT) (xx1+width-1), (PLINT) (yy1+j)); } if ((residual += abs_dy) >= 0) { residual -= abs_dx; yy1 += incy; } } } }
/* ** Test crossings side. */ static void test_lw_segment_intersects(void) { #define setpoint(p, x1, y1) {(p).x = (x1); (p).y = (y1);} POINT2D p1, p2, q1, q2; /* P: Vertical line at x=0 */ setpoint(p1, 0.0, 0.0); p1.x = 0.0; p1.y = 0.0; p2.x = 0.0; p2.y = 1.0; /* Q: Horizontal line crossing left to right */ q1.x = -0.5; q1.y = 0.5; q2.x = 0.5; q2.y = 0.5; CU_ASSERT( lw_segment_intersects(&p1, &p2, &q1, &q2) == SEG_CROSS_RIGHT ); /* Q: Horizontal line crossing right to left */ q1.x = 0.5; q1.y = 0.5; q2.x = -0.5; q2.y = 0.5; CU_ASSERT( lw_segment_intersects(&p1, &p2, &q1, &q2) == SEG_CROSS_LEFT ); /* Q: Horizontal line not crossing right to left */ q1.x = 0.5; q1.y = 1.5; q2.x = -0.5; q2.y = 1.5; CU_ASSERT( lw_segment_intersects(&p1, &p2, &q1, &q2) == SEG_NO_INTERSECTION ); /* Q: Horizontal line crossing at second vertex right to left */ q1.x = 0.5; q1.y = 1.0; q2.x = -0.5; q2.y = 1.0; CU_ASSERT( lw_segment_intersects(&p1, &p2, &q1, &q2) == SEG_NO_INTERSECTION ); /* Q: Horizontal line crossing at first vertex right to left */ q1.x = 0.5; q1.y = 0.0; q2.x = -0.5; q2.y = 0.0; CU_ASSERT( lw_segment_intersects(&p1, &p2, &q1, &q2) == SEG_CROSS_LEFT ); /* Q: Diagonal line with large range crossing at first vertex right to left */ q1.x = 0.5; q1.y = 10.0; q2.x = -0.5; q2.y = -10.0; CU_ASSERT( lw_segment_intersects(&p1, &p2, &q1, &q2) == SEG_CROSS_LEFT ); /* Q: Diagonal line with large range crossing at second vertex right to left */ q1.x = 0.5; q1.y = 11.0; q2.x = -0.5; q2.y = -9.0; CU_ASSERT( lw_segment_intersects(&p1, &p2, &q1, &q2) == SEG_NO_INTERSECTION ); /* Q: Horizontal touching from left at second vertex*/ q1.x = -0.5; q1.y = 0.5; q2.x = 0.0; q2.y = 0.5; CU_ASSERT( lw_segment_intersects(&p1, &p2, &q1, &q2) == SEG_NO_INTERSECTION ); /* Q: Horizontal touching from right at first vertex */ q1.x = 0.0; q1.y = 0.5; q2.x = 0.5; q2.y = 0.5; CU_ASSERT( lw_segment_intersects(&p1, &p2, &q1, &q2) == SEG_CROSS_RIGHT ); /* Q: Horizontal touching from left and far below on second vertex */ q1.x = -0.5; q1.y = -10.5; q2.x = 0.0; q2.y = 0.5; CU_ASSERT( lw_segment_intersects(&p1, &p2, &q1, &q2) == SEG_NO_INTERSECTION ); /* Q: Horizontal touching from right and far above on second vertex */ q1.x = 0.5; q1.y = 10.5; q2.x = 0.0; q2.y = 0.5; CU_ASSERT( lw_segment_intersects(&p1, &p2, &q1, &q2) == SEG_NO_INTERSECTION ); /* Q: Co-linear from top */ q1.x = 0.0; q1.y = 10.0; q2.x = 0.0; q2.y = 0.5; CU_ASSERT( lw_segment_intersects(&p1, &p2, &q1, &q2) == SEG_COLINEAR ); /* Q: Co-linear from bottom */ q1.x = 0.0; q1.y = -10.0; q2.x = 0.0; q2.y = 0.5; CU_ASSERT( lw_segment_intersects(&p1, &p2, &q1, &q2) == SEG_COLINEAR ); /* Q: Co-linear contained */ q1.x = 0.0; q1.y = 0.4; q2.x = 0.0; q2.y = 0.5; CU_ASSERT( lw_segment_intersects(&p1, &p2, &q1, &q2) == SEG_COLINEAR ); /* Q: Horizontal touching at end point from left */ q1.x = -0.5; q1.y = 1.0; q2.x = 0.0; q2.y = 1.0; CU_ASSERT( lw_segment_intersects(&p1, &p2, &q1, &q2) == SEG_NO_INTERSECTION ); /* Q: Horizontal touching at end point from right */ q1.x = 0.0; q1.y = 1.0; q2.x = 0.0; q2.y = 0.5; CU_ASSERT( lw_segment_intersects(&p1, &p2, &q1, &q2) == SEG_COLINEAR ); /* Q: Horizontal touching at start point from left */ q1.x = 0.0; q1.y = 0.0; q2.x = -0.5; q2.y = 0.0; CU_ASSERT( lw_segment_intersects(&p1, &p2, &q1, &q2) == SEG_CROSS_LEFT ); /* Q: Horizontal touching at start point from right */ q1.x = 0.0; q1.y = 0.0; q2.x = 0.5; q2.y = 0.0; CU_ASSERT( lw_segment_intersects(&p1, &p2, &q1, &q2) == SEG_CROSS_RIGHT ); }