示例#1
0
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;
}
示例#2
0
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;
}
示例#3
0
// 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();
}
示例#4
0
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;
}
示例#5
0
QgsPoint QgsCurve::vertexAt( QgsVertexId id ) const
{
  QgsPoint v;
  QgsVertexId::VertexType type;
  pointAt( id.vertex, v, type );
  return v;
}
示例#6
0
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() */
示例#7
0
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();
}
示例#8
0
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;
}
示例#9
0
 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); 
 }
示例#10
0
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() );
}
示例#11
0
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, &copyP1.x, &copyP1.y);
		hdPoint copyP2 = hdPoint (*p2);
		view->CalcScrolledPosition(copyP2.x, copyP2.y, &copyP2.x, &copyP2.y);

		context.DrawLine(copyP1, copyP2);
	}
}
示例#12
0
文件: qbezier.cpp 项目: Afreeca/qt
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;
}
示例#13
0
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;
}
示例#14
0
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 );
}
示例#15
0
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;
}
示例#16
0
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;
}
示例#17
0
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;
}
示例#18
0
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;
}
示例#19
0
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;
    }
}