Beispiel #1
0
void Console::outputAll(Core &core)
{
	cout << "OBJECTS:" << endl;
	if (core.sizeListObj() == 0)
		cout << "	No objects yet." << endl;
	for (size_t i = 0; i < core.sizeListObj(); ++i) {
		Point * newp = 0; Circle *newc = 0; Segment * news = 0;
		switch (core.searchID(core.getObjIDs()[i])->object_type()) {
		case IsPoint: {
			newp = dynamic_cast<Point*>(core.searchID(core.getObjIDs()[i]));
			cout.precision(2);
			cout << setw(8);
			newp->isFixed() ? cout << "(fixed) " : cout << "";
			cout << setw(8) << "POINT ";
			cout << setw(3) << "ID: " << setw(2) << newp->showId();
			cout << setw(6) << "X: " << setw(8) << newp->getX();
			cout << setw(6) << "Y: " << setw(8) << newp->getY();
			newp->isPicked() ? cout << "  <-" : cout << "";
			cout << endl;
		} break;
		case IsSegment: {
			news = dynamic_cast<Segment*>(core.searchID(core.getObjIDs()[i]));
			cout.precision(2);
			cout << setw(8);
			news->isFixed() ? cout << "(fixed) " : cout << "";
			cout << setw(8) << "SEGMENT ";
			cout << setw(3) << "ID: " << setw(2) << news->showId();
			cout << setw(6) << news->getP1()->showId();
			cout << "-----" << news->getP2()->showId();
			news->isPicked() ? cout << setw(16) << "<-" : cout << "";
			cout << endl << endl;
		} break;
		case IsCircle: {
			newc = dynamic_cast<Circle*>(core.searchID(core.getObjIDs()[i]));
			cout.precision(2);
			cout << setw(8);
			Point t = newc->getCenter();
			newc->isFixed() ? cout << "(fixed) " : cout << "";
			cout << setw(8) << "CIRCLE ";
			cout << setw(3) << "ID: " << setw(2) << newc->showId();
			cout << setw(6) << "O: " << setw(8) << newc->getCenter().showId();
			cout << setw(6) << "R: " << setw(8) << newc->getRadius();
			newc->isPicked() ? cout << "  <-" : cout << "";
			cout << endl << endl;
		} break;
		}
	}
	cout << "RESTRICTIONS:" << endl;
	if (core.sizeListRestr() == 0)
		cout << "	No restrictions yet." << endl;
	for (size_t i = 0; i < core.sizeListRestr(); ++i) {
		switch (core.searchIDRestr(core.getRestrIDs()[i])->get_type()) {

		case RT_P2PDIST: {
			auto restr = dynamic_cast<RestrP2PDIST*>(core.searchIDRestr(core.getRestrIDs()[i]));
			cout.precision(2);
			cout << setw(16) << "P2PDIST " << setw(3) << "ID: " << setw(2) << restr->showId();
			cout << setw(13) << "violation: " << setw(8) << restr->violation();
			cout << setw(8) << restr->getP1()->showId() << "---" << restr->getP2()->showId() << endl;
		} break;
		case RT_P2SDIST: {
			auto restr = dynamic_cast<RestrP2SDIST*>(core.searchIDRestr(core.getRestrIDs()[i]));
			cout.precision(2);
			cout << setw(16) << "P2SDIST " << setw(3) << "ID: " << setw(2) << restr->showId();
			cout << setw(13) << "violation: " << setw(8) << restr->violation();
			cout << setw(8) << restr->getP1()->showId() << "---" << restr->getP2()->showId();
			cout << "==" << restr->getP3()->showId() << endl;
		} break;
		case RT_P2SDISTEX: {
			auto restr = dynamic_cast<RestrP2SDISTEX*>(core.searchIDRestr(core.getRestrIDs()[i]));
			cout.precision(2);
			cout << setw(16) << "P2SDISTEX " << setw(3) << "ID: " << setw(2) << restr->showId();
			cout << setw(13) << "violation: " << setw(8) << restr->violation();
			cout << setw(8) << restr->getP1()->showId() << "---" << restr->getP2()->showId();
			cout << "==" << restr->getP3()->showId() << endl;
		} break;
		case RT_S2SANGLE: {
			auto restr = dynamic_cast<RestrS2SANGLE*>(core.searchIDRestr(core.getRestrIDs()[i]));
			cout.precision(2);
			cout << setw(16) << "S2SANGLE " << setw(3) << "ID: " << setw(2) << restr->showId();
			cout << setw(13) << "violation: " << setw(8) << restr->violation();
			cout << setw(8) << restr->getS1()->showId() << "---" << restr->getS2()->showId() << endl;
		} break;
		case RT_S2SORTHO: {
			auto restr = dynamic_cast<RestrS2SORTHO*>(core.searchIDRestr(core.getRestrIDs()[i]));
			cout.precision(2);
			cout << setw(16) << "S2SORTHO " << setw(3) << "ID: " << setw(2) << restr->showId();
			cout << setw(13) << "violation: " << setw(8) << restr->violation();
			cout << setw(8) << restr->getS1()->showId() << "---" << restr->getS2()->showId() << endl;
		} break;
		case RT_S2SPARAL: {
			auto restr = dynamic_cast<RestrS2SPARAL*>(core.searchIDRestr(core.getRestrIDs()[i]));
			cout.precision(2);
			cout << setw(16) << "S2SPARAL " << setw(3) << "ID: " << setw(2) << restr->showId();
			cout << setw(13) << "violation: " << setw(8) << restr->violation();
			cout << setw(8) << restr->getS1()->showId() << "---" << restr->getS2()->showId() << endl;
		} break;
		case RT_S2SEQUALS: {
			auto restr = dynamic_cast<RestrS2SEQUALS*>(core.searchIDRestr(core.getRestrIDs()[i]));
			cout.precision(2);
			cout << setw(16) << "S2SEQUALS " << setw(3) << "ID: " << setw(2) << restr->showId();
			cout << setw(13) << "violation: " << setw(8) << restr->violation();
			cout << setw(8) << restr->getS1()->showId() << "---" << restr->getS2()->showId() << endl;
		} break;
		}
	}
	core.ShowRestr();
}
Beispiel #2
0
Boolean ADUFromMP3Source::doGetNextFrame1() {
  // First, check whether we have enough previously-read data to output an
  // ADU for the last-read MP3 frame:
  unsigned tailIndex;
  Segment* tailSeg;
  Boolean needMoreData;

  if (fSegments->isEmpty()) {
    needMoreData = True;
    tailSeg = NULL; tailIndex = 0; // unneeded, but stops compiler warnings
  } else {
    tailIndex = SegmentQueue::prevIndex(fSegments->nextFreeIndex());
    tailSeg = &(fSegments->s[tailIndex]);

    needMoreData
	  = fTotalDataSizeBeforePreviousRead < tailSeg->backpointer // bp points back too far
      || tailSeg->backpointer + tailSeg->dataHere() < tailSeg->aduSize; // not enough data
  }

  if (needMoreData) {
    // We don't have enough data to output an ADU from the last-read MP3
    // frame, so need to read another one and try again:
    doGetNextFrame();
    return True;
  }

  // Output an ADU from the tail segment:
  fFrameSize = tailSeg->headerSize+tailSeg->sideInfoSize+tailSeg->aduSize;
  fPresentationTime = tailSeg->presentationTime;
  fDurationInMicroseconds = tailSeg->durationInMicroseconds;
  unsigned descriptorSize
    = fIncludeADUdescriptors ? ADUdescriptor::computeSize(fFrameSize) : 0;
#ifdef DEBUG
  fprintf(stderr, "m->a:outputting ADU %d<-%d, nbr:%d, sis:%d, dh:%d, (descriptor size: %d)\n", tailSeg->aduSize, tailSeg->backpointer, fFrameSize, tailSeg->sideInfoSize, tailSeg->dataHere(), descriptorSize);
#endif
  if (descriptorSize + fFrameSize > fMaxSize) {
    envir() << "ADUFromMP3Source::doGetNextFrame1(): not enough room ("
	    << descriptorSize + fFrameSize << ">"
	    << fMaxSize << ")\n";
    fFrameSize = 0;
    return False;
  }

  unsigned char* toPtr = fTo;
  // output the ADU descriptor:
  if (fIncludeADUdescriptors) {
    fFrameSize += ADUdescriptor::generateDescriptor(toPtr, fFrameSize);
  }

  // output header and side info:
  memmove(toPtr, tailSeg->dataStart(),
	  tailSeg->headerSize + tailSeg->sideInfoSize);
  toPtr += tailSeg->headerSize + tailSeg->sideInfoSize;

  // go back to the frame that contains the start of our data:
  unsigned offset = 0;
  unsigned i = tailIndex;
  unsigned prevBytes = tailSeg->backpointer;
  while (prevBytes > 0) {
    i = SegmentQueue::prevIndex(i);
    unsigned dataHere = fSegments->s[i].dataHere();
    if (dataHere < prevBytes) {
      prevBytes -= dataHere;
    } else {
      offset = dataHere - prevBytes;
      break;
    }
  }

  // dequeue any segments that we no longer need:
  while (fSegments->headIndex() != i) {
    fSegments->dequeue(); // we're done with it
  }

  unsigned bytesToUse = tailSeg->aduSize;
  while (bytesToUse > 0) {
    Segment& seg = fSegments->s[i];
    unsigned char* fromPtr
      = &seg.dataStart()[seg.headerSize + seg.sideInfoSize + offset];
    unsigned dataHere = seg.dataHere() - offset;
    unsigned bytesUsedHere = dataHere < bytesToUse ? dataHere : bytesToUse;
    memmove(toPtr, fromPtr, bytesUsedHere);
    bytesToUse -= bytesUsedHere;
    toPtr += bytesUsedHere;
    offset = 0;
    i = SegmentQueue::nextIndex(i);
  }


  if (fFrameCounter++%fScale == 0) {
    // Call our own 'after getting' function.  Because we're not a 'leaf'
    // source, we can call this directly, without risking infinite recursion.
    afterGetting(this);
  } else {
    // Don't use this frame; get another one:
    doGetNextFrame();
  }

  return True;
}
/**
 *  @brief 点と線分の距離
 *  @param[in] a  判定する点
 *  @param[in] b  判定する線分
 *  @return    点aと線分bの距離
 */
inline double distance(const Point &a, const Segment &b){
	const Point p = b.to_line().projection(a);
	if(intersect(b, p)){ return (a - p).abs(); }
	return std::min((b.a - a).abs(), (b.b - a).abs());
}
Segment *
SegmentJoinCommand::makeSegment(SegmentVec oldSegments)
{
    // We can proceed even if composition is NULL, just normalize
    // rests will do less.
    Composition *composition = oldSegments[0]->getComposition();

    // Find the leftmost segment's index and the rightmost segment's
    // index.
    timeT t0 = oldSegments[0]->getStartTime();
    timeT t1 = oldSegments[0]->getEndMarkerTime();
    size_t leftmostIndex = 0;
    size_t rightmostIndex = 0;
    for (size_t i = 1; i < oldSegments.size(); ++i) {
        timeT startTime = oldSegments[i]->getStartTime();
        if (startTime < t0) {
            t0 = startTime;
            leftmostIndex = i;
        }
        timeT endMarkerTime = oldSegments[i]->getEndMarkerTime();
        if (endMarkerTime > t1) {
            t1 = endMarkerTime;
            rightmostIndex = i;
        }
    }

    // Always begin with the leftmost segment to keep in the new segment
    // any clef or key change found at the start of this segment.
    Segment *newSegment = oldSegments[leftmostIndex]->clone(false);

    // drop any events beyond the end marker
    newSegment->setEndTime(newSegment->getEndMarkerTime());

    // that duplicated the leftmost segment; now do the rest

    // we normalize rests in any overlapping areas
    timeT overlapStart = 0, overlapEnd = 0;
    bool haveOverlap = false;
    for (size_t i = 0; i < oldSegments.size(); ++i) {

        // Don't add twice the first old segment
        if (i == leftmostIndex) continue;

        Segment *s = oldSegments[i];

        timeT start = s->getStartTime(), end = s->getEndMarkerTime();

        timeT os = 0, oe = 0;
        bool haveOverlapHere = false;

        if (start < newSegment->getEndMarkerTime() &&
            end > newSegment->getStartTime()) {
            haveOverlapHere = true;
            os = std::max(start, newSegment->getStartTime());
            oe = std::min(end, newSegment->getEndMarkerTime());
            RG_DEBUG << "overlap here, os = " << os << ", oe = " << oe;
        }

        if (haveOverlapHere) {
            if (haveOverlap) {
                overlapStart = std::min(overlapStart, os);
                overlapEnd = std::max(overlapEnd, oe);
            } else {
                overlapStart = os;
                overlapEnd = oe;
                haveOverlap = true;
            }
        }

        if (start > newSegment->getEndMarkerTime()) {
            newSegment->setEndMarkerTime(start);
        }

        for (Segment::iterator si = s->begin(); ; ++si) {

            // If we're in the rightmost segment
            if (i == rightmostIndex) {
                // Copy all of the events to the end
                if (si == s->end())
                    break;
            } else {
                // Just copy up to the End Marker of this segment.
                if (!s->isBeforeEndMarker(si))
                    break;
            }

            // weed out duplicate clefs and keys

            if ((*si)->isa(Clef::EventType)) {
                try {
                    Clef newClef(**si);
                    if (newSegment->getClefAtTime
                        ((*si)->getAbsoluteTime() + 1) == newClef) {
                        continue;
                    }
                } catch (...) { }
            }

            if ((*si)->isa(Key::EventType)) {
                try {
                    Key newKey(**si);
                    if (newSegment->getKeyAtTime
                        ((*si)->getAbsoluteTime() + 1) == newKey) {
                        continue;
                    }
                } catch (...) { }
            }

            newSegment->insert(new Event(**si));
        }

        if (end > newSegment->getEndMarkerTime()) {
            newSegment->setEndMarkerTime(end);
        }
    }

    if (haveOverlap) {
        /// normalizeRests doesn't require Composition, but is less
        /// than ideal without it;
        newSegment->setComposition(composition);
        newSegment->normalizeRests(overlapStart, overlapEnd);
        newSegment->setComposition(0);        
    }

    return newSegment;
}
Beispiel #5
0
QPointF Pedal::linePos(Grip grip, System** sys) const
      {
      qreal x = 0.0;
      qreal nhw = score()->noteHeadWidth();
      System* s = nullptr;
      if (grip == Grip::START) {
            ChordRest* c = toChordRest(startElement());
            if (c) {
                  s = c->segment()->system();
                  x = c->pos().x() + c->segment()->pos().x() + c->segment()->measure()->pos().x();
                  if (c->type() == ElementType::REST && c->durationType() == TDuration::DurationType::V_MEASURE)
                        x -= c->x();
                  if (beginHookType() == HookType::HOOK_45)
                        x += nhw * .5;
                  }
            }
      else {
            Element* e = endElement();
            ChordRest* c = toChordRest(endElement());
            if (!e || e == startElement() || (endHookType() == HookType::HOOK_90)) {
                  // pedal marking on single note or ends with non-angled hook:
                  // extend to next note or end of measure
                  Segment* seg = nullptr;
                  if (!e)
                        seg = startSegment();
                  else
                        seg = c->segment();
                  if (seg) {
                        seg = seg->next();
                        for ( ; seg; seg = seg->next()) {
                              if (seg->segmentType() == SegmentType::ChordRest) {
                                    // look for a chord/rest in any voice on this staff
                                    bool crFound = false;
                                    int track = staffIdx() * VOICES;
                                    for (int i = 0; i < VOICES; ++i) {
                                          if (seg->element(track + i)) {
                                                crFound = true;
                                                break;
                                                }
                                          }
                                    if (crFound)
                                          break;
                                    }
                              else if (seg->segmentType() == SegmentType::EndBarLine) {
                                    break;
                                    }
                              }
                        }
                  if (seg) {
                        s = seg->system();
                        x = seg->pos().x() + seg->measure()->pos().x() - nhw * 2;
                        }
                  }
            else if (c) {
                  s = c->segment()->system();
                  x = c->pos().x() + c->segment()->pos().x() + c->segment()->measure()->pos().x();
                  if (c->type() == ElementType::REST && c->durationType() == TDuration::DurationType::V_MEASURE)
                        x -= c->x();
                  }
            if (!s) {
                  int t = tick2();
                  Measure* m = score()->tick2measure(t);
                  s = m->system();
                  x = m->tick2pos(t);
                  }
            if (endHookType() == HookType::HOOK_45)
                  x += nhw * .5;
            else
                  x += nhw;
            }

      *sys = s;
      return QPointF(x, 0);
      }
WindowingResult WindowEvaluator::eval_pt_to_seg(Point origin, Segment target) {
    auto end = target.delta().magsq();

    // if target is a zero-length segment, there are no windows
    if (end == 0) return make_pair(vector<Window>{}, boost::none);

    if (debug) {
        system->drawLine(target, QColor{"Blue"}, "Debug");
    }

    vector<Window> windows = {Window{0, end}};

    // apply the obstacles

    vector<Robot*> bots(system->self.size() + system->opp.size());

    auto filter_predicate = [&](const Robot* bot) -> bool {
        return bot != nullptr && bot->visible &&
               find(excluded_robots.begin(), excluded_robots.end(), bot) ==
                   excluded_robots.end();
    };

    auto end_it = copy_if(system->self.begin(), system->self.end(),
                          bots.begin(), filter_predicate);

    end_it = copy_if(system->opp.begin(), system->opp.end(), end_it,
                     filter_predicate);

    bots.resize(distance(bots.begin(), end_it));

    vector<Point> bot_locations;
    for_each(bots.begin(), bots.end(), [&bot_locations](Robot* bot) {
        bot_locations.push_back(bot->pos);
    });

    bot_locations.insert(bot_locations.end(),
                         hypothetical_robot_locations.begin(),
                         hypothetical_robot_locations.end());

    for (auto& pos : bot_locations) {
        auto d = (pos - origin).mag();
        // whether or not we can ship over this bot
        auto chip_overable = chip_enabled &&
                             (d < max_chip_range - Robot_Radius) &&
                             (d > min_chip_range + Robot_Radius);
        if (!chip_overable) {
            obstacle_robot(windows, origin, target, pos);
        }
    }

    auto p0 = target.pt[0];
    auto delta = target.delta() / end;

    for (auto& w : windows) {
        w.segment = Segment{p0 + delta * w.t0, p0 + delta * w.t1};
        w.a0 = RadiansToDegrees((w.segment.pt[0] - origin).angle());
        w.a1 = RadiansToDegrees((w.segment.pt[1] - origin).angle());
        fill_shot_success(w, origin);
    }

    boost::optional<Window> best{
        !windows.empty(), *max_element(windows.begin(), windows.end(),
                                       [](Window& a, Window& b) -> bool {
                                           return a.segment.delta().magsq() <
                                                  b.segment.delta().magsq();
                                       })};
    if (debug) {
        if (best) {
            system->drawLine(Segment{origin, best->segment.center()},
                             QColor{"Green"}, "Debug");
        }
        for (Window& window : windows) {
            system->drawLine(window.segment, QColor{"Green"}, "Debug");
            system->drawText(QString::number(window.shot_success),
                             window.segment.center() + Point(0, 0.1),
                             QColor{"Green"}, "Debug");
        }
    }

    return make_pair(windows, best);
}
int main()
{
	int start_s =0, stop_s =0, test_start= 0, test_stop =0;
	dataManipulator dm;
	Segment segData;
	start_s = clock();
	cout << "***************  program starts  "<<"*****************************" << endl;
	//*****************First test case: 100 thousand random integer
	cout<<endl<<"First test case: 10 thousand random Integer: "<<endl;	
	cout<<"Creating random Integers from -100000000 to 100000000.."<<endl;
	const char* testfile1 = dm.createRandomInt(100000);
	cout<<"Read data from file....."<<endl;	
	vector<int> RanIntData = dm.readIntFromFile(testfile1);	
	cout<<"Data read completed, data stored."<<endl;
	cout<<endl<<"Execute some sample query:"<<endl<<endl;
	dm.executeQuery("larger", 10000, RanIntData);	
	dm.executeQuery("smaller", 10000, RanIntData);
	dm.executeQuery("equals",10000,RanIntData);
	dm.executeQuery("larger", 33333,RanIntData);	
	dm.executeQuery("smaller", 20160307, RanIntData);
	dm.executeQuery("between", 33333,20160307, RanIntData);
	dm.executeQuery("between", 10000,33333,RanIntData);
	//****************second test case: 100 thousand random floats
	cout<<endl<<endl<<"Second test case: 100 thousand random Floats: "<<endl;	
	start_s = clock();	
	cout<<"Creating random Float from -100000000 to 100000000.."<<endl;
	const char* testfile2 = dm.createRandomFloat(100000);
	cout<<"Read data from file....."<<endl;	
	vector<float> RanFloatData = dm.readFloatFromFile(testfile2);	
	cout<<"Data read completed, data stored."<<endl;
	cout<<endl<<"Execute some sample query:"<<endl<<endl;
	dm.executeQuery("larger", (float)123.45, RanFloatData);	
	dm.executeQuery("smaller",(float) 123.45, RanFloatData);
	dm.executeQuery("equals",(float)123.45,RanFloatData);
	dm.executeQuery("larger", (float)333.33,RanFloatData);	
	dm.executeQuery("smaller", (float)2016.00, RanFloatData);
	dm.executeQuery("between", (float)-500.0, (float)500.0, RanFloatData);

	//*****************Third test case: 1 Million random integers
	cout << endl << "Third test case: 1 Million random Integer: " << endl;
	start_s = clock();
	cout << "Creating random Integers from -1000000 to 1000000.." << endl;
	const char* testfile3 = segData.createRandomInt(1000000);
	cout << "Read data from file....." << endl;
	segData.readFromFile(testfile3);
	cout<<endl<<"Execute some sample query:"<<endl<<endl;
	segData.getAllCounts();
	segData.query("smaller", 2000);
	segData.query("larger", 2000);
	segData.query("equals",2000);
	segData.query("between",0,1025);
	//*****************Fourth test case: 10 Million random integers
	cout << endl << "Fourth test case: 10 Million random Integer: " << endl;
	start_s = clock();
	cout << "Creating random Integers from -1000000 to 1000000.." << endl;
	const char* testfile4 = segData.createRandomInt(10000000);
	cout << "Read data from file....." << endl;
	segData.readFromFile(testfile4);
	cout<<"Data read completed, data stored."<<endl;
	cout<<endl<<"Execute some sample query:"<<endl<<endl;
	segData.getAllCounts();
	segData.query("smaller", 2000);
	segData.query("larger", 2000);
	segData.query("equals",2000);
	segData.query("between",0,1025);
	//****************Fifth test case: 50 Million random integers
	cout << endl << "Fifth test case: 25 Million random Integer: " << endl;
	start_s = clock();
	cout << "Creating 25 Million random Integers from -1000000 to 1000000.." << endl;
	const char* testfile5 = segData.createRandomInt(25000000);
	cout << "Read data from file....." << endl;
	segData.readFromFile(testfile5);
	cout<<"Data read completed, data stored."<<endl;
	cout<<endl<<"Execute some sample query:"<<endl<<endl;
	segData.getAllCounts();
	segData.query("smaller", 2000);
	segData.query("larger", 2000);
	segData.query("equals",2000);
	segData.query("between",0,1025);
	cout << endl << "*************** End of the program. Total time cost :";
	stop_s = clock();
	cout << (stop_s - start_s) / double(CLOCKS_PER_SEC) * 1000 << " ms  " << "*****************************" << endl;
	cout<<"Wish you have a good one! ---Zhichao(Zach)."<<endl;
	return 0;
}
float FieldController::HoleSquad( const Segment& topSegment, const std::vector<Segment>& modelTopLine )
{
	double holeSquad = 0;
	for (int i = 0, i_end = modelTopLine.size(); i < i_end; ++i)
	{
		double a_length = modelTopLine[i].length();
		double b_length = Segment(modelTopLine[i].start(), Vector2F(modelTopLine[i].start().X(), topSegment.start().Y())).length();
		holeSquad += a_length * b_length;
	}

	return (float)holeSquad;
}
Beispiel #9
0
void PositionCursor::move(int tick)
      {
      QRectF r(bbox());
      //
      // set mark height for whole system
      //
      if (_type == CursorType::LOOP_OUT)
        tick --;
      Score* score = _sv->score();
      Measure* measure = score->tick2measureMM(tick);
      if (measure == 0)
            return;
      qreal x;
      int offset = 0;

      Segment* s;
      for (s = measure->first(Segment::Type::ChordRest); s;) {
            int t1 = s->tick();
            int x1 = s->canvasPos().x();
            qreal x2;
            int t2;
            Segment* ns = s->next(Segment::Type::ChordRest);
            if (ns) {
                  t2 = ns->tick();
                  x2 = ns->canvasPos().x();
                  }
            else {
                  t2 = measure->endTick();
                  x2 = measure->canvasPos().x() + measure->width();
                  }
            t1 += offset;
            t2 += offset;
            if (tick >= t1 && tick < t2) {
                  int   dt = t2 - t1;
                  qreal dx = x2 - x1;
                  x = x1 + dx * (tick-t1) / dt;
                  break;
                  }
            s = ns;
            }
      if (s == 0)
            return;

      System* system = measure->system();
      if (system == 0)
            return;
      double y        = system->staffYpage(0) + system->page()->pos().y();
      double _spatium = score->spatium();

      qreal mag = _spatium / (MScore::DPI * SPATIUM20);
      double w  = (_spatium * 2.0 + score->scoreFont()->width(SymId::noteheadBlack, mag))/3;
      double h  = 6 * _spatium;
      //
      // set cursor height for whole system
      //
      double y2 = 0.0;

      for (int i = 0; i < score->nstaves(); ++i) {
            SysStaff* ss = system->staff(i);
            if (!ss->show() || !score->staff(i)->show())
                  continue;
            y2 = ss->y() + ss->bbox().height();
            }
      h += y2;
      y -= 3 * _spatium;

      if (_type == CursorType::LOOP_IN) {
            x = x - _spatium + w/1.5;
            }
      else {
            x = x - _spatium * .5;
            }
      _tick = tick;
      _rect = QRectF(x, y, w, h);
      _sv->update(_sv->matrix().mapRect(r | bbox()).toRect().adjusted(-1,-1,1,1));
      }
Beispiel #10
0
bool AABB::Intersects(const Segment& s) const { return s.Intersects(*this); }
Beispiel #11
0
void Pot_Piecewise::initialize( Conf_Module* config, vector<Module*> dependencies )
{
	GET_LOGGER( "liee.Module.Pot_Piecewise" );
	double epsilon = config->get_double("epsilon") / CONV_au_nm;
	rounding = config->get_array("ellipse")[0] / CONV_au_nm;
	scale_y = rounding / ( config->get_array("ellipse")[1] / CONV_au_eV );
	X = config->get_array("r_list");
	Y = config->get_array("V_list");
	if ( X.size() != Y.size() || X.size() == 0 ) {
		LOG_ERROR( "r_list and V_list are required to have the same size with at least 1 element." )
		exit(1);
	}
	if ( X.size() == 1 ) {  // constant potential
		X.push_back( X[0] + config->get_double("r_range") );
		Y.push_back( Y[0] );
	}

	for ( size_t i = 0; i < X.size(); i++ ) {
		X[i] /= CONV_au_nm;
		Y[i] /= CONV_au_eV;
		if ( i > 0  &&  X[i-1] > X[i] ) {
			LOG_ERROR( "r_list is required to be sorted in ascending order. exiting." )
			exit(1);
		}
		if ( i > 0  &&  X[i-1] == X[i] ) {
			X[i] += epsilon;
		}
	}

	Segment first;
	first.line( X[0], X[1], Y[0], Y[1] );
	segs.push_back( first );

	for ( size_t i = 1; i < X.size()-1; i++ )
	{
		Segment left, right;
		left = segs.back();
		right.line( X[i], X[i+1], Y[i], Y[i+1] );

		if ( rounding > 0  &&  left.m != right.m ) {
			// note: tangential-circle calculation is done in a y-stretched system in order to
			// work with a circle instead of an ellipse. The x-positions are valid in both systems,
			// while the circle centre-V is scaled back to the actual ellipse-centre
			// (V(r) draws the ellipse according to scale_y)
			for ( double rr = rounding; rr > 1e-4 * rounding; rr /= 1.5 )
			{
				Segment sleft, sright, circle;
				double S = scale_y;
				sleft.line( X[i-1], X[i], S*Y[i-1], S*Y[i] );
				sright.line( X[i], X[i+1], S*Y[i], S*Y[i+1] );

				circle.sign = ( left.m > right.m )  ?  +1  : -1;  // sign=+1: circle under the roof-like kink, positive "square-root"-circle is touching tangents and opposite for sign=-1
				double dist = -circle.sign * rr;  // the possible centre-positions for the tangential circle are on a parallel line, distanced 1 rounding-radius in orthogonal direction, either above or below
				double shifted_n_l = (S*Y[i] + dist * sleft.ortho_Y)  - sleft.m  * (X[i] + dist * sleft.ortho_X);  // ordinate of the left-side parallel
				double shifted_n_r = (S*Y[i] + dist * sright.ortho_Y) - sright.m * (X[i] + dist * sright.ortho_X);
				circle.cr = (shifted_n_l - shifted_n_r) / (sright.m - sleft.m);  // circle centre at the intersection of the two parallels
				circle.cV = ( sleft.m * circle.cr + shifted_n_l ) / S;
				circle.start_r = circle.cr - dist * sleft.ortho_X;  // from circle centre back on the normal-vector to the respective lines
				circle.end_r   = circle.cr - dist * sright.ortho_X;
				circle.radius = rr;

				// only accept rounding circle if it does not exceed the middle of neighbouring segments
				if (    circle.start_r > 0.5 * (segs.back().start_r + segs.back().end_r)
				     && circle.end_r   < 0.5 * (right.start_r + right.end_r) )
				{
					segs.back().end_r = circle.start_r;  // reduce left segment extend
					right.start_r = circle.end_r;
					segs.push_back( circle );
					break;
				} // else continue loop with a smaller radius
			}
		}
		segs.push_back( right );
	}
}
Beispiel #12
0
void ScoreView::lyricsUnderscore()
      {
      Lyrics* lyrics   = toLyrics(editData.element);
      int track        = lyrics->track();
      Segment* segment = lyrics->segment();
      int verse        = lyrics->no();
      Placement placement = lyrics->placement();
      int endTick      = segment->tick(); // a previous melisma cannot extend beyond this point

      changeState(ViewState::NORMAL);

      // search next chord
      Segment* nextSegment = segment;
      while ((nextSegment = nextSegment->next1(SegmentType::ChordRest))) {
            Element* el = nextSegment->element(track);
            if (el &&  el->isChord())
                  break;
            }

      // look for the lyrics we are moving from; may be the current lyrics or a previous one
      // we are extending with several underscores
      Lyrics* fromLyrics = 0;
      while (segment) {
            ChordRest* cr = toChordRest(segment->element(track));
            if (cr) {
                  fromLyrics = cr->lyrics(verse, placement);
                  if (fromLyrics)
                        break;
                  }
            segment = segment->prev1(SegmentType::ChordRest);
            // if the segment has a rest in this track, stop going back
            Element* e = segment ? segment->element(track) : 0;
            if (e && !e->isChord())
                  break;
            }

      _score->startCmd();
      // one-chord melisma?
      // if still at melisma initial chord and there is a valid next chord (if not,
      // there will be no melisma anyway), set a temporary melisma duration
      if (fromLyrics == lyrics && nextSegment)
            lyrics->undoChangeProperty(Pid::LYRIC_TICKS, Lyrics::TEMP_MELISMA_TICKS);

      if (nextSegment == 0) {
            if (fromLyrics) {
                  switch(fromLyrics->syllabic()) {
                        case Lyrics::Syllabic::SINGLE:
                        case Lyrics::Syllabic::END:
                              break;
                        default:
                              fromLyrics->undoChangeProperty(Pid::SYLLABIC, int(Lyrics::Syllabic::END));
                              break;
                        }
                  if (fromLyrics->segment()->tick() < endTick)
                        fromLyrics->undoChangeProperty(Pid::LYRIC_TICKS, endTick - fromLyrics->segment()->tick());
                  }
            // leave edit mode, select something (just for user feedback) and update to show extended melisam
            mscore->changeState(STATE_NORMAL);
            if (fromLyrics)
                  _score->select(fromLyrics, SelectType::SINGLE, 0);
            _score->setLayoutAll();
            _score->endCmd();
            return;
            }

      // if a place for a new lyrics has been found, create a lyrics there

      ChordRest* cr    = toChordRest(nextSegment->element(track));
      Lyrics* toLyrics = cr->lyrics(verse, placement);
      bool newLyrics   = (toLyrics == 0);
      if (!toLyrics) {
            toLyrics = new Lyrics(_score);
            toLyrics->setTrack(track);
            toLyrics->setParent(nextSegment->element(track));
            toLyrics->setNo(verse);
            toLyrics->setPlacement(placement);
            toLyrics->setSyllabic(Lyrics::Syllabic::SINGLE);
            }
      // as we arrived at toLyrics by an underscore, it cannot have syllabic dashes before
      else if (toLyrics->syllabic() == Lyrics::Syllabic::MIDDLE)
            toLyrics->undoChangeProperty(Pid::SYLLABIC, int(Lyrics::Syllabic::BEGIN));
      else if (toLyrics->syllabic() == Lyrics::Syllabic::END)
            toLyrics->undoChangeProperty(Pid::SYLLABIC, int(Lyrics::Syllabic::SINGLE));

      if (fromLyrics) {
            // as we moved away from fromLyrics by an underscore,
            // it can be isolated or terminal but cannot have dashes after
            switch(fromLyrics->syllabic()) {
                  case Lyrics::Syllabic::SINGLE:
                  case Lyrics::Syllabic::END:
                        break;
                  default:
                        fromLyrics->undoChangeProperty(Pid::SYLLABIC, int(Lyrics::Syllabic::END));
                        break;
                  }
            // for the same reason, if it has a melisma, this cannot extend beyond toLyrics
            if (fromLyrics->segment()->tick() < endTick)
                  fromLyrics->undoChangeProperty(Pid::LYRIC_TICKS, endTick - fromLyrics->segment()->tick());
            }
      if (newLyrics)
            _score->undoAddElement(toLyrics);
      _score->endCmd();

      _score->select(toLyrics, SelectType::SINGLE, 0);
      startEdit(toLyrics, Grip::NO_GRIP);

      adjustCanvasPosition(toLyrics, false);
      TextCursor* cursor = Ms::toLyrics(editData.element)->cursor(editData);
      Ms::toLyrics(editData.element)->selectAll(cursor);
      }
Beispiel #13
0
void ScoreView::lyricsMinus()
      {
      Lyrics* lyrics   = toLyrics(editData.element);
      int track        = lyrics->track();
      Segment* segment = lyrics->segment();
      int verse        = lyrics->no();
      Placement placement = lyrics->placement();

      changeState(ViewState::NORMAL);

      // search next chord
      Segment* nextSegment = segment;
      while ((nextSegment = nextSegment->next1(SegmentType::ChordRest))) {
            Element* el = nextSegment->element(track);
            if (el &&  el->isChord())
                  break;
            }
      if (nextSegment == 0)
            return;

      // look for the lyrics we are moving from; may be the current lyrics or a previous one
      // we are extending with several dashes
      Lyrics* fromLyrics = 0;
      while (segment) {
            ChordRest* cr = toChordRest(segment->element(track));
            if (!cr) {
                  segment = segment->prev1(SegmentType::ChordRest);
                  continue;
                  }
            fromLyrics = cr->lyrics(verse, placement);
            if (fromLyrics)
                  break;
            segment = segment->prev1(SegmentType::ChordRest);
            }

      _score->startCmd();
      ChordRest* cr = toChordRest(nextSegment->element(track));
      Lyrics* toLyrics           = cr->lyrics(verse, placement);
      bool newLyrics = (toLyrics == 0);
      if (!toLyrics) {
            toLyrics = new Lyrics(_score);
            toLyrics->setTrack(track);
            toLyrics->setParent(nextSegment->element(track));
            toLyrics->setNo(verse);
            toLyrics->setPlacement(placement);
            toLyrics->setSyllabic(Lyrics::Syllabic::END);
            }
      else {
            // as we arrived at toLyrics by a dash, it cannot be initial or isolated
            if (toLyrics->syllabic() == Lyrics::Syllabic::BEGIN)
                  toLyrics->undoChangeProperty(Pid::SYLLABIC, int(Lyrics::Syllabic::MIDDLE));
            else if (toLyrics->syllabic() == Lyrics::Syllabic::SINGLE)
                  toLyrics->undoChangeProperty(Pid::SYLLABIC, int(Lyrics::Syllabic::END));
            }

      if (fromLyrics) {
            // as we moved away from fromLyrics by a dash,
            // it can have syll. dashes before and after but cannot be isolated or terminal
            switch(fromLyrics->syllabic()) {
                  case Lyrics::Syllabic::BEGIN:
                  case Lyrics::Syllabic::MIDDLE:
                        break;
                  case Lyrics::Syllabic::SINGLE:
                        fromLyrics->undoChangeProperty(Pid::SYLLABIC, int(Lyrics::Syllabic::BEGIN));
                        break;
                  case Lyrics::Syllabic::END:
                        fromLyrics->undoChangeProperty(Pid::SYLLABIC, int(Lyrics::Syllabic::MIDDLE));
                        break;
                  }
            // for the same reason, it cannot have a melisma
            fromLyrics->undoChangeProperty(Pid::LYRIC_TICKS, 0);
            }

      if (newLyrics)
            _score->undoAddElement(toLyrics);
      _score->endCmd();

      _score->select(toLyrics, SelectType::SINGLE, 0);
      startEdit(toLyrics, Grip::NO_GRIP);

      adjustCanvasPosition(toLyrics, false);
      TextCursor* cursor = Ms::toLyrics(editData.element)->cursor(editData);
      Ms::toLyrics(editData.element)->selectAll(cursor);
      _score->setLayoutAll();
      }
Beispiel #14
0
void ScoreView::lyricsTab(bool back, bool end, bool moveOnly)
      {
      Lyrics* lyrics   = toLyrics(editData.element);
      int track        = lyrics->track();
      Segment* segment = lyrics->segment();
      int verse        = lyrics->no();
      Placement placement = lyrics->placement();

      Segment* nextSegment = segment;
      if (back) {
            // search prev chord
            while ((nextSegment = nextSegment->prev1(SegmentType::ChordRest))) {
                  Element* el = nextSegment->element(track);
                  if (el &&  el->isChord())
                        break;
                  }
            }
      else {
            // search next chord
            while ((nextSegment = nextSegment->next1(SegmentType::ChordRest))) {
                  Element* el = nextSegment->element(track);
                  if (el &&  el->isChord())
                        break;
                  }
            }
      if (nextSegment == 0)
            return;

      changeState(ViewState::NORMAL);

      // look for the lyrics we are moving from; may be the current lyrics or a previous one
      // if we are skipping several chords with spaces
      Lyrics* fromLyrics = 0;
      if (!back) {
            while (segment) {
                  ChordRest* cr = toChordRest(segment->element(track));
                  if (cr) {
                        fromLyrics = cr->lyrics(verse, placement);
                        if (fromLyrics)
                              break;
                        }
                  segment = segment->prev1(SegmentType::ChordRest);
                  }
            }

      ChordRest* cr = toChordRest(nextSegment->element(track));
      if (!cr) {
            qDebug("no next lyrics list: %s", nextSegment->element(track)->name());
            return;
            }
      Lyrics* _toLyrics = cr->lyrics(verse, placement);

      bool newLyrics = false;
      if (!_toLyrics) {
            _toLyrics = new Lyrics(_score);
            _toLyrics->setTrack(track);
            ChordRest* cr = toChordRest(nextSegment->element(track));
            _toLyrics->setParent(cr);
            _toLyrics->setNo(verse);
            _toLyrics->setPlacement(placement);
            _toLyrics->setSyllabic(Lyrics::Syllabic::SINGLE);
            newLyrics = true;
            }

      _score->startCmd();
      if (fromLyrics && !moveOnly) {
            switch (_toLyrics->syllabic()) {
                  // as we arrived at toLyrics by a [Space], it can be the beginning
                  // of a multi-syllable, but cannot have syllabic dashes before
                  case Lyrics::Syllabic::SINGLE:
                  case Lyrics::Syllabic::BEGIN:
                        break;
                  case Lyrics::Syllabic::END:
                        _toLyrics->undoChangeProperty(Pid::SYLLABIC, int(Lyrics::Syllabic::SINGLE));
                        break;
                  case Lyrics::Syllabic::MIDDLE:
                        _toLyrics->undoChangeProperty(Pid::SYLLABIC, int(Lyrics::Syllabic::BEGIN));
                        break;
                  }
            // as we moved away from fromLyrics by a [Space], it can be
            // the end of a multi-syllable, but cannot have syllabic dashes after
            switch (fromLyrics->syllabic()) {
                  case Lyrics::Syllabic::SINGLE:
                  case Lyrics::Syllabic::END:
                        break;
                  case Lyrics::Syllabic::BEGIN:
                        fromLyrics->undoChangeProperty(Pid::SYLLABIC, int(Lyrics::Syllabic::SINGLE));
                        break;
                  case Lyrics::Syllabic::MIDDLE:
                        fromLyrics->undoChangeProperty(Pid::SYLLABIC, int(Lyrics::Syllabic::END));
                        break;
                  }
            // for the same reason, it cannot have a melisma
            fromLyrics->undoChangeProperty(Pid::LYRIC_TICKS, 0);
            }

      if (newLyrics)
            _score->undoAddElement(_toLyrics);
      _score->endCmd();

      _score->select(_toLyrics, SelectType::SINGLE, 0);
      startEdit(_toLyrics, Grip::NO_GRIP);

      adjustCanvasPosition(_toLyrics, false);

      TextCursor* cursor = toLyrics(editData.element)->cursor(editData);
      if (end) {
            cursor->movePosition(QTextCursor::Start, QTextCursor::MoveAnchor);
            cursor->movePosition(QTextCursor::End, QTextCursor::KeepAnchor);
            }
      else {
            cursor->movePosition(QTextCursor::End, QTextCursor::MoveAnchor);
            cursor->movePosition(QTextCursor::Start, QTextCursor::KeepAnchor);
            }
      _score->setLayoutAll();
      }
Beispiel #15
0
 bool Rectangle::overlaps(Segment const& segment) const noexcept
 {
     return (contains(segment.start()) || contains(segment.end()) || intersects(segment));
 }
Beispiel #16
0
void Clef::layout()
      {
      // determine current number of lines and line distance
      int   lines;
      qreal lineDist;
      Segment* clefSeg  = segment();

      qDeleteAll(elements);
      elements.clear();

      // check clef visibility and type compatibility
      if (clefSeg && staff()) {
            StaffType* staffType = staff()->staffType();
            bool show            = staffType->genClef();        // check staff type allows clef display
            int tick             = clefSeg->tick();

            // check clef is compatible with staff type group:
            if (ClefInfo::staffGroup(clefType()) != staffType->group()) {
                  if (tick > 0 && !generated()) // if clef is not generated, hide it
                        show = false;
                  else                          // if generated, replace with initial clef type
                        // TODO : instead of initial staff clef (which is assumed to be compatible)
                        // use the last compatible clef previously found in staff
                        _clefTypes = staff()->clefType(0);
                  }

            // if clef not to show or not compatible with staff group
            if (!show) {
                  setbbox(QRectF());
                  qDebug("Clef::layout(): invisible clef at tick %d(%d) staff %d",
                     segment()->tick(), segment()->tick()/1920, staffIdx());
                  return;
                  }
            lines    = staffType->lines();         // init values from staff type
            lineDist = staffType->lineDistance().val();
            }
      else {
            lines    = 5;
            lineDist = 1.0;
            }

      qreal _spatium = spatium();
      qreal yoff     = 0.0;

      Symbol* symbol = new Symbol(score());

      switch (clefType()) {
            case ClefType::G:                              // G clef on 2nd line
                  symbol->setSym(SymId::gClef);
                  yoff = 3.0 * lineDist;
                  break;
            case ClefType::G1:                             // G clef 8va on 2nd line
                  symbol->setSym(SymId::gClef8va);
                  yoff = 3.0 * lineDist;
                  break;
            case ClefType::G2:                             // G clef 15ma on 2nd line
                  symbol->setSym(SymId::gClef15ma);
                  yoff = 3.0 * lineDist;
                  break;
            case ClefType::G3:                             // G clef 8vb on 2nd line
                  symbol->setSym(SymId::gClef8vb);
                  yoff = 3.0 * lineDist;
                  break;
            case ClefType::G3_O:                            // double G clef 8vb on 2nd line
                  symbol->setSym(SymId::gClef8vbOld);
                  yoff = 3.0 * lineDist;
                  break;
            case ClefType::F:                              // F clef on penultimate line
                  symbol->setSym(SymId::fClef);
                  yoff = 1.0 * lineDist;
                  break;
            case ClefType::F8:                             // F clef 8va bassa on penultimate line
                  symbol->setSym(SymId::fClef8vb);
                  yoff = 1.0 * lineDist;
                  break;
            case ClefType::F15:                            // F clef 15ma bassa on penultimate line
                  symbol->setSym(SymId::fClef15mb);
                  yoff = 1.0 * lineDist;
                  break;
            case ClefType::F_B:                            // baritone clef
                  symbol->setSym(SymId::fClef);
                  yoff = 2.0 * lineDist;
                  break;
            case ClefType::F_C:                            // subbass clef
                  symbol->setSym(SymId::fClef);
                  yoff = 0.0;
                  break;
            case ClefType::C1:                             // C clef in 1st line
                  symbol->setSym(SymId::cClef);
                  yoff = 4.0 * lineDist;
                  break;
            case ClefType::C2:                             // C clef on 2nd line
                  symbol->setSym(SymId::cClef);
                  yoff = 3.0 * lineDist;
                  break;
            case ClefType::C3:                             // C clef in 3rd line
                  symbol->setSym(SymId::cClef);
                  yoff = 2.0 * lineDist;
                  break;
            case ClefType::C4:                             // C clef on 4th line
                  symbol->setSym(SymId::cClef);
                  yoff = 1.0 * lineDist;
                  break;
            case ClefType::C5:                             // C clef on 5th line
                  symbol->setSym(SymId::cClef);
                  yoff = 0.0;
                  break;
            case ClefType::TAB:                            // TAB clef
                  symbol->setSym(SymId::sixStringTabClef);
                  // on tablature, position clef at half the number of spaces * line distance
                  yoff = lineDist * (lines - 1) * .5;
                  break;
            case ClefType::TAB2:                           // TAB clef alternate style
                  symbol->setSym(SymId::sixStringTabClefSerif);
                  // on tablature, position clef at half the number of spaces * line distance
                  yoff = lineDist * (lines - 1) * .5;
                  break;
            case ClefType::PERC:                           // percussion clefs
                  symbol->setSym(SymId::unpitchedPercussionClef1);
                  yoff = lineDist * (lines - 1) * 0.5;
                  break;
            case ClefType::PERC2:
                  symbol->setSym(SymId::unpitchedPercussionClef2);
                  yoff = lineDist * (lines - 1) * 0.5;
                  break;
            case ClefType::G4:                             // G clef in 1st line
                  symbol->setSym(SymId::gClef);
                  yoff = 4.0 * lineDist;
                  break;
            case ClefType::F_8VA:                          // F clef 8va on penultimate line
                  symbol->setSym(SymId::fClef8va);
                  yoff = 1.0 * lineDist;
                  break;
            case ClefType::F_15MA:                         // F clef 15ma on penultimate line
                  symbol->setSym(SymId::fClef15ma);
                  yoff = 1.0 * lineDist;
                  break;
            case ClefType::G5:                              // G clef on 2nd line
                  symbol->setSym(SymId::gClef8vbParens);
                  yoff = 3.0 * lineDist;
                  break;
            case ClefType::INVALID:
            case ClefType::MAX:
                  qDebug("Clef::layout: invalid type");
                  return;
            }
      addElement(symbol, .0, yoff * _spatium);
      QRectF r;
      for (Element* e : elements) {
            r |= e->bbox().translated(e->pos());
            e->setSelected(selected());
            }

      // clefs are right aligned to Segment

      QPointF off(-r.right(), 0);
      for (Element* e : elements)
            e->move(off);
      r.translate(off);
      setbbox(r);
      setPos(QPointF());
      }
Beispiel #17
0
bool AreaShader::checkIntersect(const Segment& s) const
{
    const Segment::Areastore& areas(s.getAreas());
    return (areas.count(m_layer) > 0);
}
Beispiel #18
0
void SLine::layout()
      {
      if (parent() == 0) {
            //
            // when used in a palette, SLine has no parent and
            // tick and tick2 has no meaning so no layout is
            // possible and needed
            //
            if (!spannerSegments().isEmpty()) {
                  LineSegment* s = frontSegment();
                  s->layout();
                  setbbox(s->bbox());
                  }
            return;
            }
      if (startElement() == 0 || endElement() == 0) {
            qDebug("SLine::layout() failed: %s %s", parent()->name(), name());
            qDebug("   start %p   end %p", startElement(), endElement());
            return;
            }

      System* s1;
      System* s2;
      QPointF p1 = linePos(GRIP_LINE_START, &s1);
      QPointF p2 = linePos(GRIP_LINE_END,   &s2);

      QList<System*>* systems = score()->systems();
      int sysIdx1 = systems->indexOf(s1);
      int sysIdx2 = systems->indexOf(s2);
      int segmentsNeeded = 0;
      for (int i = sysIdx1; i < sysIdx2+1;  ++i) {
            if (systems->at(i)->isVbox())
                  continue;
            ++segmentsNeeded;
            }
      int segCount = spannerSegments().size();

      if (segmentsNeeded != segCount) {
            if (segmentsNeeded > segCount) {
                  int n = segmentsNeeded - segCount;
                  for (int i = 0; i < n; ++i) {
                        LineSegment* ls = createLineSegment();
                        add(ls);
                        // set user offset to previous segment's offset
                        if (segCount > 0)
                              ls->setUserOff(QPointF(0, segmentAt(segCount+i-1)->userOff().y()));
                        }
                  }
            else {
                  int n = segCount - segmentsNeeded;
                  qDebug("SLine: segments %d needed %d, remove %d", segCount, segmentsNeeded, n);
                  for (int i = 0; i < n; ++i) {
                        if (spannerSegments().isEmpty()) {
                              qDebug("SLine::layout(): no segment %d, %d expected", i, n);
                              break;
                              }
                        else {
                              // LineSegment* seg = takeLastSegment();
                              // TODO delete seg;
                              }
                        }
                  }
            }

      int segIdx = 0;
      int si  = staffIdx();
      for (int i = sysIdx1; i <= sysIdx2; ++i) {
            System* system = systems->at(i);
            if (system->isVbox())
                  continue;
            LineSegment* seg = segmentAt(segIdx++);
            seg->setSystem(system);

            Measure* m = system->firstMeasure();
            Segment* mseg = m->first(SegChordRest);
            qreal x1 = (mseg ? mseg->pos().x() : 0) + m->pos().x();
            qreal x2 = system->bbox().right();
            qreal y  = system->staff(si)->y();

            if (sysIdx1 == sysIdx2) {
                  // single segment
                  seg->setSubtype(SEGMENT_SINGLE);
                  seg->setPos(p1);
                  seg->setPos2(QPointF(p2.x() - p1.x(), 0.0));
                  }
            else if (i == sysIdx1) {
                  // start segment
                  seg->setSubtype(SEGMENT_BEGIN);
                  seg->setPos(p1);
                  seg->setPos2(QPointF(x2 - p1.x(), 0.0));
                  }
            else if (i > 0 && i != sysIdx2) {
                  // middle segment
                  seg->setSubtype(SEGMENT_MIDDLE);
                  seg->setPos(QPointF(x1, y));
                  seg->setPos2(QPointF(x2 - x1, 0.0));
                  }
            else if (i == sysIdx2) {
                  // end segment
                  seg->setSubtype(SEGMENT_END);
                  seg->setPos(QPointF(x1, y));
                  seg->setPos2(QPointF(p2.x() - x1, 0.0));
                  }
            seg->layout();
            seg->rypos() += (_yoffset * spatium());
            seg->adjustReadPos();
            }
      }
Beispiel #19
0
SegmentSplitCommand::SegmentVec
SegmentSplitCommand::
getNewSegments(Segment *segment, timeT splitTime, bool keepLabel)
{
    Segment * newSegmentA = segment->clone(false);
    Segment * newSegmentB = new Segment();

    newSegmentB->setTrack(segment->getTrack());
    newSegmentB->setStartTime(splitTime);

    // !!! Set Composition?
    
    Event *clefEvent = 0;
    Event *keyEvent = 0;

    // Copy the last occurrence of clef and key
    // from the left hand side of the split (nb. timesig events
    // don't appear in segments, only in composition)
    //
    Segment::iterator it = segment->findTime(splitTime);

    while (it != segment->begin()) {

        --it;

        if (!clefEvent && (*it)->isa(Clef::EventType)) {
            clefEvent = new Event(**it, splitTime);
        }

        if (!keyEvent && (*it)->isa(Key::EventType)) {
            keyEvent = new Event(**it, splitTime);
        }

        if (clefEvent && keyEvent)
            break;
    }

    // Insert relevant meta info if we've found some
    //
    if (clefEvent)
        newSegmentB->insert(clefEvent);

    if (keyEvent)
        newSegmentB->insert(keyEvent);

    // Copy through the Events
    //
    it = segment->findTime(splitTime);

    if (it != segment->end() && (*it)->getAbsoluteTime() > splitTime) {
        newSegmentB->fillWithRests((*it)->getAbsoluteTime());
    }

    while (it != segment->end()) {
        newSegmentB->insert(new Event(**it));
        ++it;
    }
    newSegmentB->setEndTime(segment->getEndTime());
    newSegmentB->setEndMarkerTime(segment->getEndMarkerTime());

    // Set labels
    //
    std::string label = segment->getLabel();
    newSegmentA->setLabel(label);
    newSegmentB->setLabel(label);
    if (!keepLabel) {
        newSegmentA->setLabel(appendLabel(label, qstrtostr(tr("(split)"))));
        newSegmentB->setLabel(appendLabel(label, qstrtostr(tr("(split)"))));
    }

    newSegmentB->setColourIndex(segment->getColourIndex());
    newSegmentB->setTranspose(segment->getTranspose());
    newSegmentB->setDelay(segment->getDelay());

    // Resize left hand Segment
    //
    std::vector<Event *> toErase, toInsert;
    for (Segment::iterator i = newSegmentA->findTime(splitTime);
         i != newSegmentA->end(); ++i) {
        if ((*i)->getAbsoluteTime() >= splitTime) break;
        if ((*i)->getAbsoluteTime() + (*i)->getDuration() > splitTime) {
            Event *e = new Event(**i, (*i)->getAbsoluteTime(),
                                 splitTime - (*i)->getAbsoluteTime());
            toErase.push_back(*i);
            toInsert.push_back(e);
        }
    }

    for (size_t i = 0; i < toErase.size(); ++i) {
        newSegmentA->eraseSingle(toErase[i]);
        delete toErase[i];
    }
    for (size_t i = 0; i < toInsert.size(); ++i) {
        newSegmentA->insert(toInsert[i]);
    }

    newSegmentA->setEndTime(splitTime);
    newSegmentA->setEndMarkerTime(splitTime);
    SegmentVec segmentVec;
    segmentVec.reserve(2);
    segmentVec.push_back(newSegmentA);
    segmentVec.push_back(newSegmentB);
    return segmentVec;
}
Beispiel #20
0
void BarLine::getY(qreal* y1, qreal* y2) const
      {
      qreal _spatium = spatium();
      if (parent()) {
            int staffIdx1    = staffIdx();
            int staffIdx2    = staffIdx1 + _span - 1;
            if (staffIdx2 >= score()->nstaves()) {
                  qDebug("BarLine: bad _span %d", _span);
                  staffIdx2 = score()->nstaves() - 1;
                  }
            Measure* measure;
            System* system;
            qreal yp = 0.0;
            if (parent()->type() == Element::Type::SEGMENT) {
                  Segment* segment = static_cast<Segment*>(parent());
                  measure = segment->measure();
                  system  = measure->system();
                  }
            else {
                  system  = static_cast<System*>(parent());
                  measure = system->firstMeasure();
                  }
            if (measure) {
                  // test start and end staff visibility
                  int   nstaves = score()->nstaves();
                  int   span = _span;
                  Staff* staff1 = score()->staff(staffIdx1);
                  Staff* staff2 = score()->staff(staffIdx2);
                  SysStaff* sysStaff1 = system->staff(staffIdx1);
                  SysStaff* sysStaff2 = system->staff(staffIdx2);
                  while (span > 0) {
                        // if start staff not shown, reduce span and move one staff down
                        if ( !(sysStaff1->show() && staff1->show()) ) {
                              span--;
                              if (staffIdx1 >= nstaves-1)         // running out of staves?
                                    break;
                              sysStaff1 = system->staff(++staffIdx1);
                              staff1    = score()->staff(staffIdx1);
                        }
                        // if end staff not shown, reduce span and move one staff up
                        else if ( !(sysStaff2->show() && staff2->show()) ) {
                              span--;
                              if (staffIdx2 == 0)
                                    break;
                              sysStaff2 = system->staff(--staffIdx2);
                              staff2    = score()->staff(staffIdx2);
                        }
                        // if both staves shown, exit loop
                        else
                              break;
                  }
                  // if no longer any span, set 0 length and exit
                  if (span <= 0) {
                        *y1 = *y2 = 0;
                        return;
                  }
                  // both staffIdx1 and staffIdx2 are shown: compute corresponding line length
                  StaffLines* l1 = measure->staffLines(staffIdx1);
                  StaffLines* l2 = measure->staffLines(staffIdx2);

                  if (system)
                        yp += sysStaff1->y();
                  *y1 = l1->y1() - yp;
                  *y1 += (_spanFrom * staff1->lineDistance() * staff1->spatium()) / 2;
                  *y2 = l2->y1() - yp;
                  *y2 += (_spanTo   * staff2->lineDistance() * staff2->spatium()) / 2;
                  }
            }
      else {
            // for use in palette
            *y1 = _spanFrom * _spatium / 2;
            *y2 = _spanTo   * _spatium / 2;
            }

      if (selected()) {
            *y1 += yoff1;
            *y2 += yoff2;
            }
      }
Beispiel #21
0
void Clef::layout()
      {
      // determine current number of lines and line distance
      int   lines;
      qreal lineDist;
      Segment* clefSeg  = segment();

      // check clef visibility and type compatibility
      if (clefSeg && staff()) {
            StaffType* staffType = staff()->staffType();
            bool show            = staffType->genClef();        // check staff type allows clef display
            int tick             = clefSeg->tick();

            // check clef is compatible with staff type group:
            if (ClefInfo::staffGroup(clefType()) != staffType->group()) {
                  if (tick > 0 && !generated()) // if clef is not generated, hide it
                        show = false;
                  else                          // if generated, replace with initial clef type
                        // TODO : instead of initial staff clef (which is assumed to be compatible)
                        // use the last compatible clef previously found in staff
                        _clefTypes = staff()->clefType(0);
                  }

            // if clef not to show or not compatible with staff group
            if (!show) {
                  setbbox(QRectF());
                  qDebug("Clef::layout(): invisible clef at tick %d(%d) staff %d",
                     segment()->tick(), segment()->tick()/1920, staffIdx());
                  return;
                  }
            lines    = staffType->lines();         // init values from staff type
            lineDist = staffType->lineDistance().val();
            }
      else {
            lines    = 5;
            lineDist = 1.0;
            }

      qreal _spatium = spatium();
      qreal yoff     = 0.0;
      if (clefType() !=  ClefType::INVALID && clefType() !=  ClefType::MAX) {
            symId = ClefInfo::symId(clefType());
            yoff = lineDist * (lines - ClefInfo::line(clefType()));
            }

      switch (clefType()) {
            case ClefType::C_19C:                            // 19th C clef is like a G clef
                  yoff = lineDist * 1.5;
                  break;
            case ClefType::TAB:                            // TAB clef
                  // on tablature, position clef at half the number of spaces * line distance
                  yoff = lineDist * (lines - 1) * .5;
                  break;
            case ClefType::TAB4:                            // TAB clef 4 strings
                  // on tablature, position clef at half the number of spaces * line distance
                  yoff = lineDist * (lines - 1) * .5;
                  break;
            case ClefType::TAB_SERIF:                           // TAB clef alternate style
                  // on tablature, position clef at half the number of spaces * line distance
                  yoff = lineDist * (lines - 1) * .5;
                  break;
            case ClefType::TAB4_SERIF:                           // TAB clef alternate style
                  // on tablature, position clef at half the number of spaces * line distance
                  yoff = lineDist * (lines - 1) * .5;
                  break;
            case ClefType::PERC:                           // percussion clefs
                  yoff = lineDist * (lines - 1) * 0.5;
                  break;
            case ClefType::PERC2:
                  yoff = lineDist * (lines - 1) * 0.5;
                  break;
            case ClefType::INVALID:
            case ClefType::MAX:
                  qDebug("Clef::layout: invalid type");
                  return;
            default:
                  break;
            }
      // clefs are right aligned to Segment
      QRectF r(symBbox(symId));
//      setPos(-r.right(), yoff * _spatium);
      setPos(0.0, yoff * _spatium);

      setbbox(r);
      }
void 
SegmentTransposeCommand::processSegment(Segment &segment, bool changeKey, int steps, int semitones, bool transposeSegmentBack)
{
    MacroCommand * macroCommand = this;

    // TODO delete it somewhere.
    EventSelection * wholeSegment = new EventSelection(segment, segment.getStartTime(), segment.getEndMarkerTime());
    macroCommand->addCommand(new TransposeCommand
        (semitones, steps, *wholeSegment));
    
    // Key insertion can do transposition, but a C4 to D becomes a D4, while
    //  a C4 to G becomes a G3. Because we let the user specify an explicit number
    //  of octaves to move the notes up/down, we add the keys without transposing
    //  and handle the transposition seperately:
    if (changeKey)
    {
        Rosegarden::Key initialKey = segment.getKeyAtTime(segment.getStartTime());
        Rosegarden::Key newInitialKey = initialKey.transpose(semitones, steps);

        EventSelection::eventcontainer::iterator i;
        //std::list<KeyInsertionCommand*> commands;

        for (i = wholeSegment->getSegmentEvents().begin();
            i != wholeSegment->getSegmentEvents().end(); ++i) {
                // transpose key
                if ((*i)->isa(Rosegarden::Key::EventType)) {
                    Rosegarden::Key trKey = (Rosegarden::Key (**i)).transpose(semitones, steps); 
                    //commands.push_front
                    macroCommand->addCommand
                        (new KeyInsertionCommand
                         (segment,
                           (*i)->getAbsoluteTime(),
                           trKey,
                          false,
                          false,
                          false,
			  true));
                    }
            }
        std::list<KeyInsertionCommand*>::iterator ci;
        //for (ci=commands.begin(); ci!=commands.end(); ci++)
        //{
        //    commandHistory->addCommand(*ci);
        //}
            
        KeyInsertionCommand *firstKeyCommand = new KeyInsertionCommand
             (segment,
              segment.getStartTime(),
              newInitialKey,
              false,
              false,
              false,
	      true);
        //commandHistory->addCommand(firstKeyCommand);
        macroCommand->addCommand(firstKeyCommand);
    }
        
    if (transposeSegmentBack)
    {
        // Transpose segment in opposite direction
        int newTranspose = segment.getTranspose() - semitones;
        macroCommand->addCommand(new SegmentChangeTransposeCommand(newTranspose, &segment));
    }
}
Beispiel #23
0
void Slice::ConnectSegmentNeighbors()
{
	unsigned int s;
    unsigned int potential;
    unsigned int s2;
	double potentialangle;
	double potentialDist;
	double minDist = 10000.0;

	Segment* thisSeg = NULL;
	Segment* thatSeg = NULL;
    QVector2D* thisPoint = NULL;

    QVector2D* thatPoint = NULL;

    std::vector<Segment*> sameXStripSegs;
    std::vector<Segment*> potentialLeadSegs;

    Segment* finalLeadSeg = NULL;

	for(s = 0; s < segmentList.size(); s++)//compare from every segment
	{
		thisSeg = segmentList[s];
		thisPoint = &thisSeg->p2;//compare from the 2nd point on "this" segment

		if(thisSeg->leadingSeg)//no need to add a connection if there already is one!
			continue;
		
		potentialLeadSegs.clear();//clear out the potentials list
		

        GetSegmentsAroundX(sameXStripSegs, thisPoint->x());


        //////////////////////////////////////
        for(s2 = 0; s2 < sameXStripSegs.size(); s2++)//to every other segment in ring
		{
			//make sure its not the same segment
			if(s == s2)
			{continue;}
			
            thatSeg = sameXStripSegs[s2];
			if(thatSeg->trailingSeg)//already connected to a trailing segment...
				continue;
			
			thatPoint = &thatSeg->p1;//to the first point of "that" segment
            if(IsZero(Distance2D(*thisPoint, *thatPoint),0.03))//they are close enough to each other
            {
				potentialLeadSegs.push_back(thatSeg);
            }
		}
        //////////////////////////////////////

		//sort through and pick from the potential pile
		//we want to pick a segment with the sharpest change in direction!
		//
		//
		//1>>>>>>>>>A>>>>>>>>2 1>>>>>>>>B>>>>>>>>>2
		//                    ^
		//             large delta angle/ Right Wieghted
		minDist = 100000.0;
		finalLeadSeg = NULL;
		potentialangle = 0.0;
		for(potential = 0; potential < potentialLeadSegs.size(); potential++)
		{
			thatSeg = potentialLeadSegs[potential];
			//potentialDot = (thisSeg->normal.x() * thatSeg->normal.x()) + (thisSeg->normal.y() * thatSeg->normal.y()); //gives a number indicating how sharp the angle is, -1 is the sharpest (-1,1)
			//potentialCross = (thisSeg->normal.x() * thatSeg->normal.y()) - (thisSeg->normal.y() * thatSeg->normal.x());//gives a number indicating a right or left turn. (uphill is positive), (downhill is negative) (-1,1)
			potentialDist = Distance2D(thisSeg->p2, thatSeg->p1);
			
			if(potentialDist < minDist)
			{
				minDist = potentialDist;
				finalLeadSeg = potentialLeadSegs[potential];
			}
			
		}
		if(finalLeadSeg)
		{
			thisSeg->leadingSeg = finalLeadSeg;
			finalLeadSeg->trailingSeg = thisSeg;

			thisSeg->p2 = finalLeadSeg->p1;
			thisSeg->FormNormal();
		}
	}
}
Beispiel #24
0
Note* Glissando::guessInitialNote(Chord* chord)
      {
      switch (chord->noteType()) {
//            case NoteType::INVALID:
//                  return nullptr;
            // for grace notes before, previous chord is previous chord of parent chord
            case NoteType::ACCIACCATURA:
            case NoteType::APPOGGIATURA:
            case NoteType::GRACE4:
            case NoteType::GRACE16:
            case NoteType::GRACE32:
                  // move unto parent chord and proceed to standard case
                  if (chord->parent() && chord->parent()->type() == Element::Type::CHORD)
                        chord = static_cast<Chord*>(chord->parent());
                  else
                        return nullptr;
                  break;
            // for grace notes after, return top note of parent chord
            case NoteType::GRACE8_AFTER:
            case NoteType::GRACE16_AFTER:
            case NoteType::GRACE32_AFTER:
                  if (chord->parent() && chord->parent()->type() == Element::Type::CHORD)
                        return static_cast<Chord*>(chord->parent())->upNote();
                  else                          // no parent or parent is not a chord?
                        return nullptr;
            case NoteType::NORMAL:
                  {
                  // if chord has grace notes before, the last one is the previous note
                  QVector<Chord*>graces = chord->graceNotesBefore();
                  if (graces.size() > 0)
                        return graces.last()->upNote();
                  }
                  break;                        // else process to standard case
            default:
                  break;
            }

      // standard case (NORMAL or grace before chord)

      // if parent not a segment, can't locate a target note
      if (chord->parent()->type() != Element::Type::SEGMENT)
            return nullptr;

      int         chordTrack  = chord->track();
      Segment*    segm        = chord->segment();
      Part*       part        = chord->part();
      if (segm != nullptr)
            segm = segm->prev1();
      while (segm) {
            // if previous segment is a ChordRest segment
            if (segm->segmentType() == Segment::Type::ChordRest) {
                  Chord* target = nullptr;
                  // look for a Chord in the same track
                  if (segm->element(chordTrack) && segm->element(chordTrack)->type() == Element::Type::CHORD)
                        target = static_cast<Chord*>(segm->element(chordTrack));
                  else              // if no same track, look for other chords in the same instrument
                        for (Element* currChord : segm->elist())
                              if (currChord != nullptr && currChord->type() == Element::Type::CHORD
                                          && static_cast<Chord*>(currChord)->part() == part) {
                                    target = static_cast<Chord*>(currChord);
                                    break;
                                    }
                  // if we found a target previous chord
                  if (target) {
                        // if chord has grace notes after, the last one is the previous note
                        QVector<Chord*>graces = target->graceNotesAfter();
                        if (graces.size() > 0)
                              return graces.last()->upNote();
                        return target->upNote();      // if no grace after, return top note
                        }
                  }
            segm = segm->prev1();
            }
      qDebug("no first note for glissando found");
      return nullptr;
      }
Beispiel #25
0
void SegmentPencil::mouseReleaseEvent(QMouseEvent *e)
{
    // Have to allow middle button for SegmentSelector's middle
    // button feature to work.
    if (e->button() != Qt::LeftButton  &&
        e->button() != Qt::MidButton)
        return;

    // No need to propagate.
    e->accept();

    QPoint pos = m_canvas->viewportToContents(e->pos());

    setContextHelpFor(pos);

    if (m_newRect) {

        QRect tmpRect = m_canvas->getNewSegmentRect();

        int trackPosition = m_canvas->grid().getYBin(tmpRect.y());
        Track *track = 
            m_doc->getComposition().getTrackByPosition(trackPosition);

        SegmentInsertCommand *command =
            new SegmentInsertCommand(m_doc, track->getId(),
                                     m_startTime, m_endTime);

        m_newRect = false;

        CommandHistory::getInstance()->addCommand(command);

        // add the SegmentItem by hand, instead of allowing the usual
        // update mechanism to spot it.  This way we can select the
        // segment as we add it; otherwise we'd have no way to know
        // that the segment was created by this tool rather than by
        // e.g. a simple file load

        Segment *segment = command->getSegment();

        // add a clef to the start of the segment (tracks initialize to a
        // default of 0 for this property, so treble will be the default if it
        // is not specified elsewhere)
        segment->insert(clefIndexToClef(track->getClef()).getAsEvent
                        (segment->getStartTime()));

        //!!! Should not a default key be inserted here equally in order to
        //    have the "hide redundant clefs and keys" mechanism working
        //    on the segments using the default key ?

        segment->setTranspose(track->getTranspose());
        segment->setColourIndex(track->getColor());
        segment->setLowestPlayable(track->getLowestPlayable());
        segment->setHighestPlayable(track->getHighestPlayable());

        std::string label = track->getPresetLabel();
        if (label != "") {
            segment->setLabel( track->getPresetLabel().c_str() );
        }

        m_canvas->getModel()->clearSelected();
        m_canvas->getModel()->setSelected(segment);
        m_canvas->getModel()->selectionHasChanged();

        m_canvas->hideNewSegment();
        m_canvas->slotUpdateAll();

    }
}
Beispiel #26
0
Note* Glissando::guessFinalNote(Chord* chord)
      {
      switch (chord->noteType()) {
//            case NoteType::INVALID:
//                  return nullptr;
            // for grace notes before, return top note of parent chord
            // TODO : if the grace-before is not the LAST ONE, this still returns the main note
            //    which is probably not correct; however a glissando between two grace notes
            //    probably makes little sense.
            case NoteType::ACCIACCATURA:
            case NoteType::APPOGGIATURA:
            case NoteType::GRACE4:
            case NoteType::GRACE16:
            case NoteType::GRACE32:
                  if (chord->parent() && chord->parent()->type() == Element::Type::CHORD)
                        return static_cast<Chord*>(chord->parent())->upNote();
                  else                          // no parent or parent is not a chord?
                        return nullptr;
            // for grace notes after, next chord is next chord of parent chord
            // TODO : same note as case above!
            case NoteType::GRACE8_AFTER:
            case NoteType::GRACE16_AFTER:
            case NoteType::GRACE32_AFTER:
                  // move unto parent chord and proceed to standard case
                  if (chord->parent() && chord->parent()->type() == Element::Type::CHORD)
                        chord = static_cast<Chord*>(chord->parent());
                  else
                        return nullptr;
                  break;
            case NoteType::NORMAL:
                  {
                  // if chord has grace notes after, the first one is the next note
                  QVector<Chord*>graces = chord->graceNotesAfter();
                  if (graces.size() > 0)
                        return graces.first()->upNote();
                  }
                  break;
            default:
                  break;
            }

      // standard case (NORMAL or grace after chord)

      // if parent not a segment, can't locate a target note
      if (chord->parent()->type() != Element::Type::SEGMENT)
            return nullptr;

      // look for first ChordRest segment after initial note is elapsed
      Segment*    segm        = chord->score()->tick2rightSegment(chord->tick() + chord->actualTicks());
      int         chordTrack  = chord->track();
      Part*       part        = chord->part();
      while (segm) {
            // if next segment is a ChordRest segment
            if (segm->segmentType() == Segment::Type::ChordRest) {
                  Chord* target = nullptr;

                  // look for a Chord in the same track
                  if (segm->element(chordTrack) && segm->element(chordTrack)->type() == Element::Type::CHORD)
                        target = static_cast<Chord*>(segm->element(chordTrack));
                  else              // if no same track, look for other chords in the same instrument
                        for (Element* currChord : segm->elist())
                              if (currChord != nullptr && currChord->type() == Element::Type::CHORD
                                          && static_cast<Chord*>(currChord)->part() == part) {
                                    target = static_cast<Chord*>(currChord);
                                    break;
                                    }

                  // if we found a target next chord
                  if (target) {
                        // if chord has grace notes before, the first one is the next note
                        QVector<Chord*>graces = target->graceNotesBefore();
                        if (graces.size() > 0)
                              return graces.first()->upNote();
                        return target->upNote();      // if no grace before, return top note
                        }
                  }
            segm = segm->next1();
            }
      qDebug("no second note for glissando found");
      return nullptr;
      }
Beispiel #27
0
Segment::Segment(const Segment& source) : _myId(_freeID++), _a(source.start()), _b(source.end()){
#ifdef NDEBUG
	cout << "Segment " << _myId << ": copy constructor. Source: " << source;
#endif
}
Beispiel #28
0
void Ambitus::layout()
      {
      int         bottomLine, topLine;
      ClefType    clf;
      qreal       headWdt     = headWidth();
      Key         key;
      qreal       lineDist;
      int         numOfLines;
      Segment*    segm        = segment();
      qreal       _spatium    = spatium();
      Staff*      stf         = nullptr;
      if (segm && track() > -1) {
            int tick    = segm->tick();
            stf         = score()->staff(staffIdx());
            lineDist    = stf->lineDistance(tick) * _spatium;
            numOfLines  = stf->lines(tick);
            clf         = stf->clef(tick);
            }
      else {                              // for use in palettes
            lineDist    = _spatium;
            numOfLines  = 3;
            clf         = ClefType::G;
            }

      //
      // NOTEHEADS Y POS
      //
      // if pitch == INVALID_PITCH oor tpc == INALID_TPC, set to some default:
      // for use in palettes and when actual range cannot be calculated (new ambitus or no notes in staff)
      //
      qreal xAccidOffTop    = 0;
      qreal xAccidOffBottom = 0;
      if (stf)
            key = stf->key(segm->tick());
      else
            key = Key::C;

      // top notehead
      if (_topPitch == INVALID_PITCH || _topTpc == Tpc::TPC_INVALID)
            _topPos.setY(0);                          // if uninitialized, set to top staff line
      else {
            topLine  = absStep(_topTpc, _topPitch);
            topLine  = relStep(topLine, clf);
            _topPos.setY(topLine * lineDist * 0.5);
            // compute accidental
            AccidentalType accidType;
            // if (13 <= (tpc - key) <= 19) there is no accidental)
            if (_topTpc - int(key) >= 13 && _topTpc - int(key) <= 19)
                  accidType = AccidentalType::NONE;
            else {
                  AccidentalVal accidVal = AccidentalVal( (_topTpc - Tpc::TPC_MIN) / TPC_DELTA_SEMITONE - 2 );
                  accidType = Accidental::value2subtype(accidVal);
                  if (accidType == AccidentalType::NONE)
                        accidType = AccidentalType::NATURAL;
                  }
            _topAccid.setAccidentalType(accidType);
            if (accidType != AccidentalType::NONE)
                  _topAccid.layout();
            else
                  _topAccid.setbbox(QRect());
            _topAccid.rypos() = _topPos.y();
            }

      // bottom notehead
      if (_bottomPitch == INVALID_PITCH || _bottomTpc == Tpc::TPC_INVALID)
            _bottomPos.setY( (numOfLines-1) * lineDist);          // if uninitialized, set to last staff line
      else {
            bottomLine  = absStep(_bottomTpc, _bottomPitch);
            bottomLine  = relStep(bottomLine, clf);
            _bottomPos.setY(bottomLine * lineDist * 0.5);
            // compute accidental
            AccidentalType accidType;
            if (_bottomTpc - int(key) >= 13 && _bottomTpc - int(key) <= 19)
                  accidType = AccidentalType::NONE;
            else {
                  AccidentalVal accidVal = AccidentalVal( (_bottomTpc - Tpc::TPC_MIN) / TPC_DELTA_SEMITONE - 2 );
                  accidType = Accidental::value2subtype(accidVal);
                  if (accidType == AccidentalType::NONE)
                        accidType = AccidentalType::NATURAL;
                  }
            _bottomAccid.setAccidentalType(accidType);
            if (accidType != AccidentalType::NONE)
                  _bottomAccid.layout();
            else
                  _bottomAccid.setbbox(QRect());
            _bottomAccid.rypos() = _bottomPos.y();
            }

      //
      // NOTEHEAD X POS
      //
      // Note: manages colliding accidentals
      //
      qreal accNoteDist = point(score()->styleS(Sid::accidentalNoteDistance));
      xAccidOffTop      = _topAccid.width() + accNoteDist;
      xAccidOffBottom   = _bottomAccid.width() + accNoteDist;

      // if top accidental extends down more than bottom accidental extends up,
      // AND ambitus is not leaning right, bottom accidental needs to be displaced
      bool collision =
            (_topAccid.ipos().y() + _topAccid.bbox().y() + _topAccid.height()
                   > _bottomAccid.ipos().y() + _bottomAccid.bbox().y() )
            && _dir != MScore::DirectionH::RIGHT;
      if (collision) {
            // displace bottom accidental (also attempting to 'undercut' flats)
            xAccidOffBottom = xAccidOffTop +
                  ((_bottomAccid.accidentalType() == AccidentalType::FLAT
                        || _bottomAccid.accidentalType() == AccidentalType::FLAT2
                        || _bottomAccid.accidentalType() == AccidentalType::NATURAL)
                  ? _bottomAccid.width() * 0.5 : _bottomAccid.width());
            }

      switch (_dir) {
            case MScore::DirectionH::AUTO:               // noteheads one above the other
                  // left align noteheads and right align accidentals 'hanging' on the left
                  _topPos.setX(0.0);
                  _bottomPos.setX(0.0);
                  _topAccid.rxpos()       = - xAccidOffTop;
                  _bottomAccid.rxpos()    = - xAccidOffBottom;
                  break;
            case MScore::DirectionH::LEFT:               // top notehead at the left of bottom notehead
                  // place top notehead at left margin; bottom notehead at right of top head;
                  // top accid. 'hanging' on left of top head and bottom accid. 'hanging' at left of bottom head
                  _topPos.setX(0.0);
                  _bottomPos.setX(headWdt);
                  _topAccid.rxpos() = - xAccidOffTop;
                  _bottomAccid.rxpos() = collision ? - xAccidOffBottom : headWdt - xAccidOffBottom;
                  break;
            case MScore::DirectionH::RIGHT:              // top notehead at the right of bottom notehead
                  // bottom notehead at left margin; top notehead at right of bottomnotehead
                  // top accid. 'hanging' on left of top head and bottom accid. 'hanging' at left of bottom head
                  _bottomPos.setX(0.0);
                  _topPos.setX(headWdt);
                  _bottomAccid.rxpos() = - xAccidOffBottom;
                  _topAccid.rxpos() = headWdt - xAccidOffTop;
                  break;
            }

      // compute line from top note centre to bottom note centre
      QLineF fullLine(_topPos.x() + headWdt*0.5, _topPos.y(),
            _bottomPos.x() + headWdt*0.5, _bottomPos.y());
      // shorten line on each side by offsets
      qreal yDelta = _bottomPos.y() - _topPos.y();
      if (yDelta != 0.0) {
            qreal off = _spatium * LINEOFFSET_DEFAULT;
            QPointF p1 = fullLine.pointAt(off / yDelta);
            QPointF p2 = fullLine.pointAt(1 - (off / yDelta));
            _line = QLineF(p1, p2);
            }
      else
            _line = fullLine;

      QRectF headRect = QRectF(0, -0.5*_spatium, headWdt, 1*_spatium);
      setbbox(headRect.translated(_topPos).united(headRect.translated(_bottomPos))
            .united(_topAccid.bbox().translated(_topAccid.ipos()))
            .united(_bottomAccid.bbox().translated(_bottomAccid.ipos()))
            );
      }
Beispiel #29
0
void find_next_edge(Segment s, std::vector<Segment>& segments, 
                    std::set<int>& unusedIndexes, std::vector<Polygon_2>& rings)
{
  if(unusedIndexes.empty()
    || prev_size == unusedIndexes.size())
  {
    return;
  }
  
  prev_size = unusedIndexes.size();
  
  Point start = s.source();
  Point end = s.target();
  rings.back().push_back(end);
  
  std::vector<int> nextIndexes;
  for(unsigned int i = 0;i < segments.size(); i++)
  {
    if (unusedIndexes.find(i) != unusedIndexes.end())
    {
      Point source = segments.at(i).source();
      if(source == end)
      {
        nextIndexes.push_back(i);
      }
    }
  }
  if (nextIndexes.size() == 1)
  {
    int i = nextIndexes.at(0);
    unusedIndexes.erase(i);
    find_next_edge(segments.at(i), segments, unusedIndexes, rings);
  }
  else if (nextIndexes.size() > 1)
  {
    std::vector< std::pair<double, int> > nextAngles;
    for (unsigned int i = 0; i < nextIndexes.size(); i++)
    {
      int j = nextIndexes.at(i);
      Point target = segments.at(j).target();
      double angle = get_angle(start, end, target);
      nextAngles.push_back(std::pair<double, int>(angle, j));
    }
    std::sort(nextAngles.begin(), nextAngles.end());
    int i = nextAngles.begin()->second;
    unusedIndexes.erase(i);
    find_next_edge(segments.at(i), segments, unusedIndexes, rings);
  }
  
  if (!unusedIndexes.empty())
  {
    for (unsigned int i = 0; i < segments.size(); i++)
    {
      if (unusedIndexes.find(i) != unusedIndexes.end())
      {
        Polygon_2 ring;
        ring.push_back(segments.at(i).source());
        rings.push_back(ring);
        unusedIndexes.erase(i);
        find_next_edge(segments.at(i), segments, unusedIndexes, rings);
      }
    }
  }
}
Beispiel #30
0
Element* Jump::nextElement()
      {
      Segment* seg = measure()->last();
      return seg->firstElement(staffIdx());
      }