|
@@ -161,6 +161,10 @@ export class GraphicalMusicSheet {
|
|
this.leadSheet = value;
|
|
this.leadSheet = value;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
+ * Calculate the Absolute Positions from the Relative Positions.
|
|
|
|
+ * @param graphicalMusicSheet
|
|
|
|
+ */
|
|
public static transformRelativeToAbsolutePosition(graphicalMusicSheet: GraphicalMusicSheet): void {
|
|
public static transformRelativeToAbsolutePosition(graphicalMusicSheet: GraphicalMusicSheet): void {
|
|
for (let i: number = 0; i < graphicalMusicSheet.MusicPages.length; i++) {
|
|
for (let i: number = 0; i < graphicalMusicSheet.MusicPages.length; i++) {
|
|
let pageAbsolute: PointF2D = graphicalMusicSheet.MusicPages[i].setMusicPageAbsolutePosition(i, graphicalMusicSheet.ParentMusicSheet.rules);
|
|
let pageAbsolute: PointF2D = graphicalMusicSheet.MusicPages[i].setMusicPageAbsolutePosition(i, graphicalMusicSheet.ParentMusicSheet.rules);
|
|
@@ -201,6 +205,14 @@ export class GraphicalMusicSheet {
|
|
return undefined;
|
|
return undefined;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
+ * Search the MeasureList for a certain GraphicalStaffEntry with the given SourceStaffEntry,
|
|
|
|
+ * at a certain verticalIndex (eg a corresponnding Staff), starting at a specific horizontalIndex (eg specific GraphicalMeasure).
|
|
|
|
+ * @param staffIndex
|
|
|
|
+ * @param measureIndex
|
|
|
|
+ * @param sourceStaffEntry
|
|
|
|
+ * @returns {any}
|
|
|
|
+ */
|
|
public findGraphicalStaffEntryFromMeasureList(staffIndex: number, measureIndex: number, sourceStaffEntry: SourceStaffEntry): GraphicalStaffEntry {
|
|
public findGraphicalStaffEntryFromMeasureList(staffIndex: number, measureIndex: number, sourceStaffEntry: SourceStaffEntry): GraphicalStaffEntry {
|
|
for (let i: number = measureIndex; i < this.measureList.length; i++) {
|
|
for (let i: number = measureIndex; i < this.measureList.length; i++) {
|
|
let graphicalMeasure: StaffMeasure = this.measureList[i][staffIndex];
|
|
let graphicalMeasure: StaffMeasure = this.measureList[i][staffIndex];
|
|
@@ -214,6 +226,13 @@ export class GraphicalMusicSheet {
|
|
return undefined;
|
|
return undefined;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
+ * Return the next (to the right) not null GraphicalStaffEntry from a given Index.
|
|
|
|
+ * @param staffIndex
|
|
|
|
+ * @param measureIndex
|
|
|
|
+ * @param graphicalStaffEntry
|
|
|
|
+ * @returns {any}
|
|
|
|
+ */
|
|
public findNextGraphicalStaffEntry(staffIndex: number, measureIndex: number, graphicalStaffEntry: GraphicalStaffEntry): GraphicalStaffEntry {
|
|
public findNextGraphicalStaffEntry(staffIndex: number, measureIndex: number, graphicalStaffEntry: GraphicalStaffEntry): GraphicalStaffEntry {
|
|
let graphicalMeasure: StaffMeasure = graphicalStaffEntry.parentMeasure;
|
|
let graphicalMeasure: StaffMeasure = graphicalStaffEntry.parentMeasure;
|
|
let graphicalStaffEntryIndex: number = graphicalMeasure.staffEntries.indexOf(graphicalStaffEntry);
|
|
let graphicalStaffEntryIndex: number = graphicalMeasure.staffEntries.indexOf(graphicalStaffEntry);
|
|
@@ -265,6 +284,10 @@ export class GraphicalMusicSheet {
|
|
return orderedMeasures;
|
|
return orderedMeasures;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
+ * Return the active Clefs at the start of the first SourceMeasure.
|
|
|
|
+ * @returns {ClefInstruction[]}
|
|
|
|
+ */
|
|
public initializeActiveClefs(): ClefInstruction[] {
|
|
public initializeActiveClefs(): ClefInstruction[] {
|
|
let activeClefs: ClefInstruction[] = [];
|
|
let activeClefs: ClefInstruction[] = [];
|
|
let firstSourceMeasure: SourceMeasure = this.musicSheet.getFirstSourceMeasure();
|
|
let firstSourceMeasure: SourceMeasure = this.musicSheet.getFirstSourceMeasure();
|
|
@@ -301,6 +324,11 @@ export class GraphicalMusicSheet {
|
|
return undefined;
|
|
return undefined;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
+ * Create the VerticalContainer and adds it to the List at the correct Timestamp position.
|
|
|
|
+ * @param timestamp
|
|
|
|
+ * @returns {any}
|
|
|
|
+ */
|
|
public getOrCreateVerticalContainer(timestamp: Fraction): VerticalGraphicalStaffEntryContainer {
|
|
public getOrCreateVerticalContainer(timestamp: Fraction): VerticalGraphicalStaffEntryContainer {
|
|
if (this.verticalGraphicalStaffEntryContainers.length === 0 ||
|
|
if (this.verticalGraphicalStaffEntryContainers.length === 0 ||
|
|
(CollectionUtil.getLastElement(this.verticalGraphicalStaffEntryContainers).AbsoluteTimestamp).lt(timestamp)) {
|
|
(CollectionUtil.getLastElement(this.verticalGraphicalStaffEntryContainers).AbsoluteTimestamp).lt(timestamp)) {
|
|
@@ -323,6 +351,15 @@ export class GraphicalMusicSheet {
|
|
return undefined;
|
|
return undefined;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
+ * Does a binary search on the container list and returns the VerticalContainer with the given Timestamp.
|
|
|
|
+ * The search begins at startIndex, if given.
|
|
|
|
+ * If the timestamp cannot be found, null is returned.
|
|
|
|
+ * @param timestamp - The timestamp for which the container shall be found.
|
|
|
|
+ * @param startIndex - The index from which the search starts in the container list.
|
|
|
|
+ * @returns {any}
|
|
|
|
+ * @constructor
|
|
|
|
+ */
|
|
public GetVerticalContainerFromTimestamp(timestamp: Fraction, startIndex: number = 0): VerticalGraphicalStaffEntryContainer {
|
|
public GetVerticalContainerFromTimestamp(timestamp: Fraction, startIndex: number = 0): VerticalGraphicalStaffEntryContainer {
|
|
let index: number = CollectionUtil.binarySearch(this.verticalGraphicalStaffEntryContainers,
|
|
let index: number = CollectionUtil.binarySearch(this.verticalGraphicalStaffEntryContainers,
|
|
new VerticalGraphicalStaffEntryContainer(0, timestamp),
|
|
new VerticalGraphicalStaffEntryContainer(0, timestamp),
|
|
@@ -334,6 +371,12 @@ export class GraphicalMusicSheet {
|
|
return undefined;
|
|
return undefined;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
+ * Perform a binary search for the absolute given Timestamp in all the GraphicalVerticalContainers.
|
|
|
|
+ * @param musicTimestamp
|
|
|
|
+ * @returns {number}
|
|
|
|
+ * @constructor
|
|
|
|
+ */
|
|
public GetInterpolatedIndexInVerticalContainers(musicTimestamp: Fraction): number {
|
|
public GetInterpolatedIndexInVerticalContainers(musicTimestamp: Fraction): number {
|
|
let containers: VerticalGraphicalStaffEntryContainer[] = this.verticalGraphicalStaffEntryContainers;
|
|
let containers: VerticalGraphicalStaffEntryContainer[] = this.verticalGraphicalStaffEntryContainers;
|
|
let leftIndex: number = 0;
|
|
let leftIndex: number = 0;
|
|
@@ -358,6 +401,8 @@ export class GraphicalMusicSheet {
|
|
leftIndex = middleIndex;
|
|
leftIndex = middleIndex;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ // no interpolation needed
|
|
if (leftIndex === rightIndex) {
|
|
if (leftIndex === rightIndex) {
|
|
return this.verticalGraphicalStaffEntryContainers.indexOf(containers[leftIndex]);
|
|
return this.verticalGraphicalStaffEntryContainers.indexOf(containers[leftIndex]);
|
|
}
|
|
}
|
|
@@ -370,10 +415,18 @@ export class GraphicalMusicSheet {
|
|
}
|
|
}
|
|
let diff: number = rightTS.RealValue - leftTS.RealValue;
|
|
let diff: number = rightTS.RealValue - leftTS.RealValue;
|
|
let diffTS: number = rightTS.RealValue - musicTimestamp.RealValue;
|
|
let diffTS: number = rightTS.RealValue - musicTimestamp.RealValue;
|
|
|
|
+
|
|
|
|
+ // estimate the interpolated index
|
|
foundIndex = rightIndex - (diffTS / diff);
|
|
foundIndex = rightIndex - (diffTS / diff);
|
|
return Math.min(foundIndex, this.verticalGraphicalStaffEntryContainers.length);
|
|
return Math.min(foundIndex, this.verticalGraphicalStaffEntryContainers.length);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
+ * Get a List with the indeces of all the visible GraphicalMeasures and calculates their
|
|
|
|
+ * corresponding indices in the first SourceMeasure, taking into account Instruments with multiple Staves.
|
|
|
|
+ * @param visibleMeasures
|
|
|
|
+ * @returns {number[]}
|
|
|
|
+ */
|
|
public getVisibleStavesIndecesFromSourceMeasure(visibleMeasures: StaffMeasure[]): number[] {
|
|
public getVisibleStavesIndecesFromSourceMeasure(visibleMeasures: StaffMeasure[]): number[] {
|
|
let visibleInstruments: Instrument[] = [];
|
|
let visibleInstruments: Instrument[] = [];
|
|
let visibleStavesIndeces: number[] = [];
|
|
let visibleStavesIndeces: number[] = [];
|
|
@@ -394,6 +447,12 @@ export class GraphicalMusicSheet {
|
|
return visibleStavesIndeces;
|
|
return visibleStavesIndeces;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
+ * Returns the GraphicalMeasure with the given SourceMeasure as Parent at the given Index.
|
|
|
|
+ * @param sourceMeasure
|
|
|
|
+ * @param index
|
|
|
|
+ * @returns {any}
|
|
|
|
+ */
|
|
public getGraphicalMeasureFromSourceMeasureAndIndex(sourceMeasure: SourceMeasure, index: number): StaffMeasure {
|
|
public getGraphicalMeasureFromSourceMeasureAndIndex(sourceMeasure: SourceMeasure, index: number): StaffMeasure {
|
|
for (let i: number = 0; i < this.measureList.length; i++) {
|
|
for (let i: number = 0; i < this.measureList.length; i++) {
|
|
if (this.measureList[i][0].parentSourceMeasure === sourceMeasure) {
|
|
if (this.measureList[i][0].parentSourceMeasure === sourceMeasure) {
|
|
@@ -420,12 +479,16 @@ export class GraphicalMusicSheet {
|
|
public GetNearesNote(clickPosition: PointF2D, maxClickDist: PointF2D): GraphicalNote {
|
|
public GetNearesNote(clickPosition: PointF2D, maxClickDist: PointF2D): GraphicalNote {
|
|
let initialSearchArea: number = 10;
|
|
let initialSearchArea: number = 10;
|
|
let foundNotes: GraphicalNote[] = [];
|
|
let foundNotes: GraphicalNote[] = [];
|
|
|
|
+
|
|
|
|
+ // Prepare search area
|
|
let region: BoundingBox = new BoundingBox();
|
|
let region: BoundingBox = new BoundingBox();
|
|
region.BorderLeft = clickPosition.x - initialSearchArea;
|
|
region.BorderLeft = clickPosition.x - initialSearchArea;
|
|
region.BorderTop = clickPosition.y - initialSearchArea;
|
|
region.BorderTop = clickPosition.y - initialSearchArea;
|
|
region.BorderRight = clickPosition.x + initialSearchArea;
|
|
region.BorderRight = clickPosition.x + initialSearchArea;
|
|
region.BorderBottom = clickPosition.y + initialSearchArea;
|
|
region.BorderBottom = clickPosition.y + initialSearchArea;
|
|
region.AbsolutePosition = new PointF2D(0, 0);
|
|
region.AbsolutePosition = new PointF2D(0, 0);
|
|
|
|
+
|
|
|
|
+ // Search for StaffEntries in region
|
|
for (let idx: number = 0, len: number = this.MusicPages.length; idx < len; ++idx) {
|
|
for (let idx: number = 0, len: number = this.MusicPages.length; idx < len; ++idx) {
|
|
let graphicalMusicPage: GraphicalMusicPage = this.MusicPages[idx];
|
|
let graphicalMusicPage: GraphicalMusicPage = this.MusicPages[idx];
|
|
let entries: GraphicalNote[] = graphicalMusicPage.PositionAndShape.getObjectsInRegion<GraphicalNote>(region);
|
|
let entries: GraphicalNote[] = graphicalMusicPage.PositionAndShape.getObjectsInRegion<GraphicalNote>(region);
|
|
@@ -442,6 +505,8 @@ export class GraphicalMusicSheet {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ // Get closest entry
|
|
let closest: GraphicalNote = undefined;
|
|
let closest: GraphicalNote = undefined;
|
|
for (let idx: number = 0, len: number = foundNotes.length; idx < len; ++idx) {
|
|
for (let idx: number = 0, len: number = foundNotes.length; idx < len; ++idx) {
|
|
let note: GraphicalNote = foundNotes[idx];
|
|
let note: GraphicalNote = foundNotes[idx];
|
|
@@ -461,12 +526,15 @@ export class GraphicalMusicSheet {
|
|
if (closest !== undefined) {
|
|
if (closest !== undefined) {
|
|
return closest;
|
|
return closest;
|
|
}
|
|
}
|
|
|
|
+ // TODO No staff entry was found. Feedback?
|
|
|
|
+ // throw new ArgumentException("No staff entry found");
|
|
return undefined;
|
|
return undefined;
|
|
}
|
|
}
|
|
|
|
|
|
public GetClickableLabel(clickPosition: PointF2D): GraphicalLabel {
|
|
public GetClickableLabel(clickPosition: PointF2D): GraphicalLabel {
|
|
let initialSearchAreaX: number = 4;
|
|
let initialSearchAreaX: number = 4;
|
|
let initialSearchAreaY: number = 4;
|
|
let initialSearchAreaY: number = 4;
|
|
|
|
+ // Prepare search area
|
|
let region: BoundingBox = new BoundingBox();
|
|
let region: BoundingBox = new BoundingBox();
|
|
region.BorderLeft = clickPosition.x - initialSearchAreaX;
|
|
region.BorderLeft = clickPosition.x - initialSearchAreaX;
|
|
region.BorderTop = clickPosition.y - initialSearchAreaY;
|
|
region.BorderTop = clickPosition.y - initialSearchAreaY;
|
|
@@ -491,12 +559,14 @@ export class GraphicalMusicSheet {
|
|
public GetNearestStaffEntry(clickPosition: PointF2D): GraphicalStaffEntry {
|
|
public GetNearestStaffEntry(clickPosition: PointF2D): GraphicalStaffEntry {
|
|
let initialSearchArea: number = 10;
|
|
let initialSearchArea: number = 10;
|
|
let foundEntries: GraphicalStaffEntry[] = [];
|
|
let foundEntries: GraphicalStaffEntry[] = [];
|
|
|
|
+ // Prepare search area
|
|
let region: BoundingBox = new BoundingBox(undefined);
|
|
let region: BoundingBox = new BoundingBox(undefined);
|
|
region.BorderLeft = clickPosition.x - initialSearchArea;
|
|
region.BorderLeft = clickPosition.x - initialSearchArea;
|
|
region.BorderTop = clickPosition.y - initialSearchArea;
|
|
region.BorderTop = clickPosition.y - initialSearchArea;
|
|
region.BorderRight = clickPosition.x + initialSearchArea;
|
|
region.BorderRight = clickPosition.x + initialSearchArea;
|
|
region.BorderBottom = clickPosition.y + initialSearchArea;
|
|
region.BorderBottom = clickPosition.y + initialSearchArea;
|
|
region.AbsolutePosition = new PointF2D(0, 0);
|
|
region.AbsolutePosition = new PointF2D(0, 0);
|
|
|
|
+ // Search for StaffEntries in region
|
|
for (let idx: number = 0, len: number = this.MusicPages.length; idx < len; ++idx) {
|
|
for (let idx: number = 0, len: number = this.MusicPages.length; idx < len; ++idx) {
|
|
let graphicalMusicPage: GraphicalMusicPage = this.MusicPages[idx];
|
|
let graphicalMusicPage: GraphicalMusicPage = this.MusicPages[idx];
|
|
let entries: GraphicalStaffEntry[] = graphicalMusicPage.PositionAndShape.getObjectsInRegion<GraphicalStaffEntry>(region, false);
|
|
let entries: GraphicalStaffEntry[] = graphicalMusicPage.PositionAndShape.getObjectsInRegion<GraphicalStaffEntry>(region, false);
|
|
@@ -509,6 +579,7 @@ export class GraphicalMusicSheet {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
+ // Get closest entry
|
|
let closest: GraphicalStaffEntry = undefined;
|
|
let closest: GraphicalStaffEntry = undefined;
|
|
for (let idx: number = 0, len: number = foundEntries.length; idx < len; ++idx) {
|
|
for (let idx: number = 0, len: number = foundEntries.length; idx < len; ++idx) {
|
|
let gse: GraphicalStaffEntry = foundEntries[idx];
|
|
let gse: GraphicalStaffEntry = foundEntries[idx];
|
|
@@ -528,6 +599,8 @@ export class GraphicalMusicSheet {
|
|
if (closest !== undefined) {
|
|
if (closest !== undefined) {
|
|
return closest;
|
|
return closest;
|
|
}
|
|
}
|
|
|
|
+ // TODO No staff entry was found. Feedback?
|
|
|
|
+ // throw new ArgumentException("No staff entry found");
|
|
return undefined;
|
|
return undefined;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -585,6 +658,11 @@ export class GraphicalMusicSheet {
|
|
return undefined;
|
|
return undefined;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
+ * Get visible staffentry for the container given by the index.
|
|
|
|
+ * @param index
|
|
|
|
+ * @returns {GraphicalStaffEntry}
|
|
|
|
+ */
|
|
public getStaffEntry(index: number): GraphicalStaffEntry {
|
|
public getStaffEntry(index: number): GraphicalStaffEntry {
|
|
let container: VerticalGraphicalStaffEntryContainer = this.VerticalGraphicalStaffEntryContainers[index];
|
|
let container: VerticalGraphicalStaffEntryContainer = this.VerticalGraphicalStaffEntryContainers[index];
|
|
let staffEntry: GraphicalStaffEntry = undefined;
|
|
let staffEntry: GraphicalStaffEntry = undefined;
|
|
@@ -609,6 +687,12 @@ export class GraphicalMusicSheet {
|
|
return staffEntry;
|
|
return staffEntry;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
+ * Returns the index of the closest previous (earlier) vertical container which has at least some visible staff entry, with respect to the given index.
|
|
|
|
+ * @param index
|
|
|
|
+ * @returns {number}
|
|
|
|
+ * @constructor
|
|
|
|
+ */
|
|
public GetPreviousVisibleContainerIndex(index: number): number {
|
|
public GetPreviousVisibleContainerIndex(index: number): number {
|
|
for (let i: number = index - 1; i >= 0; i--) {
|
|
for (let i: number = index - 1; i >= 0; i--) {
|
|
let entries: GraphicalStaffEntry[] = this.verticalGraphicalStaffEntryContainers[i].StaffEntries;
|
|
let entries: GraphicalStaffEntry[] = this.verticalGraphicalStaffEntryContainers[i].StaffEntries;
|
|
@@ -622,6 +706,12 @@ export class GraphicalMusicSheet {
|
|
return -1;
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
+ * Returns the index of the closest next (later) vertical container which has at least some visible staff entry, with respect to the given index.
|
|
|
|
+ * @param index
|
|
|
|
+ * @returns {number}
|
|
|
|
+ * @constructor
|
|
|
|
+ */
|
|
public GetNextVisibleContainerIndex(index: number): number {
|
|
public GetNextVisibleContainerIndex(index: number): number {
|
|
for (let i: number = index + 1; i < this.verticalGraphicalStaffEntryContainers.length; ++i) {
|
|
for (let i: number = index + 1; i < this.verticalGraphicalStaffEntryContainers.length; ++i) {
|
|
let entries: GraphicalStaffEntry[] = this.verticalGraphicalStaffEntryContainers[i].StaffEntries;
|
|
let entries: GraphicalStaffEntry[] = this.verticalGraphicalStaffEntryContainers[i].StaffEntries;
|
|
@@ -808,6 +898,11 @@ export class GraphicalMusicSheet {
|
|
return (deltaX * deltaX) + (deltaY * deltaY);
|
|
return (deltaX * deltaX) + (deltaY * deltaY);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
+ * Return the longest StaffEntry duration from a GraphicalVerticalContainer.
|
|
|
|
+ * @param index
|
|
|
|
+ * @returns {Fraction}
|
|
|
|
+ */
|
|
private getLongestStaffEntryDuration(index: number): Fraction {
|
|
private getLongestStaffEntryDuration(index: number): Fraction {
|
|
let maxLength: Fraction = new Fraction(0, 1);
|
|
let maxLength: Fraction = new Fraction(0, 1);
|
|
for (let idx: number = 0, len: number = this.verticalGraphicalStaffEntryContainers[index].StaffEntries.length; idx < len; ++idx) {
|
|
for (let idx: number = 0, len: number = this.verticalGraphicalStaffEntryContainers[index].StaffEntries.length; idx < len; ++idx) {
|