void Slit::build() { prepareGeometryChange(); m_path = QPainterPath(QPointF(0.0, -m_radius)); m_path.lineTo(0.0, -m_slitRadius); m_path.moveTo(0.0, m_slitRadius); m_path.lineTo(QPointF(0.0, m_radius)); m_leftEdge = leftEdge(); m_rightEdge = rightEdge(); m_leftSlitEdge = mapToScene(QPointF(0.0, -m_slitRadius)); m_rightSlitEdge = mapToScene(QPointF(0.0, m_slitRadius)); m_rays.append(nullptr); while(Ray * ray = m_rays.takeFirst()) ray->plot(); foreach(LightSource * lightSource, m_opticalSystem->lightSources()) lightSource->replot(this); }
void VerticalRayGraphicsItem::drawArrowhead( QPainter* painter, double targetY, bool isShootingUp ) { if ( this->scene( ) == 0 || this->scene( )->views( ).size( ) == 0 ) { return; } QGraphicsView* view = this->scene( )->views( ).first( ); QPointF arrowTip( this->m_source.x( ), targetY ); QPoint pt = view->mapFromScene( arrowTip ); if ( ! isShootingUp && this->m_isInfinite ) { if (view->horizontalScrollBar( ) && view->horizontalScrollBar( )->isVisible( ) ) { // std::cout << view->horizontalScrollBar( )->height( ) << std::endl; pt.setY( pt.y( ) - view->horizontalScrollBar( )->height( ) - 5 ); arrowTip = view->mapToScene( pt ); } else { // std::cout << "no scroll bar " << std::endl; pt.setY( pt.y( ) - 5 ); arrowTip = view->mapToScene( pt ); } } int dy = -1; if ( isShootingUp ) { dy = 1; } QPoint leftPt( pt.x( ) - 3, pt.y( ) + 3*dy ); QPoint rightPt( pt.x( ) + 3, pt.y( ) + 3*dy ); QPointF left = view->mapToScene( leftPt ); QPointF right = view->mapToScene( rightPt ); QLineF leftEdge( left, arrowTip ); QLineF rightEdge( arrowTip, right ); painter->drawLine( leftEdge ); painter->drawLine( rightEdge ); }
Size Transformation::getCropSize(vector<Point2f> areaCorners, Size targetSize) { // Figure out the approximate width/height of the license plate region, so we can maintain the aspect ratio. LineSegment leftEdge(round(areaCorners[3].x), round(areaCorners[3].y), round(areaCorners[0].x), round(areaCorners[0].y)); LineSegment rightEdge(round(areaCorners[2].x), round(areaCorners[2].y), round(areaCorners[1].x), round(areaCorners[1].y)); LineSegment topEdge(round(areaCorners[0].x), round(areaCorners[0].y), round(areaCorners[1].x), round(areaCorners[1].y)); LineSegment bottomEdge(round(areaCorners[3].x), round(areaCorners[3].y), round(areaCorners[2].x), round(areaCorners[2].y)); float w = distanceBetweenPoints(leftEdge.midpoint(), rightEdge.midpoint()); float h = distanceBetweenPoints(bottomEdge.midpoint(), topEdge.midpoint()); float aspect = w/h; int width = targetSize.width; int height = round(((float) width) / aspect); if (height > targetSize.height) { height = targetSize.height; width = round(((float) height) * aspect); } return Size(width, height); }
// ------------------------------------------------------------------ // Coordinates: // row and column are square coordinates. // sr and sc are display coordinates void Viewer::drawGrid() { GridChar gc; GridChar::LineType rowType; GridChar::LineType colType; for (int sr = 0; sr < height; ++sr) { // Classify row type if (topEdge(sr)) rowType = GridChar::edge1; else if (botEdge(sr)) rowType = GridChar::edge2; else if (majorRow(sr)) rowType = GridChar::major; else if (minorRow(sr)) rowType = GridChar::minor; else rowType = GridChar::none; for (int sc = 0; sc < width; ++sc) { // Classify col type if (leftEdge(sc)) colType = GridChar::edge1; else if (rightEdge(sc)) colType = GridChar::edge2; else if (majorCol(sc)) colType = GridChar::major; else if (minorCol(sc)) colType = GridChar::minor; else colType = GridChar::none; cv->setPixel(sr, sc, gc.boxGlyph(rowType, colType)); } } }
ViewerGL::Implementation::WipePolygonEnum ViewerGL::Implementation::getWipePolygon(const RectD & texRectClipped, QPolygonF & polygonPoints, bool rightPlane) const { ///Compute a second point on the plane separator line ///we don't really care how far it is from the center point, it just has to be on the line QPointF firstPoint, secondPoint; QPointF center; double angle; { QMutexLocker l(&wipeControlsMutex); center = wipeCenter; angle = wipeAngle; } ///extrapolate the line to the maximum size of the RoD so we're sure the line ///intersection algorithm works double maxSize = std::max(texRectClipped.x2 - texRectClipped.x1, texRectClipped.y2 - texRectClipped.y1) * 10000.; double xmax, ymax; xmax = std::cos(angle + M_PI_2) * maxSize; ymax = std::sin(angle + M_PI_2) * maxSize; firstPoint.setX(center.x() - xmax); firstPoint.setY(center.y() - ymax); secondPoint.setX(center.x() + xmax); secondPoint.setY(center.y() + ymax); QLineF inter(firstPoint, secondPoint); QLineF::IntersectType intersectionTypes[4]; QPointF intersections[4]; QLineF topEdge(texRectClipped.x1, texRectClipped.y2, texRectClipped.x2, texRectClipped.y2); QLineF rightEdge(texRectClipped.x2, texRectClipped.y2, texRectClipped.x2, texRectClipped.y1); QLineF bottomEdge(texRectClipped.x2, texRectClipped.y1, texRectClipped.x1, texRectClipped.y1); QLineF leftEdge(texRectClipped.x1, texRectClipped.y1, texRectClipped.x1, texRectClipped.y2); bool crossingTop = false, crossingRight = false, crossingLeft = false, crossingBtm = false; int validIntersectionsIndex[4]; validIntersectionsIndex[0] = validIntersectionsIndex[1] = -1; int numIntersec = 0; intersectionTypes[0] = inter.intersect(topEdge, &intersections[0]); if (intersectionTypes[0] == QLineF::BoundedIntersection) { validIntersectionsIndex[numIntersec] = 0; crossingTop = true; ++numIntersec; } intersectionTypes[1] = inter.intersect(rightEdge, &intersections[1]); if (intersectionTypes[1] == QLineF::BoundedIntersection) { validIntersectionsIndex[numIntersec] = 1; crossingRight = true; ++numIntersec; } intersectionTypes[2] = inter.intersect(bottomEdge, &intersections[2]); if (intersectionTypes[2] == QLineF::BoundedIntersection) { validIntersectionsIndex[numIntersec] = 2; crossingBtm = true; ++numIntersec; } intersectionTypes[3] = inter.intersect(leftEdge, &intersections[3]); if (intersectionTypes[3] == QLineF::BoundedIntersection) { validIntersectionsIndex[numIntersec] = 3; crossingLeft = true; ++numIntersec; } if ( (numIntersec != 0) && (numIntersec != 2) ) { ///Don't bother drawing the polygon, it is most certainly not visible in this case return ViewerGL::Implementation::eWipePolygonEmpty; } ///determine the orientation of the planes double crossProd = ( secondPoint.x() - center.x() ) * ( texRectClipped.y1 - center.y() ) - ( secondPoint.y() - center.y() ) * ( texRectClipped.x1 - center.x() ); if (numIntersec == 0) { ///the bottom left corner is on the left plane if ( (crossProd > 0) && ( (center.x() >= texRectClipped.x2) || (center.y() >= texRectClipped.y2) ) ) { ///the plane is invisible because the wipe handle is below or on the left of the texRectClipped return rightPlane ? ViewerGL::Implementation::eWipePolygonEmpty : ViewerGL::Implementation::eWipePolygonFull; } ///otherwise we draw the entire texture as usual return rightPlane ? ViewerGL::Implementation::eWipePolygonFull : ViewerGL::Implementation::eWipePolygonEmpty; } else { ///we have 2 intersects assert(validIntersectionsIndex[0] != -1 && validIntersectionsIndex[1] != -1); bool isBottomLeftOnLeftPlane = crossProd > 0; ///there are 6 cases if (crossingBtm && crossingLeft) { if ( (isBottomLeftOnLeftPlane && rightPlane) || (!isBottomLeftOnLeftPlane && !rightPlane) ) { //btm intersect is the first polygonPoints.insert(0, intersections[validIntersectionsIndex[0]]); polygonPoints.insert(1, intersections[validIntersectionsIndex[1]]); polygonPoints.insert( 2, QPointF(texRectClipped.x1, texRectClipped.y2) ); polygonPoints.insert( 3, QPointF(texRectClipped.x2, texRectClipped.y2) ); polygonPoints.insert( 4, QPointF(texRectClipped.x2, texRectClipped.y1) ); polygonPoints.insert(5, intersections[validIntersectionsIndex[0]]); } else { polygonPoints.insert(0, intersections[validIntersectionsIndex[0]]); polygonPoints.insert(1, intersections[validIntersectionsIndex[1]]); polygonPoints.insert( 2, QPointF(texRectClipped.x1, texRectClipped.y1) ); polygonPoints.insert(3, intersections[validIntersectionsIndex[0]]); } } else if (crossingBtm && crossingTop) { if ( (isBottomLeftOnLeftPlane && rightPlane) || (!isBottomLeftOnLeftPlane && !rightPlane) ) { ///btm intersect is the second polygonPoints.insert(0, intersections[validIntersectionsIndex[1]]); polygonPoints.insert(1, intersections[validIntersectionsIndex[0]]); polygonPoints.insert( 2, QPointF(texRectClipped.x2, texRectClipped.y2) ); polygonPoints.insert( 3, QPointF(texRectClipped.x2, texRectClipped.y1) ); polygonPoints.insert(4, intersections[validIntersectionsIndex[1]]); } else { polygonPoints.insert(0, intersections[validIntersectionsIndex[1]]); polygonPoints.insert(1, intersections[validIntersectionsIndex[0]]); polygonPoints.insert( 2, QPointF(texRectClipped.x1, texRectClipped.y2) ); polygonPoints.insert( 3, QPointF(texRectClipped.x1, texRectClipped.y1) ); polygonPoints.insert(4, intersections[validIntersectionsIndex[1]]); } } else if (crossingBtm && crossingRight) { if ( (isBottomLeftOnLeftPlane && rightPlane) || (!isBottomLeftOnLeftPlane && !rightPlane) ) { ///btm intersect is the second polygonPoints.insert(0, intersections[validIntersectionsIndex[1]]); polygonPoints.insert(1, intersections[validIntersectionsIndex[0]]); polygonPoints.insert( 2, QPointF(texRectClipped.x2, texRectClipped.y1) ); polygonPoints.insert(3, intersections[validIntersectionsIndex[1]]); } else { polygonPoints.insert(0, intersections[validIntersectionsIndex[1]]); polygonPoints.insert(1, intersections[validIntersectionsIndex[0]]); polygonPoints.insert( 2, QPointF(texRectClipped.x2, texRectClipped.y2) ); polygonPoints.insert( 3, QPointF(texRectClipped.x1, texRectClipped.y2) ); polygonPoints.insert( 4, QPointF(texRectClipped.x1, texRectClipped.y1) ); polygonPoints.insert(5, intersections[validIntersectionsIndex[1]]); } } else if (crossingLeft && crossingTop) { if ( (isBottomLeftOnLeftPlane && rightPlane) || (!isBottomLeftOnLeftPlane && !rightPlane) ) { ///left intersect is the second polygonPoints.insert(0, intersections[validIntersectionsIndex[1]]); polygonPoints.insert(1, intersections[validIntersectionsIndex[0]]); polygonPoints.insert( 2, QPointF(texRectClipped.x1, texRectClipped.y2) ); polygonPoints.insert(3, intersections[validIntersectionsIndex[1]]); } else { polygonPoints.insert(0, intersections[validIntersectionsIndex[1]]); polygonPoints.insert(1, intersections[validIntersectionsIndex[0]]); polygonPoints.insert( 2, QPointF(texRectClipped.x2, texRectClipped.y2) ); polygonPoints.insert( 3, QPointF(texRectClipped.x2, texRectClipped.y1) ); polygonPoints.insert( 4, QPointF(texRectClipped.x1, texRectClipped.y1) ); polygonPoints.insert(5, intersections[validIntersectionsIndex[1]]); } } else if (crossingLeft && crossingRight) { if ( (isBottomLeftOnLeftPlane && rightPlane) || (!isBottomLeftOnLeftPlane && !rightPlane) ) { ///left intersect is the second polygonPoints.insert(0, intersections[validIntersectionsIndex[1]]); polygonPoints.insert( 1, QPointF(texRectClipped.x1, texRectClipped.y2) ); polygonPoints.insert( 2, QPointF(texRectClipped.x2, texRectClipped.y2) ); polygonPoints.insert(3, intersections[validIntersectionsIndex[0]]); polygonPoints.insert(4, intersections[validIntersectionsIndex[1]]); } else { polygonPoints.insert(0, intersections[validIntersectionsIndex[1]]); polygonPoints.insert(1, intersections[validIntersectionsIndex[0]]); polygonPoints.insert( 2, QPointF(texRectClipped.x2, texRectClipped.y1) ); polygonPoints.insert( 3, QPointF(texRectClipped.x1, texRectClipped.y1) ); polygonPoints.insert(4, intersections[validIntersectionsIndex[1]]); } } else if (crossingTop && crossingRight) { if ( (isBottomLeftOnLeftPlane && rightPlane) || (!isBottomLeftOnLeftPlane && !rightPlane) ) { ///right is second polygonPoints.insert(0, intersections[validIntersectionsIndex[0]]); polygonPoints.insert( 1, QPointF(texRectClipped.x2, texRectClipped.y2) ); polygonPoints.insert(2, intersections[validIntersectionsIndex[1]]); polygonPoints.insert(3, intersections[validIntersectionsIndex[0]]); } else { polygonPoints.insert(0, intersections[validIntersectionsIndex[0]]); polygonPoints.insert(1, intersections[validIntersectionsIndex[1]]); polygonPoints.insert( 2, QPointF(texRectClipped.x2, texRectClipped.y1) ); polygonPoints.insert( 3, QPointF(texRectClipped.x1, texRectClipped.y1) ); polygonPoints.insert( 4, QPointF(texRectClipped.x1, texRectClipped.y2) ); polygonPoints.insert(5, intersections[validIntersectionsIndex[0]]); } } else { assert(false); } } return ViewerGL::Implementation::eWipePolygonPartial; } // getWipePolygon
void Interval::setLeftEdge(double left) { setEdges(left, rightEdge()); }
void Interval::move(double delta) { setEdges(leftEdge()+delta, rightEdge()+delta); }
bool Interval::intersects(Interval* that) { return (qMax(leftEdge(), that->leftEdge()) <= qMin(rightEdge(), that->rightEdge())); }
double Interval::center() { return (rightEdge() + leftEdge()) / 2.0; }
double Interval::width() { return rightEdge() - leftEdge(); }