Beispiel #1
0
void SegmParams::calculateSegmParams(const Segment & s)
{
	//k = (y2-y1)/(x2-x1)
	k = (s.end().y() - s.start().y() )/(s.end().x() - s.start().x());
	//b = y1-k*x1
	b = s.start().y() - k * s.start().x();
	length = sqrt(abs(abs(s.start().x()) - abs(s.end().x())) + abs(abs(s.start().y()) - abs(s.end().y())))
}
void FieldController::LinesCalibrate( const Segment& topSegment, std::vector<Segment>& modelTopLine )
{
	std::vector<Segment>::iterator  it_modelTopLine = modelTopLine.begin();
	while (it_modelTopLine != modelTopLine.end())
	{
		if (it_modelTopLine->start().X() < topSegment.start().X())
			it_modelTopLine->start().X() = topSegment.start().X();
		if (it_modelTopLine->end().X() > topSegment.end().X())
			it_modelTopLine->end().X() = topSegment.end().X();
		++it_modelTopLine;
	}
	SortSegmetnsByY(modelTopLine);


	Segment temp(Vector2F(1.f, 1.f), Vector2F(5.f, 1.f));
	bool res = temp.inside(Vector2F(1.f, 1.f));
	res = temp.inside(Vector2F(5.f, 1.f));
	res = temp.inside(Vector2F(4.f, 1.f));
	res = temp.inside(Vector2F(5.1f, 1.f));
	res = temp.inside(Vector2F(0.9f, 1.f));

	for (int i = 0, i_end = modelTopLine.size(); i < i_end; ++i)
	{
		for (int j = i + 1, j_end = modelTopLine.size(); j < j_end; ++j)
		{
			bool startInside = (modelTopLine[i].start().X() <= modelTopLine[j].start().X()) && (modelTopLine[j].start().X() <= modelTopLine[i].end().X());
			bool endInside = (modelTopLine[i].start().X() <= modelTopLine[j].end().X()) && (modelTopLine[j].end().X() <= modelTopLine[i].end().X());
			if (startInside && endInside)
			{
				it_modelTopLine = modelTopLine.begin();
				std::advance(it_modelTopLine, j);
				modelTopLine.erase(it_modelTopLine);
				i_end = j_end = modelTopLine.size();
				i = j = 0;
			}
			else if (startInside)
			{
				modelTopLine[j].start().X() = modelTopLine[i].end().X();
			}
			else if (endInside)
			{
				modelTopLine[j].end().X() = modelTopLine[i].start().X();
			}
			else if (modelTopLine[i].start().X() > modelTopLine[j].start().X() && modelTopLine[i].end().X() < modelTopLine[j].end().X())
			{
				modelTopLine.push_back(Segment(modelTopLine[j].start(), Vector2F(modelTopLine[i].start().X(), modelTopLine[j].start().Y())));
				modelTopLine.push_back(Segment(Vector2F(modelTopLine[i].end().X(), modelTopLine[j].end().Y()), modelTopLine[j].end()));
				it_modelTopLine = modelTopLine.begin();
				std::advance(it_modelTopLine, j);
				modelTopLine.erase(it_modelTopLine);
				i_end = j_end = modelTopLine.size();
			}
		}
	}
}
Beispiel #3
0
void 
SegmentLinker::refreshSegment(Segment *seg)
{
    timeT startTime = seg->getStartTime();
    eraseNonIgnored(seg,seg->begin(),seg->end());
    
    //find another segment
    Segment *sourceSeg = 0;
    Segment *tempClone = 0;
    
    LinkedSegmentParamsList::iterator itr;
    for (itr = m_linkedSegmentParamsList.begin(); 
        itr!= m_linkedSegmentParamsList.end(); ++itr) {
        
        LinkedSegmentParams &linkedSegParams = *itr;
        Segment *other = linkedSegParams.m_linkedSegment;
        if (other != seg) {
            sourceSeg = other;
            break;
        }
    }
    
    if (!sourceSeg) {
        //make a temporary clone
        tempClone = createLinkedSegment(seg);
        sourceSeg = tempClone;
    }
        
    timeT sourceSegStartTime = sourceSeg->getStartTime();
    Segment::const_iterator segitr;
    for(segitr=sourceSeg->begin(); segitr!=sourceSeg->end(); ++segitr) {
        const Event *refEvent = *segitr;

        timeT refEventTime = refEvent->getAbsoluteTime() - sourceSegStartTime;
        timeT freshEventTime = refEventTime+startTime;
        
        insertMappedEvent(seg,refEvent,freshEventTime,
                          seg->getLinkTransposeParams().m_semitones,
                          seg->getLinkTransposeParams().m_steps);
    }
    
    if (tempClone) {
        delete tempClone;
    }
}
Beispiel #4
0
Segment *
Clipboard::newSegment(const EventSelection *copyFrom)
{
    // create with clone function so as to inherit track, instrument etc
    // but clone as a segment only, even if it's actually a linked segment
    Segment *s = copyFrom->getSegment().clone(false);
    s->erase(s->begin(), s->end());

    const EventSelection::eventcontainer &events(copyFrom->getSegmentEvents());
    for (EventSelection::eventcontainer::const_iterator i = events.begin();
         i != events.end(); ++i) {
        s->insert(new Event(**i));
    }

    m_segments.insert(s);
    m_partial = true;
    return s;
}
Beispiel #5
0
//ostream & operator<<(ostream & os, pair<int, Segment> paral)
//{
//	os<<"oYparalEntry: [ k="<<paral.first<<" | "<<paral.second<<" ]";
//	return os;
//}
//ostream & operator<<(ostream & os, const multimap<SegmParams, Segment>::iterator normal)
//{
//	os<<"oKsegmEntry: [ k="<<normal->first<<" | "<<normal->second<<" ]";
//	return os;
//}
void parseAndInit(const string & message, Segment & s)//we should construct a dflt segment before
{
	//incoming format <"fn"/"mk"/"rm">[234,54223;23443,2342] or "quit" mk[3,4;4,5]
	size_t found_cm = message.find(',');
	size_t found_sc = message.find(';');
	string x_tmp = message.substr(3, found_cm-3);
	string y_tmp = message.substr(found_cm+1, found_sc - found_cm-1);
	int x = stoi(x_tmp);
	int y = stoi(y_tmp);
	Point st(x, y);
	s.start() = st;
	found_cm = message.find(',', found_sc+1);
	x_tmp = message.substr(found_sc+1, found_cm - found_sc-1);
	y_tmp = message.substr(found_cm+1, message.length()-1 - found_sc-1);
	x = stoi(x_tmp);
	y = stoi(y_tmp);
	Point en(x, y);
	s.end() = en;
}
// Find evenly-spaced notes
// @param firstBeat A note Event performed on the first beat.
// @param secondBeat A note Event performed on the second beat.
// @param s The segment to look in for further events.
// @return Beat-defining data as a BeatEventVector
// @author Tom Breton (Tehom)
SelectAddEvenNotesCommand::BeatEventVector
SelectAddEvenNotesCommand::findBeatEvents(Segment &s,
                                   Event *firstBeat,
                                   Event *secondBeat)
{
    // Fixed parameters
    const float marginTimeRatio = 0.77;
    const float minTimeRatio = marginTimeRatio;
    const float maxTimeRatio = 1 / minTimeRatio;

    // Storage for the results.  We add the first two beats
    // immediately.  Caller promises us that they make sense.
    BeatEventVector result;
    result.push_back(BeatEvent(firstBeat, 0));
    result.push_back(BeatEvent(secondBeat, 0));

    // State variables tracking the most recent beat we've found.
    timeT currentBeatTime = secondBeat->getAbsoluteTime();
    timeT prevKnownBeatDuration =
        currentBeatTime - firstBeat->getAbsoluteTime();
    if (prevKnownBeatDuration <= 0) { return result; }

    // State variables tracking the current noteless stretch.  It may
    // be empty.
    int numSkippedBeats = 0;
    timeT prevKnownBeatTime = currentBeatTime;

    /**
     * We assume the beat-defining notes are separated by roughly the
     * same time-interval.  We handle noteless stretches where we
     * expect beats by counting the number of beats we missed.  We
     * drop the noteless stretch after the last true beat we find
     * because it can't do anything useful.  Stretches that contain
     * just notes that are too far from rhythmic expectations are
     * treated as noteless stretches.
     **/
    
    // Find beat-defining notes in the segment
    while (true) {

        // The time we would expect a new beat if the rhythm and tempo
        // were exactly constant.
        timeT expectedNoteTime = currentBeatTime + prevKnownBeatDuration;

        // An acceptable interval for the next beat.
        timeT minNextDuration = float(prevKnownBeatDuration) * minTimeRatio;
        timeT maxNextDuration = float(prevKnownBeatDuration) * maxTimeRatio;
        timeT minNextNoteTime = currentBeatTime + minNextDuration;
        timeT maxNextNoteTime = currentBeatTime + maxNextDuration;

        Segment::const_iterator startRangeIter = s.findTime(minNextNoteTime);
        Segment::const_iterator endRangeIter = s.findTime(maxNextNoteTime);

       // Break if there won't be more notes to find.
       if (startRangeIter == s.end()) { break; }

       // Candidate variable.  NULL means nothing found.
       Event *nextBeat = 0;
       // Scoring variable, how much the best candidate note differs
       // from expectedNoteTime.  Smaller is better.
       timeT nearestMiss = std::numeric_limits<timeT>::max();
       
       for (Segment::const_iterator i = startRangeIter;
            i != endRangeIter;
            ++i) {
           Event *e = *i;
           // Only consider notes.
           if (e->isa(Note::EventType)) {
               const timeT missedBy =
                   std::abs(e->getAbsoluteTime() - expectedNoteTime);

               // Track the best candidate.
               if (missedBy < nearestMiss) {
                   nextBeat = e;
                   nearestMiss = missedBy;
               }
           }
       }

       
       if (nextBeat) {
           const timeT nextBeatTime = nextBeat->getAbsoluteTime();
           const timeT stretchDuration = nextBeatTime - prevKnownBeatTime;
           const int numIncludedBeats = numSkippedBeats + 1;
           // The absolute time of the beat immediately before
           // nextBeatTime, possibly calculated by BeatInterpolator
           timeT prevFoundBeatTime =
               (numSkippedBeats > 0) ?
               (prevKnownBeatTime +
                BeatInterpolator::
                getLastBeatRelativeTime(stretchDuration,
                                        prevKnownBeatDuration,
                                        numIncludedBeats)) :
               currentBeatTime;

           // Add this beat
           result.push_back(BeatEvent(nextBeat,
                                      numSkippedBeats,
                                      BeatInterpolator(stretchDuration,
                                                       prevKnownBeatDuration,
                                                       numIncludedBeats)));

           // Since we'll continue from a known beat, record that we
           // haven't skipped any beats.
           numSkippedBeats = 0;

           // Set variables for the next iteration of the loop.
           prevKnownBeatDuration = nextBeatTime - prevFoundBeatTime;
           currentBeatTime = nextBeatTime;
           prevKnownBeatTime = nextBeatTime;
       } else {
           // If we found no candidates, we began or are already in a
           // noteless stretch.  In either case we count one more
           // missed beat and step forward in time.
           ++numSkippedBeats;
           currentBeatTime = expectedNoteTime;
       }
    }

    return result;
}
Beispiel #7
0
Segment::Segment(const Segment& source) : _myId(_freeID++), _a(source.start()), _b(source.end()){
#ifdef NDEBUG
	cout << "Segment " << _myId << ": copy constructor. Source: " << source;
#endif
}
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;
}
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 #10
0
 bool Rectangle::overlaps(Segment const& segment) const noexcept
 {
     return (contains(segment.start()) || contains(segment.end()) || intersects(segment));
 }
Beispiel #11
0
bool is_on_line ( const Point & a, const Segment & obj )
{
	return ( obj.length() == Segment(a, obj.start()).length() + Segment(a, obj.end()).length() );
}
Beispiel #12
0
bool belongs_to ( const Point & pt, const Segment & seg )
{
	return seg.length() == fabs ( Segment( pt, seg.start() ).length() - Segment( pt, seg.end() ).length() );
}
Beispiel #13
0
void
MatrixMover::handleLeftButtonPress(const MatrixMouseEvent *e)
{
    MATRIX_DEBUG << "MatrixMover::handleLeftButtonPress() : snapped time = " << e->snappedLeftTime << ", el = " << e->element << endl;

    if (!e->element) return;

    // Check the scene's current segment (apparently not necessarily the same
    // segment referred to by the scene's current view segment) for this event;
    // return if not found, indicating that this event is from some other,
    // non-active segment.
    //
    // I think notation just makes whatever segment active when you click an
    // event outside the active segment, and I think that's what this code
    // attempted to do too.  I couldn't get that to work at all.  This is better
    // than being able to click on non-active elements to create new events by
    // accident, and will probably fly.  Especially since the multi-segment
    // matrix is new, and we're defining the terms of how it works.
    Segment *segment = m_scene->getCurrentSegment();
    if (!segment) return;
    bool found = false;
    for (Segment::iterator i = segment->begin(); i != segment->end(); ++i) {
        if ((*i) == e->element->event()) found = true;
    }

    if (!found) {
        MATRIX_DEBUG << "Clicked element not owned by active segment.  Returning..." << endl;
        return;
    }

    m_currentViewSegment = e->viewSegment;

    m_currentElement = e->element;
    m_clickSnappedLeftTime = e->snappedLeftTime;

    m_quickCopy = (e->modifiers & Qt::ControlModifier);

    if (!m_duplicateElements.empty()) {
        for (size_t i = 0; i < m_duplicateElements.size(); ++i) {
            delete m_duplicateElements[i]->event();
            delete m_duplicateElements[i];
        }
        m_duplicateElements.clear();
    }

    // Add this element and allow movement
    //
    EventSelection* selection = m_scene->getSelection();
    Event *event = m_currentElement->event();

    if (selection) {
        EventSelection *newSelection;
        
        if ((e->modifiers & Qt::ShiftModifier) ||
            selection->contains(event)) {
            newSelection = new EventSelection(*selection);
        } else {
            newSelection = new EventSelection(m_currentViewSegment->getSegment());
        }
        
        // if the selection already contains the event, remove it from the
        // selection if shift is pressed
        if (selection->contains(event)) {
            if (e->modifiers & Qt::ShiftModifier) {
                newSelection->removeEvent(event);
            }
        } else {
            newSelection->addEvent(event);
        }
        m_scene->setSelection(newSelection, true);
        selection = newSelection;
    } else {
        m_scene->setSingleSelectedEvent(m_currentViewSegment,
                                        m_currentElement, true);
    }
    
    long velocity = m_widget->getCurrentVelocity();
    event->get<Int>(BaseProperties::VELOCITY, velocity);

    long pitchOffset = m_currentViewSegment->getSegment().getTranspose();

    long pitch = 60;
    event->get<Int>(BaseProperties::PITCH, pitch);

    // We used to m_scene->playNote() here, but the new concert pitch matrix was
    // playing chords the first time I clicked a note.  Investigation with
    // KMidiMon revealed two notes firing nearly simultaneously, and with
    // segments of 0 transpose, they were simply identical to each other.  One
    // of them came from here, and this was the one sounding at the wrong pitch
    // in transposed segments.  I've simply removed it with no apparent ill side
    // effects, and a problem solved super cheap.

    m_lastPlayedPitch = pitch;

    if (m_quickCopy && selection) {
        for (EventSelection::eventcontainer::iterator i =
                 selection->getSegmentEvents().begin();
             i != selection->getSegmentEvents().end(); ++i) {

            MatrixElement *duplicate = new MatrixElement
                (m_scene, new Event(**i),
                 m_widget->isDrumMode(), pitchOffset);

            m_duplicateElements.push_back(duplicate);
        }
    }
}
Beispiel #14
0
Segment::Segment ( const Segment & seg ) :
	_a ( seg.start() ),
	_b ( seg.end() )
{
}
Beispiel #15
0
void
Clipboard::newSegment(const Segment *copyFrom, timeT from, timeT to,
    bool expandRepeats)
{
    // create with copy ctor so as to inherit track, instrument etc
    Segment *s = copyFrom->clone(false);

    // If the segment is within the time range
    if (from <= s->getStartTime() && to >= s->getEndMarkerTime()) {
        // Insert the whole thing.
        m_segments.insert(s);

        // don't change m_partial as we are inserting a complete segment

        return;
    }

    // Only a portion of the source segment will be used.

    const timeT segStart = copyFrom->getStartTime();
    const timeT segEndMarker = copyFrom->getEndMarkerTime();
    timeT segDuration = segEndMarker - segStart;
    
    // We can't copy starting prior to the start of the segment.
    if (from < segStart)
        from = segStart;

    int firstRepeat = 0;
    int lastRepeat = 0;

    if (!copyFrom->isRepeating() || segDuration <= 0) {
        expandRepeats = false;
    }

    if (expandRepeats) {
        firstRepeat = (from - segStart) / segDuration;
        to = std::min(to, copyFrom->getRepeatEndTime());
        lastRepeat = (to - segStart) / segDuration;
    }

    s->setRepeating(false);
    
    if (s->getType() == Segment::Audio) {

        Composition *c = copyFrom->getComposition();

        for (int repeat = firstRepeat; repeat <= lastRepeat; ++repeat) {

            timeT wrappedFrom = segStart;
            timeT wrappedTo = segEndMarker;

            if (!expandRepeats) {
                wrappedFrom = from;
                wrappedTo = to;
            } else {
                if (repeat == firstRepeat) {
                    wrappedFrom = segStart + (from - segStart) % segDuration;
                }
                if (repeat == lastRepeat) {
                    wrappedTo = segStart + (to - segStart) % segDuration;
                }
            }

            if (wrappedFrom > segStart) {
                if (c) {
                    s->setAudioStartTime
                        (s->getAudioStartTime() +
                         c->getRealTimeDifference(segStart + repeat * segDuration,
                                                  from));
                }
                s->setStartTime(from);
            } else {
                s->setStartTime(segStart + repeat * segDuration);
            }

            if (wrappedTo < segEndMarker) {
                s->setEndMarkerTime(to);
                if (c) {
                    s->setAudioEndTime
                        (s->getAudioStartTime() +
                         c->getRealTimeDifference(segStart + repeat * segDuration,
                                                  to));
                }
            } else {
                s->setEndMarkerTime(segStart + (repeat + 1) * segDuration);
            }

            m_segments.insert(s);
            if (repeat < lastRepeat) {
                s = copyFrom->clone(false);
                s->setRepeating(false);
            }
        }

        m_partial = true;
        return;
    }

    // We have a normal (MIDI) segment.

    s->erase(s->begin(), s->end());
    
    for (int repeat = firstRepeat; repeat <= lastRepeat; ++repeat) {

        Segment::const_iterator ifrom = copyFrom->begin();
        Segment::const_iterator ito = copyFrom->end();

        if (!expandRepeats) {
            ifrom = copyFrom->findTime(from);
            ito = copyFrom->findTime(to);
        } else {
            if (repeat == firstRepeat) {
                ifrom = copyFrom->findTime
                    (segStart + (from - segStart) % segDuration);
            }
            if (repeat == lastRepeat) {
                ito = copyFrom->findTime
                    (segStart + (to - segStart) % segDuration);
            }
        }

        // For each event in the time range and before the end marker.
        for (Segment::const_iterator i = ifrom;
             i != ito && copyFrom->isBeforeEndMarker(i); ++i) {

            Event *e = (*i)->copyMoving(repeat * segDuration);

            s->insert(e);
        }
    }

    if (expandRepeats)
        s->setEndMarkerTime(to);

    // Make sure the end of the segment doesn't go past the end of the range.
    // Need to use the end marker time from the original segment, not s, 
    // because its value may depend on the composition it's in.
    if (segEndMarker > to)
        s->setEndMarkerTime(to);

    // Fix the beginning.
    
    timeT firstEventTime = s->getStartTime();
    
    // if the beginning was chopped off and the first event isn't at the start
    if (from > segStart  &&  firstEventTime > from) {
        // Expand the beginning to the left so that it starts at the expected
        // time (from).
        s->fillWithRests(from, firstEventTime);
    }

    // Fix zero-length segments.
    
    // if s is zero length
    if (s->getStartTime() == s->getEndMarkerTime()) {
        // Figure out what start and end time would look right.
        timeT finalStartTime = ((segStart > from) ? segStart : from);
        timeT finalEndTime = ((segEndMarker < to) ? segEndMarker : to);
        // Fill it up so it appears.
        s->fillWithRests(finalStartTime, finalEndTime);
    }

    m_segments.insert(s);

    m_partial = true;
}
Beispiel #16
0
const bool checkIfParallel(const Segment & s)
{
	return s.start().x() == s.end().x();
}
Beispiel #17
0
	Segment(const Segment & s): m_start(s.start()), m_end(s.end()) { }
Beispiel #18
0
Segment::Segment(const Segment& segment) : _start(segment.start()), _end(segment.end()), _myID(++_freeID) {
	#ifndef NDEBUG

	#endif
	return;
};
Beispiel #19
0
double magic_area ( const Segment & seg, const Point & pt )
{
	return magic_area (seg.start(), seg.end(), pt);
}
/// Initialize ExpandFigurationCommand
/// @author Tom Breton (Tehom)
void
ExpandFigurationCommand::initialise(SegmentSelection selection)
{
    FigurationVector figs;
    int figSourceID = -1;
    bool gotFigSource = false;

    RG_DEBUG << "Initializing ExpandFigurationCommand" << endl;

    // Update, because if we need new IDs they mustn't duplicate old
    // IDs, so we must be up to date on what IDs are there.
    SegmentFigData::SegmentFigDataMap segMap = 
        SegmentFigData::getInvolvedSegments(true, this);
    for (SegmentSelection::iterator i = selection.begin();
         i != selection.end();
         ++i) {
        SegmentFigData& segmentData =
            SegmentFigData::findOrAdd(segMap, *i);
        
        // If it's used here, it's not uninvolved, so unless it's a
        // figuration, it's a chord source.
        if (segmentData.isa(SegmentFigData::Uninvolved)) {
            segmentData.convertType(SegmentFigData::ChordSource);
        }
        segmentData.addTagIfNeeded(*i, this);
        if (gotFigSource ||
            !segmentData.isa(SegmentFigData::FigurationSource))
            { continue; }

        figSourceID = segmentData.getID();
        figs = FigurationSourceMap::getFigurations(*i);
        if (!figs.empty())
            { gotFigSource = true; }
    }
    // If we didn't find a real figuration, there's nothing to do.
    if (!gotFigSource) { return; }

    SourcedFiguration sourcedfigs(figSourceID, figs);
    
    // Expand figuration in each segment in selection except the
    // figuration segment itself.
    for (SegmentSelection::iterator i = selection.begin();
         i != selection.end();
         ++i) {
        Segment *s = (*i);
        SegmentFigData::SegmentFigDataMap::iterator it = segMap.find(*i);
        Q_ASSERT_X(it != segMap.end(),
                   "ExpandFigurationCommand::initialise",
                   "didn't find the segment");
        SegmentFigData& segmentData = it->second;
        
        if (!segmentData.isa(SegmentFigData::ChordSource))
            { continue; }

        // Make a target segment
        Segment *target = s->clone(false);
        // Temporarily attach it to composition so that expand can
        // work.
        m_composition->weakAddSegment(target);

        target->clear();
        target->fillWithRests(s->getEndTime());
        SegmentFigData::addTag(target, this, SegmentID::Target);
        m_newSegments.insert(target);

        /** Add notes to target segment **/
        for (Segment::iterator e = s->begin();
             e != s->end();
             ++e) {
            // Non-notes they don't imply there's a chord here.
            // We add them to target segment in case they are
            // clefs or key changes.
            if ((*e)->isa(SegmentID::EventType)) {
                continue;
            }
            if (!(*e)->isa(Note::EventType)) {
                target->insert(new Event(**e));
            }
        }


        // rawStartTime is the apparent start time before we take bars
        // into account.  We step it along the composition, finding
        // valid places to expand.  Specifically, on bar lines not
        // already part of an expansion.
        timeT rawStartTime = s->getStartTime();
        while (1) {
            timeT figurationStartTime = rawStartTimeToExact(rawStartTime);

            if (rawStartTime >= s->getEndTime())
                { break; }

            timeT timePastFiguration =
                SegmentFigData::expand(sourcedfigs,
                                       ChordSegment(s, segmentData.getID()),
                                       target, figurationStartTime);

            // If we didn't expand, ensure we don't try endlessly at
            // the same place.
            if (timePastFiguration == figurationStartTime) {
                ++timePastFiguration;
            }
            rawStartTime = timePastFiguration;
        }

        // Detach from composition, because SegmentInsertCommand does
        // the actual placing
        m_composition->weakDetachSegment(target);

        
        Command *c =
            new SegmentInsertCommand(m_composition, target, s->getTrack());
        addCommand(c);
    }

}
Beispiel #21
0
void
AddLayerCommand::execute()
{ 
    if (!m_segment) return;

    Segment *layer = new Segment();

    layer->setTrack(m_segment->getTrack());
    layer->setStartTime(m_segment->getStartTime());
    m_composition.addSegment(layer);
    layer->setEndTime(m_segment->getEndTime());

    std::string label = m_segment->getLabel();
    label += tr(" - layer").toStdString();
    layer->setLabel(label);

    layer->setHighestPlayable(m_segment->getHighestPlayable());
    layer->setLowestPlayable(m_segment->getLowestPlayable());
    layer->setTranspose(m_segment->getTranspose());

    // fill the segment with rests, so we can make them invisible
    layer->fillWithRests(m_segment->getStartTime(), m_segment->getEndTime());

    for (Segment::iterator i = m_segment->begin(); i != m_segment->end(); ++i) {
        // copy over any clefs or key signatures, as these are needed to
        // maintain compatibility between segments
        if ((*i)->isa(Clef::EventType) ||
            (*i)->isa(Key::EventType)) {

            layer->insert(new Event(**i));

        }
    }

    // set everything in the layer segment invisible
    for (Segment::iterator i = layer->begin(); i != layer->end(); ++i) {
        (*i)->set<Bool>(BaseProperties::INVISIBLE, true);

        // raise the heights of alternate voice rests to get them out of the
        // middle of the staff, where they may be easier to deal with
        if ((*i)->isa(Note::EventRestType)) (*i)->setMaybe<Int>(BaseProperties::DISPLACED_Y, -1000);

    }

    // get the total number of colors in the map
    int maxColors = m_composition.getSegmentColourMap().size();

    // get the color index for the segment used as the template for the new
    // empty one we're creating
    int index = m_segment->getColourIndex();

    // with the default color map (the only one I care about anymore) a
    // difference of +5 guarantees enough contrast to make the segment changer
    // widget, raw note ruler, and track headers show enough contrast to be
    // useful as an indication that this segment is not the same as the one it
    // is patterned after
    index += 5;

    // if we went past the end of the color map, just roll back to 0, because
    // this will happen so infrequently in use it's not worth a lot of fancy
    // handling, and anyway 0 will be a contrast from what's sitting on the end
    // of the standard color map, so it will still be functional
    if (index > maxColors) index = 0;
    layer->setColourIndex(index);
    
    // now what other gotchas are there?

    // now m_segment goes from being the input template to what we'll return if
    // asked
    m_segment = layer;
    m_detached = false;
}