Curve* EllipticalArc::portion(double f, double t) const { // fix input arguments if (f < 0) f = 0; if (f > 1) f = 1; if (t < 0) t = 0; if (t > 1) t = 1; if ( are_near(f, t) ) { EllipticalArc *arc = static_cast<EllipticalArc*>(duplicate()); arc->_center = arc->_initial_point = arc->_final_point = pointAt(f); arc->_start_angle = arc->_end_angle = _start_angle; arc->_rot_angle = _rot_angle; arc->_sweep = _sweep; arc->_large_arc = _large_arc; return arc; } EllipticalArc *arc = static_cast<EllipticalArc*>(duplicate()); arc->_initial_point = pointAt(f); arc->_final_point = pointAt(t); if ( f > t ) arc->_sweep = !_sweep; if ( _large_arc && fabs(sweepAngle() * (t-f)) < M_PI) arc->_large_arc = false; arc->_updateCenterAndAngles(arc->isSVGCompliant()); //TODO: be more clever return arc; }
int hdPolyLineFigure::findSegment (int posIdx, int x, int y) { for(int i = 0 ; i < points[posIdx]->count() - 1 ; i++) { hdPoint p1 = pointAt(posIdx, i); hdPoint p2 = pointAt(posIdx, i + 1); hdGeometry g; if(g.lineContainsPoint(p1.x, p1.y, p2.x, p2.y, x, y)) { return i + 1; } } return -1; }
// Returns the normal vector at t QLineF KCubicBezier::normalVectorAt(qreal t) const { const QPointF point = pointAt(t); const QPointF delta = deltaAt(t); return QLineF(point, point + delta).normalVector(); }
hdMultiPosRect &hdPolyLineFigure::getBasicDisplayBox() { basicDisplayBox.height = 0; basicDisplayBox.width = 0; int posIdx; //optimize this if needed in a future, because right now calculate displaybox for all posIdx hdIteratorBase *iterator; for(posIdx = 0; posIdx < basicDisplayBox.CountPositions(); posIdx++) { if(points[posIdx]->count() >= 1) { basicDisplayBox.SetPosition(posIdx, pointAt(posIdx, 0)); } else { basicDisplayBox.SetPosition(posIdx, wxPoint(0, 0)); } iterator = points[posIdx]->createIterator(); while(iterator->HasNext()) { hdPoint *p = (hdPoint *) iterator->Next(); hdRect r = hdRect(p->x, p->y, 0, 0); basicDisplayBox.add(posIdx, r); } delete iterator; } return basicDisplayBox; }
QgsPoint QgsCurve::vertexAt( QgsVertexId id ) const { QgsPoint v; QgsVertexId::VertexType type; pointAt( id.vertex, v, type ); return v; }
int TWarnLight::setAttribute (const string& rktNAME, NAttribute nVALUE, EAttribType eTYPE) { if ( rktNAME == "point_at" ) { if ( eTYPE == FX_VECTOR ) { pointAt (*((TVector*) nVALUE.pvValue)); } else { return FX_ATTRIB_WRONG_TYPE; } } else if ( rktNAME == "exponent" ) { if ( eTYPE == FX_REAL ) { setExponent (nVALUE.dValue); } else { return FX_ATTRIB_WRONG_TYPE; } } else { return TPointLight::setAttribute (rktNAME, nVALUE, eTYPE); } return FX_ATTRIB_OK; } /* setAttribute() */
static QVariant fcnYat( const QVariantList& values, QgsFeature* f, QgsExpression* parent ) { QVariant v = pointAt( values, f, parent ); if ( v.type() == QVariant::PointF ) return QVariant( v.toPointF().y() ); else return QVariant(); }
QgsPoint QgsCurve::childPoint( int index ) const { QgsPoint point; QgsVertexId::VertexType type; bool res = pointAt( index, point, type ); Q_ASSERT( res ); Q_UNUSED( res ); return point; }
inline void vStr(const char *kw, AzBytArr *s) { if (param == NULL) return; const char *bp = pointAfterKw(param, kw); if (bp == NULL) return; const char *ep = pointAt(bp, dlm); s->reset(); s->concat(bp, Az64::ptr_diff(ep-bp, "AzParam::vStr")); if (doCheck) sp_used_kw.put(kw); }
Curve *EllipticalArc::transformed(Affine const& m) const { Ellipse e(center(X), center(Y), ray(X), ray(Y), _rot_angle); Ellipse et = e.transformed(m); Point inner_point = pointAt(0.5); return et.arc( initialPoint() * m, inner_point * m, finalPoint() * m, isSVGCompliant() ); }
void hdPolyLineFigure::basicDraw(wxBufferedDC &context, hdDrawingView *view) { int posIdx = view->getIdx(); if(points[posIdx]->count() < 2) { return; } hdPoint start, end; if(startTerminal) { startTerminal->setLinePen(linePen); start = startTerminal->draw(context, getStartPoint(posIdx), pointAt(posIdx, 1), view); } else { start = getStartPoint(posIdx); } if(endTerminal) { endTerminal->setLinePen(linePen); end = endTerminal->draw(context, getEndPoint(posIdx), pointAt(posIdx, pointCount(posIdx) - 2), view); } else { end = getEndPoint(posIdx); } context.SetPen(linePen); for(int i = 0; i < points[posIdx]->count() - 1; i++) { hdPoint *p1 = (hdPoint *) points[posIdx]->getItemAt(i); hdPoint *p2 = (hdPoint *) points[posIdx]->getItemAt(i + 1); hdPoint copyP1 = hdPoint (*p1); view->CalcScrolledPosition(copyP1.x, copyP1.y, ©P1.x, ©P1.y); hdPoint copyP2 = hdPoint (*p2); view->CalcScrolledPosition(copyP2.x, copyP2.y, ©P2.x, ©P2.y); context.DrawLine(copyP1, copyP2); } }
qreal QBezier::tForY(qreal t0, qreal t1, qreal y) const { qreal py0 = pointAt(t0).y(); qreal py1 = pointAt(t1).y(); if (py0 > py1) { qSwap(py0, py1); qSwap(t0, t1); } Q_ASSERT(py0 <= py1); if (py0 >= y) return t0; else if (py1 <= y) return t1; Q_ASSERT(py0 < y && y < py1); qreal lt = t0; qreal dt; do { qreal t = qreal(0.5) * (t0 + t1); qreal a, b, c, d; QBezier::coefficients(t, a, b, c, d); qreal yt = a * y1 + b * y2 + c * y3 + d * y4; if (yt < y) { t0 = t; py0 = yt; } else { t1 = t; py1 = yt; } dt = lt - t; lt = t; } while (qAbs(dt) > qreal(1e-7)); return t0; }
bool hdPolyLineFigure::containsPoint (int posIdx, int x, int y) { hdRect rect = this->displayBox().gethdRect(posIdx); rect.Inflate(4, 4); if(!rect.Contains(x, y)) { return false; } for(int i = 0 ; i < points[posIdx]->count() - 1 ; i++) { hdPoint p1 = pointAt(posIdx, i); hdPoint p2 = pointAt(posIdx, i + 1); hdGeometry g; if(g.lineContainsPoint(p1.x, p1.y, p2.x, p2.y, x, y)) { return true; } } return false; }
bool QgsCurve::nextVertex( QgsVertexId &id, QgsPoint &vertex ) const { if ( id.vertex < 0 ) { id.vertex = 0; if ( id.part < 0 ) { id.part = 0; } if ( id.ring < 0 ) { id.ring = 0; } } else { if ( id.vertex + 1 >= numPoints() ) { return false; } ++id.vertex; } return pointAt( id.vertex, vertex, id.type ); }
QVector< Vector2f > Projector::groundPoly(SkyPoint* labelpoint, bool *drawLabel) const { KStarsData *data = KStarsData::Instance(); QVector<Vector2f> ground; static const QString horizonLabel = i18n("Horizon"); float marginLeft, marginRight, marginTop, marginBot; SkyLabeler::Instance()->getMargins( horizonLabel, &marginLeft, &marginRight, &marginTop, &marginBot ); //daz is 1/2 the width of the sky in degrees double daz = 90.; if ( m_vp.useAltAz ) { daz = 0.5*m_vp.width*57.3/m_vp.zoomFactor; //center to edge, in degrees if ( type() == SkyMap::Orthographic ) { daz = daz * 1.4; } daz = qMin(90.0, daz); } double faz = m_vp.focus->az().Degrees(); double az1 = faz -daz; double az2 = faz +daz; bool allGround = true; bool allSky = true; double inc = 1.0; //Add points along horizon for(double az = az1; az <= az2 + inc; az += inc) { SkyPoint p = pointAt(az,data); bool visible = false; Vector2f o = toScreenVec(&p, false, &visible); if( visible ) { ground.append( o ); //Set the label point if this point is onscreen if ( labelpoint && o.x() < marginRight && o.y() > marginTop && o.y() < marginBot ) *labelpoint = p; if ( o.y() > 0. ) allGround = false; if ( o.y() < m_vp.height ) allSky = false; } } if( allSky ) { if( drawLabel) *drawLabel = false; return QVector<Vector2f>(); } if( allGround ) { ground.clear(); ground.append( Vector2f( -10., -10. ) ); ground.append( Vector2f( m_vp.width +10., -10. ) ); ground.append( Vector2f( m_vp.width +10., m_vp.height +10. ) ); ground.append( Vector2f( -10., m_vp.height +10. ) ); if( drawLabel) *drawLabel = false; return ground; } //In Gnomonic projection, or if sufficiently zoomed in, we can complete //the ground polygon by simply adding offscreen points //FIXME: not just gnomonic if ( daz < 25.0 || type() == SkyMap::Gnomonic ) { ground.append( Vector2f( m_vp.width + 10.f, ground.last().y() ) ); ground.append( Vector2f( m_vp.width + 10.f, m_vp.height + 10.f ) ); ground.append( Vector2f( -10.f, m_vp.height + 10.f ) ); ground.append( Vector2f( -10.f, ground.first().y() ) ); } else { double r = m_vp.zoomFactor*radius(); double t1 = atan2( -1.*(ground.last().y() - 0.5*m_vp.height), ground.last().x() - 0.5*m_vp.width )/dms::DegToRad; double t2 = t1 - 180.; for ( double t=t1; t >= t2; t -= inc ) { //step along circumference dms a( t ); double sa(0.), ca(0.); a.SinCos( sa, ca ); ground.append( Vector2f( 0.5*m_vp.width + r*ca, 0.5*m_vp.height - r*sa) ); } } if( drawLabel) *drawLabel = true; return ground; }
bool UniformGrid::intersectsCell(const Model& model, const CellCoord& coord) { // Left side // Bottom left point Point3D p0 = pointAt(coord); Point3D p1(p0[0], p0[1] + cellSize, p0[2]); Point3D p2(p0[0], p0[1] + cellSize, p0[2] + cellSize); Point3D p3(p0[0], p0[1], p0[2] + cellSize); // Right side Point3D p4(p0[0] + cellSize, p0[1], p0[2]); Point3D p5(p0[0] + cellSize, p0[1] + cellSize, p0[2]); Point3D p6(p0[0] + cellSize, p0[1] + cellSize, p0[2] + cellSize); Point3D p7(p0[0] + cellSize, p0[1], p0[2] + cellSize); const std::vector<Point3D> pts = {p0, p1, p2, p3, p4, p5, p6, p7}; auto cellMat = translationMatrix(p0[0], p0[1], p0[2]) * cellSizeScaleMatrix; // But we need the inverse of course cellMat = cellMat.invert(); // Check if a pt is in the cell auto inCell = [&] (const Point3D& pt) -> bool { return p0[0] <= pt[0] && pt[0] <= (p0[0] + cellSize) && p0[1] <= pt[1] && pt[1] <= (p0[1] + cellSize) && p0[2] <= pt[2] && pt[2] <= (p0[2] + cellSize); }; // First, we need to get the 8 points of the bounding box auto bbox = model.getBoundingBox(); auto inBoundingBox = [&bbox] (const Point3D& pt) -> bool { // We are in the box if we are in between all the opposite parallel planes const auto c1 = bbox[0]; // Bottom back left corner const auto v1a = bbox[1] - c1; // Bottom back left to bottom back right const auto v1b = bbox[3] - c1; // Bottom back left to top back left const auto v1c = bbox[4] - c1; // Bottom back left to bottom front left const auto n1 = v1a.cross(v1b); // Back face const auto n2 = v1b.cross(v1c); // Left face const auto n3 = v1c.cross(v1a); // Bottom face const auto c2 = bbox[6]; // Top front right corner const auto v2a = bbox[5] - c2; // Top front right to bottom front right const auto v2b = bbox[7] - c2; // Top front right to top front left const auto v2c = bbox[2] - c2; // Top front right to top back right // We want this to be opposite sign (i.e. not pointing inwards) // so we do the opposite cross as above const auto n4 = v2b.cross(v2a); // Front face const auto n5 = v2c.cross(v2b); // Top face const auto n6 = v2a.cross(v2c); // Right face return betweenPlanes(n1, c1, n4, c2, pt) && betweenPlanes(n2, c1, n6, c2, pt) && betweenPlanes(n3, c1, n5, c2, pt); }; // A corner of the bbox being inside the cell implies an intersection // between the bbox and the cell. for (const auto& pt : bbox) { if (inCell(pt)) { return true; } } // Similarly, a corner of cell inside bbox implies intersection for (const auto& pt : pts) { if (inBoundingBox(pt)) { return true; } } // Check if any of the 12 lines from bbox intersect this cell HitRecord hr; for (size_t i = 0; i < 8; ++i) { // This is the vector of one edge Vector3D v = bbox[(i % 4 == 0) ? i + 3 : i - 1] - bbox[i]; Ray ray(bbox[i] - v, bbox[i]); if (utilityCube.intersects(ray, &hr, cellMat) && 1 <= hr.t && hr.t <= 2) { // This edge of the bounding box intersects our cell cube. return true; } } for (size_t i = 0; i < 4; ++i) { Vector3D v = bbox[i + 4] - bbox[i]; Ray ray(bbox[i] - v, bbox[i]); if (utilityCube.intersects(ray, &hr, cellMat) && 1 <= hr.t && hr.t <= 2) { // This edge of the bounding box intersects our cell cube. return true; } } // Now check if any of the 12 lines from this cell intersect the model for (size_t i = 0; i < pts.size(); ++i) { Vector3D v = pts[(i % 4 == 0) ? i + 3 : i - 1] - pts[i]; // Note: We are doing pts[i] - v and checking for t between 1 and 2. // This is equivalent to checking between 0 and 1 without doing the // subtraction, *but* we have an epsilon check in the intersects code. // For this case, we do *not* want to bother with epsilon check, so we // will check from 1 to 2 to avoid it. if (model.intersects(Ray(pts[i] - v, pts[i]), &hr)) { if (1 <= hr.t && hr.t <= 2) { return true; } } } // Now we have to check the struts between the two sides for (size_t i = 0; i < 4; ++i) { Vector3D v = pts[i + 4] - pts[i]; if (model.intersects(Ray(pts[i] - v, pts[i]), &hr)) { if (1 <= hr.t && hr.t <= 2) { return true; } } } return false; }
std::vector<double> EllipticalArc::allNearestPoints( Point const& p, double from, double to ) const { std::vector<double> result; if ( from > to ) std::swap(from, to); if ( from < 0 || to > 1 ) { THROW_RANGEERROR("[from,to] interval out of range"); } if ( ( are_near(ray(X), 0) && are_near(ray(Y), 0) ) || are_near(from, to) ) { result.push_back(from); return result; } else if ( are_near(ray(X), 0) || are_near(ray(Y), 0) ) { LineSegment seg(pointAt(from), pointAt(to)); Point np = seg.pointAt( seg.nearestPoint(p) ); if ( are_near(ray(Y), 0) ) { if ( are_near(_rot_angle, M_PI/2) || are_near(_rot_angle, 3*M_PI/2) ) { result = roots(np[Y], Y); } else { result = roots(np[X], X); } } else { if ( are_near(_rot_angle, M_PI/2) || are_near(_rot_angle, 3*M_PI/2) ) { result = roots(np[X], X); } else { result = roots(np[Y], Y); } } return result; } else if ( are_near(ray(X), ray(Y)) ) { Point r = p - center(); if ( are_near(r, Point(0,0)) ) { THROW_INFINITESOLUTIONS(0); } // TODO: implement case r != 0 // Point np = ray(X) * unit_vector(r); // std::vector<double> solX = roots(np[X],X); // std::vector<double> solY = roots(np[Y],Y); // double t; // if ( are_near(solX[0], solY[0]) || are_near(solX[0], solY[1])) // { // t = solX[0]; // } // else // { // t = solX[1]; // } // if ( !(t < from || t > to) ) // { // result.push_back(t); // } // else // { // // } } // solve the equation <D(E(t),t)|E(t)-p> == 0 // that provides min and max distance points // on the ellipse E wrt the point p // after the substitutions: // cos(t) = (1 - s^2) / (1 + s^2) // sin(t) = 2t / (1 + s^2) // where s = tan(t/2) // we get a 4th degree equation in s /* * ry s^4 ((-cy + py) Cos[Phi] + (cx - px) Sin[Phi]) + * ry ((cy - py) Cos[Phi] + (-cx + px) Sin[Phi]) + * 2 s^3 (rx^2 - ry^2 + (-cx + px) rx Cos[Phi] + (-cy + py) rx Sin[Phi]) + * 2 s (-rx^2 + ry^2 + (-cx + px) rx Cos[Phi] + (-cy + py) rx Sin[Phi]) */ Point p_c = p - center(); double rx2_ry2 = (ray(X) - ray(Y)) * (ray(X) + ray(Y)); double sinrot, cosrot; sincos(_rot_angle, sinrot, cosrot); double expr1 = ray(X) * (p_c[X] * cosrot + p_c[Y] * sinrot); Poly coeff; coeff.resize(5); coeff[4] = ray(Y) * ( p_c[Y] * cosrot - p_c[X] * sinrot ); coeff[3] = 2 * ( rx2_ry2 + expr1 ); coeff[2] = 0; coeff[1] = 2 * ( -rx2_ry2 + expr1 ); coeff[0] = -coeff[4]; // for ( unsigned int i = 0; i < 5; ++i ) // std::cerr << "c[" << i << "] = " << coeff[i] << std::endl; std::vector<double> real_sol; // gsl_poly_complex_solve raises an error // if the leading coefficient is zero if ( are_near(coeff[4], 0) ) { real_sol.push_back(0); if ( !are_near(coeff[3], 0) ) { double sq = -coeff[1] / coeff[3]; if ( sq > 0 ) { double s = std::sqrt(sq); real_sol.push_back(s); real_sol.push_back(-s); } } } else { real_sol = solve_reals(coeff); } for ( unsigned int i = 0; i < real_sol.size(); ++i ) { real_sol[i] = 2 * std::atan(real_sol[i]); if ( real_sol[i] < 0 ) real_sol[i] += 2*M_PI; } // when s -> Infinity then <D(E)|E-p> -> 0 iff coeff[4] == 0 // so we add M_PI to the solutions being lim arctan(s) = PI when s->Infinity if ( (real_sol.size() % 2) != 0 ) { real_sol.push_back(M_PI); } double mindistsq1 = std::numeric_limits<double>::max(); double mindistsq2 = std::numeric_limits<double>::max(); double dsq; unsigned int mi1, mi2; for ( unsigned int i = 0; i < real_sol.size(); ++i ) { dsq = distanceSq(p, pointAtAngle(real_sol[i])); if ( mindistsq1 > dsq ) { mindistsq2 = mindistsq1; mi2 = mi1; mindistsq1 = dsq; mi1 = i; } else if ( mindistsq2 > dsq ) { mindistsq2 = dsq; mi2 = i; } } double t = map_to_01( real_sol[mi1] ); if ( !(t < from || t > to) ) { result.push_back(t); } bool second_sol = false; t = map_to_01( real_sol[mi2] ); if ( real_sol.size() == 4 && !(t < from || t > to) ) { if ( result.empty() || are_near(mindistsq1, mindistsq2) ) { result.push_back(t); second_sol = true; } } // we need to test extreme points too double dsq1 = distanceSq(p, pointAt(from)); double dsq2 = distanceSq(p, pointAt(to)); if ( second_sol ) { if ( mindistsq2 > dsq1 ) { result.clear(); result.push_back(from); mindistsq2 = dsq1; } else if ( are_near(mindistsq2, dsq) ) { result.push_back(from); } if ( mindistsq2 > dsq2 ) { result.clear(); result.push_back(to); } else if ( are_near(mindistsq2, dsq2) ) { result.push_back(to); } } else { if ( result.empty() ) { if ( are_near(dsq1, dsq2) ) { result.push_back(from); result.push_back(to); } else if ( dsq2 > dsq1 ) { result.push_back(from); } else { result.push_back(to); } } } return result; }
std::set<const Model*> UniformGrid::getModels(const Ray& ray) const { std::set<const Model*> models; Point3D nextT(0, 0, 0); // The point *within* the grid where the ray first intersected it Point3D rayStartPoint(0, 0, 0); if (!inGrid(ray.start)) { const auto& sp = startPoint; // Not in the grid: We will use a cube the sz of whole grid to find // the point of entry into the grid auto gridCubeInverse = (translationMatrix(sp[0], sp[0], sp[0]) * gridSizeScaleMatrix).invert(); HitRecord hr; if (!utilityCube.intersects(ray, &hr, gridCubeInverse)) { // Does not intersect the grid even return models; } nextT[0] = hr.t; nextT[1] = hr.t; nextT[2] = hr.t; rayStartPoint = ray.at(hr.t); } else { rayStartPoint = ray.start; } // Place in the grid we are currently stepping through CellCoord gridCoord = coordAt(rayStartPoint); Vector3D dir( std::abs(ray.dir[0]), std::abs(ray.dir[1]), std::abs(ray.dir[2])); // These values are in units of t: how far we must go to travel a whole cell Vector3D dt( isZero(dir[0]) ? 0 : cellSize / dir[0], isZero(dir[1]) ? 0 : cellSize / dir[1], isZero(dir[2]) ? 0 : cellSize / dir[2] ); { // The bottom left corner of the cell we are starting in Point3D gsp = pointAt(gridCoord); // "Grid start point" // Determine how far, in units of t, we have to go in any direction // to reach the next cell // If we are going "forwards" in a coordinate then we need to travel to // gsp + cellSize. If we are going "backwards" in a coordinate then we need // to travel to only gsp. for (int i = 0; i < 3; ++i) { if (isZero(dir[i])) { nextT[i] = -1; continue; } if (ray.dir[i] < 0) { nextT[i] += (rayStartPoint[i] - gsp[i]) / dir[i]; } else { nextT[i] += (gsp[i] + cellSize - rayStartPoint[i]) / dir[i]; } } } // Which direction in the grid to move when we hit a "next" value CellCoord incs( (ray.dir[0] > 0) ? 1 : -1, (ray.dir[1] > 0) ? 1 : -1, (ray.dir[2] > 0) ? 1 : -1 ); // Check if a coord is still valid auto coordOk = [&] (int coord) -> bool { return 0 <= coord && coord < sideLength; }; auto smaller = [] (double a, double b) -> bool { return (b < 0) || a <= b; }; while (coordOk(gridCoord.x) && coordOk(gridCoord.y) && coordOk(gridCoord.z)) { for (const Model* model : cells[indexFor(gridCoord)].models) { models.insert(model); } for (int i = 0; i < 3; ++i) { if (nextT[i] < 0) continue; const auto a = nextT[(i + 1) % 3]; const auto b = nextT[(i + 2) % 3]; if (smaller(nextT[i], a) && smaller(nextT[i], b)) { nextT[i] += dt[i]; gridCoord[i] += incs[i]; break; } } } return models; }
QVector< Vector2f > EquirectangularProjector::groundPoly(SkyPoint* labelpoint, bool* drawLabel) const { float x0 = m_vp.width/2.; float y0 = m_vp.width/2.; if( m_vp.useAltAz ) { float dX = m_vp.zoomFactor*M_PI; float dY = m_vp.zoomFactor*M_PI; SkyPoint belowFocus; belowFocus.setAz( m_vp.focus->az().Degrees() ); belowFocus.setAlt( 0.0 ); Vector2f obf = toScreenVec( &belowFocus, false ); //If the horizon is off the bottom edge of the screen, //we can return immediately if ( obf.y() > m_vp.height ) { if( drawLabel ) *drawLabel = false; return QVector<Vector2f>(); } //We can also return if the horizon is off the top edge, //as long as the ground poly is not being drawn if ( obf.y() < 0. && m_vp.fillGround == false ) { if( drawLabel ) *drawLabel = false; return QVector<Vector2f>(); } QVector<Vector2f> ground; //Construct the ground polygon, which is a simple rectangle in this case ground << Vector2f( x0 - dX, obf.y() ) << Vector2f( x0 + dX, obf.y() ) << Vector2f( x0 + dX, y0 + dY ) << Vector2f( x0 - dX, y0 + dY ); if( labelpoint ) { QPointF pLabel( x0 -dX -50., obf.y() ); KStarsData *data = KStarsData::Instance(); *labelpoint = fromScreen(pLabel, data->lst(), data->geo()->lat()); } if( drawLabel ) *drawLabel = true; return ground; } else { float dX = m_vp.zoomFactor*M_PI/2; float dY = m_vp.zoomFactor*M_PI/2; QVector<Vector2f> ground; static const QString horizonLabel = i18n("Horizon"); float marginLeft, marginRight, marginTop, marginBot; SkyLabeler::Instance()->getMargins( horizonLabel, &marginLeft, &marginRight, &marginTop, &marginBot ); double daz = 90.; double faz = m_vp.focus->az().Degrees(); double az1 = faz -daz; double az2 = faz +daz; bool allGround = true; bool allSky = true; double inc = 1.0; //Add points along horizon for(double az = az1; az <= az2 + inc; az += inc) { SkyPoint p = pointAt(az); bool visible = false; Vector2f o = toScreenVec(&p, false, &visible); if( visible ) { ground.append( o ); //Set the label point if this point is onscreen if ( labelpoint && o.x() < marginRight && o.y() > marginTop && o.y() < marginBot ) *labelpoint = p; if ( o.y() > 0. ) allGround = false; if ( o.y() < m_vp.height ) allSky = false; } } if( allSky ) { if( drawLabel) *drawLabel = false; return QVector<Vector2f>(); } if( allGround ) { ground.clear(); ground.append( Vector2f( x0 - dX, y0 - dY ) ); ground.append( Vector2f( x0 + dX, y0 - dY ) ); ground.append( Vector2f( x0 + dX, y0 + dY ) ); ground.append( Vector2f( x0 - dX, y0 + dY ) ); if( drawLabel) *drawLabel = false; return ground; } if( labelpoint ) { QPointF pLabel( x0 -dX -50., ground.last().y() ); KStarsData *data = KStarsData::Instance(); *labelpoint = fromScreen(pLabel, data->lst(), data->geo()->lat()); } if( drawLabel ) *drawLabel = true; //Now add points along the ground ground.append( Vector2f( x0 + dX, ground.last().y() ) ); ground.append( Vector2f( x0 + dX, y0 + dY ) ); ground.append( Vector2f( x0 - dX, y0 + dY ) ); ground.append( Vector2f( x0 - dX, ground.first().y() ) ); return ground; } }