예제 #1
0
파일: stem.cpp 프로젝트: Fyrult/MuseScore
void Stem::layout()
      {
      qreal l    = _len + _userLen;
      qreal _up  = up() ? -1.0 : 1.0;
      l         *= _up;

      qreal y1 = 0.0;                           // vertical displacement to match note attach point
      Staff* stf = staff();
      if (chord()) {
            int tick = chord()->tick();
            StaffType* st = stf->staffType(tick);
            if (st->isTabStaff() ) {            // TAB staves
                  if (st->stemThrough()) {
                        // if stems through staves, gets Y pos. of stem-side note relative to chord other side
                        qreal lineDist = st->lineDistance().val() * spatium();
                        y1             = (chord()->downString() - chord()->upString()) * _up * lineDist;
                        // if fret marks above lines, raise stem beginning by 1/2 line distance
                        if (!st->onLines())
                              y1 -= lineDist * 0.5;
                        // shorten stem by 1/2 lineDist to clear the note and a little more to keep 'air' betwen stem and note
                        lineDist *= 0.7 * mag();
                        y1       += _up * lineDist;
                        }
                  // in other TAB types, no correction
                  }
            else {                              // non-TAB
                  // move stem start to note attach point
                  Note* n  = up() ? chord()->downNote() : chord()->upNote();
                  y1      += (up() ? n->stemUpSE().y() : n->stemDownNW().y());
                  rypos() = n->rypos();
                  }
            }

      qreal lw5 = _lineWidth * .5;

      line.setLine(0.0, y1, 0.0, l);

      // compute bounding rectangle
      QRectF r(line.p1(), line.p2());
      setbbox(r.normalized().adjusted(-lw5, -lw5, lw5, lw5));
      adjustReadPos();  // does not work if stem is layouted twice
      }
예제 #2
0
bool ON_Intersect( const ON_BoundingBox& bbox, 
                   const ON_Line& line, 
                   double tol,
                   ON_Interval* line_parameters)
{
  double a,b,d,mn,mx,s0,s1, t0, t1;
  const double M = 1.0e308;

  // i,j,k are indices of coordinates to trim.
  // trim the direction with the biggest line deltas first
  ON_3dVector v = line.Direction();
  const int i = v.MaximumCoordinateIndex();

  // gaurd against ON_UNSET_VALUE as input
  if ( !(tol >= 0.0) )
    tol = 0.0;

  // clip i-th coordinate
  a = line.from[i];
  b = line.to[i];
  mn = bbox.m_min[i];
  mx = bbox.m_max[i];
  if ( !(mn <= mx) )
    return false;
  mn -= (tol+a);
  mx += (tol-a);
  if ( !(mn <= mx) )
    return false;
  d = b-a;
  if ( 0.0 == d )
  {
    // happens when line.from == line.to
    if ( 0.0 < mn || 0.0 > mx )
    {
      // point is in box
      if ( line_parameters )
      {
        // setting parameters makes no sense - just use 0.0
        // so it's clear we have a point
        line_parameters->Set(0.0,0.0);
      }
      return true;
    }
    return false; // point is outside box
  }
  if ( fabs(d) < 1.0 && (fabs(mn) >= fabs(d)*M || fabs(mx) >= fabs(d)*M) )
  {
    // the value of mn/d or mx/d is too large for a realistic answer to be computed
    return false;
  }
  d = 1.0/d;
  t0 = mn*d;
  t1 = mx*d;

  // set "chord" = line segment that begins and ends on the
  // i-th coordinate box side planes.
  ON_Line chord(line.PointAt(t0),line.PointAt(t1));

  // test j-th coordinate direction
  const int j = (i + (fabs(v[(i+1)%3])>fabs(v[(i+2)%3])?1:2) ) % 3;
  a = chord.from[j];
  b = chord.to[j];
  mn = bbox.m_min[j];
  mx = bbox.m_max[j];
  if ( !(mn <= mx) )
    return false;
  mn -= (tol+a);
  mx += (tol-a);
  if ( !(mn <= mx) )
    return false;
  d = b-a;
  if ( (0.0 < mn && d < mn) || (0.0 > mx && d > mx) )
  {
    // chord lies outside the box
    return false;
  }

  while ( fabs(d) >= 1.0 || (fabs(mn) <= fabs(d)*M && fabs(mx) <= fabs(d)*M) )
  {
    // The chord is not (nearly) parallel to the j-th sides.
    // See if the chord needs to be trimmed by the j-th sides.
    d = 1.0/d;
    s0 = mn*d;
    s1 = mx*d;
    if ( s0 > 1.0 )
    {
      if ( s1 > 1.0 )
      {
        // unstable calculation happens when
        // fabs(d) is very tiny and chord is
        // on the j-th side.
        break;
      }
      s0 = 1.0;
    }
    else if ( s0 < 0.0 )
    {
      if (s1 < 0.0)
      {
        // unstable calculation happens when
        // fabs(d) is very tiny and chord is
        // on the j-th side.
        break;
      }
      s0 = 0.0;
    }
    if ( s1 < 0.0 ) s1 = 0.0; else if ( s1 > 1.0 ) s1 = 1.0;
    d = (1.0-s0)*t0 + s0*t1;
    t1 = (1.0-s1)*t0 + s1*t1;
    t0 = d;
    v = chord.PointAt(s0);
    chord.to = chord.PointAt(s1);
    chord.from = v;
    break;
  }
  
  // test k-th coordinate direction
  const int k = (i&&j) ? 0 : ((i!=1&&j!=1)?1:2);
  a = chord.from[k];
  b = chord.to[k];
  mn = bbox.m_min[k];
  mx = bbox.m_max[k];
  if ( !(mn <= mx) )
    return false;
  mn -= (tol+a);
  mx += (tol-a);
  if ( !(mn <= mx) )
    return false;
  d = b-a;
  if ( (0.0 < mn && d < mn) || (0.0 > mx && d > mx) )
  {
    // chord does not intersect the rectangle
    return false;
  }

  if ( line_parameters )
  {

    while ( fabs(d) >= 1.0 || (fabs(mn) <= fabs(d)*M && fabs(mx) <= fabs(d)*M) )
    {
      // The chord is not (nearly) parallel to the k-th sides.
      // See if the chord needs to be trimmed by the k-th sides.
      d = 1.0/d;
      s0 = mn*d;
      s1 = mx*d;
      if ( s0 > 1.0 )
      {
        if ( s1 > 1.0 )
        {
          // unstable calculation happens when
          // fabs(d) is very tiny and chord is
          // on the k-th side.
          break;
        }
        s0 = 1.0;
      }
      else if ( s0 < 0.0 )
      {
        if (s1 < 0.0)
        {
          // unstable calculation happens when
          // fabs(d) is very tiny and chord is
          // on the k-th side.
          break;
        }
        s0 = 0.0;
      }

      if ( s1 < 0.0 ) s1 = 0.0; else if ( s1 > 1.0 ) s1 = 1.0;
      d = (1.0-s0)*t0 + s0*t1;
      t1 = (1.0-s1)*t0 + s1*t1;
      t0 = d;
      break;
    }

    if (t0 > t1 )
    {
      line_parameters->Set(t1,t0);
    }
    else
    {
      line_parameters->Set(t0,t1);
    }
  }

  return true;
}
예제 #3
0
bool Stem::up() const
      {
      return chord() ? chord()->up() : true;
      }
예제 #4
0
void Stem::draw(QPainter* painter) const
      {
      // hide if second chord of a cross-measure pair
      if (chord() && chord()->crossMeasure() == CrossMeasure::SECOND)
            return;

      Staff* st = staff();
      bool useTab = st && st->isTabStaff();

      qreal lw = lineWidth();
      painter->setPen(QPen(curColor(), lw, Qt::SolidLine, Qt::RoundCap));
      painter->drawLine(line);

      if (!useTab || !chord())
            return;

      // TODO: adjust bounding rectangle in layout() for dots and for slash
      StaffType* stt = st->staffType();
      qreal sp = spatium();
      bool _up = up();

      // slashed half note stem
      if (chord()->durationType().type() == TDuration::DurationType::V_HALF && stt->minimStyle() == TablatureMinimStyle::SLASHED) {
            // position slashes onto stem
            qreal y = _up ? -(_len+_userLen) + STAFFTYPE_TAB_SLASH_2STARTY_UP*sp : (_len+_userLen) - STAFFTYPE_TAB_SLASH_2STARTY_DN*sp;
            // if stems through, try to align slashes within or across lines
            if (stt->stemThrough()) {
                  qreal halfLineDist = stt->lineDistance().val() * sp * 0.5;
                  qreal halfSlashHgt = STAFFTYPE_TAB_SLASH_2TOTHEIGHT * sp * 0.5;
                  y = lrint( (y + halfSlashHgt) / halfLineDist) * halfLineDist - halfSlashHgt;
                  }
            // draw slashes
            qreal hlfWdt= sp * STAFFTYPE_TAB_SLASH_WIDTH * 0.5;
            qreal sln   = sp * STAFFTYPE_TAB_SLASH_SLANTY;
            qreal thk   = sp * STAFFTYPE_TAB_SLASH_THICK;
            qreal displ = sp * STAFFTYPE_TAB_SLASH_DISPL;
            QPainterPath path;
            for (int i = 0; i < 2; ++i) {
                  path.moveTo( hlfWdt, y);            // top-right corner
                  path.lineTo( hlfWdt, y+thk);        // bottom-right corner
                  path.lineTo(-hlfWdt, y+thk+sln);    // bottom-left corner
                  path.lineTo(-hlfWdt, y+sln);        // top-left corner
                  path.closeSubpath();
                  y += displ;
                  }
            painter->setBrush(QBrush(curColor()));
            painter->setPen(Qt::NoPen);
            painter->drawPath(path);
            }

      // dots
      // NOT THE BEST PLACE FOR THIS?
      // with tablatures and stems beside staves, dots are not drawn near 'notes', but near stems
      int nDots = chord()->dots();
      if (nDots > 0 && !stt->stemThrough()) {
            qreal x     = chord()->dotPosX();
            qreal y     = ( (STAFFTYPE_TAB_DEFAULTSTEMLEN_DN * 0.2) * sp) * (_up ? -1.0 : 1.0);
            qreal step  = score()->styleS(StyleIdx::dotDotDistance).val() * sp;
            for (int dot = 0; dot < nDots; dot++, x += step)
                  drawSymbol(SymId::augmentationDot, painter, QPointF(x, y));
            }
      }
예제 #5
0
//==== Generate Fuse Component ====//
void PropGeom::generate()
{
	int i, j;

	//==== Copy Current Section Data into SectVec ====//
	sectVec[currSectID].chord     = chord();
	sectVec[currSectID].twist     = twist();
	sectVec[currSectID].x_off     = loc();
	sectVec[currSectID].y_off     = offset();

	Xsec_surf surf;
	surf.set_num_pnts( numPnts.iget() );
	surf.set_num_xsecs( sectVec.size()+2 );

	//==== Load Up Airfoil ====//
	for ( int ip = 0 ; ip < surf.get_num_pnts() ; ip++ )
		surf.set_pnt(0, ip, sectVec[0].foil->get_end_cap(ip) );	

	int numxs = sectVec.size();
	for ( i = 0 ; i < numxs ; i++ )
	{
		for ( j = 0 ; j < surf.get_num_pnts() ; j++ )
		{
			surf.set_pnt( i+1, j, sectVec[i].foil->get_pnt(j) );
		}
	}
	for ( int ip = 0 ; ip < surf.get_num_pnts() ; ip++ )
		surf.set_pnt(numxs+1, ip, sectVec[numxs-1].foil->get_end_cap(ip) );	

	//==== Build Up One Blade ====//
	double rad = diameter()/2.0;
	for ( i = 0 ; i < surf.get_num_xsecs() ; i++ )
	{
		int sid = i;

		if ( i > 0 ) sid = i-1;

		if ( i > (int)sectVec.size()-1 ) sid = (int)sectVec.size()-1;

		Section* sPtr = &(sectVec[sid]);
		surf.scale_xsec_x(  i, sPtr->chord()*rad );
		surf.scale_xsec_z(  i, sPtr->chord()*rad );
		surf.offset_xsec_x( i, -0.5*(sPtr->chord()*rad) );
		surf.rotate_xsec_y( i, 90.0 );
		surf.rotate_xsec_y( i, -sPtr->twist() - pitch() );
		surf.offset_xsec_y( i, sPtr->x_off()*rad );
		surf.offset_xsec_z( i, -sPtr->y_off()*rad );
	}

	//==== Set Flags So Trailing Edge Remains Sharp ====//
	surf.set_pnt_tan_flag( 0, Bezier_curve::SHARP );
	surf.set_pnt_tan_flag( 1, Bezier_curve::SHARP );
    int num_pnts  = surf.get_num_pnts();
	surf.set_pnt_tan_flag( num_pnts-1, Bezier_curve::SHARP );

	if ( !smoothFlag )
	{
		for ( i = 0 ; i < surf.get_num_xsecs() ; i++ )
		{
			surf.set_xsec_tan_flag( i, Bezier_curve::SHARP );
		}
	}
	else	// Sharpen End Caps
	{
		surf.set_xsec_tan_flag( surf.get_num_xsecs()-2, Bezier_curve::SHARP );
	}


	bezier_surf besurf;
	surf.load_bezier_surface( &besurf );
	int umax = besurf.get_u_max();
	int wmax = besurf.get_w_max();

	Xsec_surf smooth_surf;
	smooth_surf.set_num_pnts( (surf.get_num_pnts()-1)*numW + 1 );
	smooth_surf.set_num_xsecs( (surf.get_num_xsecs()-1)*numU + 1 );

	for ( i = 0 ; i < smooth_surf.get_num_xsecs() ; i++ )
	{
		double fu = (double)i/(double)(smooth_surf.get_num_xsecs()-1);
		double u  = fu*(double)umax;
		for ( j = 0 ; j < smooth_surf.get_num_pnts() ; j++ )
		{
			double fw = (double)j/(double)(smooth_surf.get_num_pnts()-1);
			double w  = fw*(double)wmax;
			vec3d p = besurf.comp_pnt( u, w );
			smooth_surf.set_pnt( i, j, p );
		}
	}

	//==== Load Blades into bladeVec ====//
	for ( int nb = 0 ; nb < (int)bladeVec.size() ; nb++ )
	{
		bladeVec[nb].set_num_pnts( smooth_surf.get_num_pnts() );
		bladeVec[nb].set_num_xsecs(  smooth_surf.get_num_xsecs() );

		//==== Load Points ====//
		for ( i = 0 ; i < smooth_surf.get_num_xsecs() ; i++ )
			for ( j = 0 ; j < smooth_surf.get_num_pnts() ; j++ )
				bladeVec[nb].set_pnt( i, j, smooth_surf.get_pnt( i, j ) );

		double xang = 360.0*(double)nb/(double)(bladeVec.size());

		for ( i = 0 ; i < bladeVec[nb].get_num_xsecs() ; i++ )
		{
			bladeVec[nb].rotate_xsec_z( i, cone_angle() );
			bladeVec[nb].rotate_xsec_x( i, xang );
		}
		bladeVec[nb].load_refl_pnts_xsecs();
		bladeVec[nb].load_hidden_surf();
		bladeVec[nb].load_normals();
		bladeVec[nb].load_uw();

	}

	for ( int i = 0 ; i < (int)sectVec.size() ; i++ )
		sectVec[i].SetGeomPtr( this );

	update_bbox();


}
예제 #6
0
void ChordLine::layout()
      {
      if (!modified) {
            qreal x2 = 0;
            qreal y2 = 0;
            switch(_chordLineType) {
                  case ChordLineType::NOTYPE:
                        break;
                  case ChordLineType::FALL:
                        x2 = _initialLength;
                        y2 = _initialLength;
                        break;
                  case ChordLineType::PLOP:
                        x2 = -_initialLength;
                        y2 = -_initialLength;
                        break;
                  case ChordLineType::SCOOP:
                        x2 = -_initialLength;
                        y2 = _initialLength;
                        break;
                  default:
                  case ChordLineType::DOIT:
                        x2 = _initialLength;
                        y2 = -_initialLength;
                        break;
                  }
            if (_chordLineType != ChordLineType::NOTYPE) {
                  path = QPainterPath();
                  // chordlines to the right of the note
                  if (_chordLineType == ChordLineType::FALL || _chordLineType == ChordLineType::DOIT) {
                        if (_straight)
                              path.lineTo(x2, y2);
                        else
                              path.cubicTo(x2/2, 0.0, x2, y2/2, x2, y2);
                        }
                  // chordlines to the left of the note
                  else if (_chordLineType == ChordLineType::PLOP || _chordLineType == ChordLineType::SCOOP) {
                        if (_straight)
                              path.lineTo(x2, y2);
                        else
                              path.cubicTo(0.0, y2/2, x2/2, y2, x2, y2);
                        }
                  }
            }

      qreal _spatium = spatium();
      if (parent()) {
            Note* note = chord()->upNote();
            QPointF p(note->pos());
            // chordlines to the right of the note
            if (_chordLineType == ChordLineType::FALL || _chordLineType == ChordLineType::DOIT)
                  setPos(p.x() + note->headWidth() + _spatium * .2, p.y());
            // chordlines to the left of the note
            if (_chordLineType == ChordLineType::PLOP)
                  setPos(p.x() + note->headWidth() * .25, p.y() - note->headHeight() * .75);
            if (_chordLineType == ChordLineType::SCOOP) {
                  qreal x = p.x() + (chord()->up() ? note->headWidth() * .25 : _spatium * -.2);
                  setPos(x, p.y() + note->headHeight() * .75);
                  }
            }
      else
            setPos(0.0, 0.0);
      QRectF r(path.boundingRect());
      int x1, y1, width, height = 0;

      x1 = r.x() * _spatium;
      y1 = r.y() * _spatium;
      width = r.width() * _spatium;
      height = r.height() * _spatium;
      bbox().setRect(x1, y1, width, height);
      }
예제 #7
0
void LedgerLine::draw(QPainter* painter) const
      {
      if(chord()->crossMeasure() == CrossMeasure::SECOND)
            return;
      Line::draw(painter);
      }
예제 #8
0
QPointF LedgerLine::pagePos() const
      {
      System* system = chord()->measure()->system();
      qreal yp = y() + system->staff(staffIdx())->y() + system->y();
      return QPointF(pageX(), yp);
      }