Skip to content
This repository has been archived by the owner on May 14, 2020. It is now read-only.

nx3 • 2b. D* tree calculation overview

Jonas Nyström edited this page Jan 13, 2014 · 5 revisions

In music notation, the notation objects affect each other regarding formatting and layout in ways that don't follow hierarchial orders. Things depend on other things in a rather complex relations. For example, the up/down direction of the note stave basically depends on the head(s) placement in the current note, but this direction is might be overriden if 1) the note belongs to a beam group of eight or sixteenth notes (where all containing notes with their heads are taken into account) or 2) if the voice has an fixed direction that affects all containing notes. Due to the fact that the head placement in a note is affected of the stave direction - and therefore also the resulting graphical rectangular space that the heads will occupy on the page - we must know how the 1) beamingpattern and 2) voice direction properties affect the note direction before we can calculate the rectangle that the heads will occupy!

Below is an attempt to give an overview of the "step-by-step flow" where these calculations are performed in the orderer needed to guarantee that all needed information is present.

Starting point: N*-tree copied into a D*-tree

As a starting point, we assume that we have a N*-tree wich entities are copied into a corresponding D*-tree.

DVoice: Creating beaming groups and calculating DNote stave direction

The beaming pattern to be used can be manually set in the corresponding NVoice entity, but more typically it isn't set. In that normal case, the beaming pattern is adapted to the current bar time signature.

The current beaming pattern is used to generate the DVoice's array of DBeamGroup(s), where each beamgroup references one or many DNotes. If the NVoice has a fixed direction (up or down) this direction is applied to the beam gropus, if not the direction is calculated for each beamgroup depending on the child note(s) and its/their head level(s). The resulting final direction is set for the DNote.direction property. This means that each DNote now actually know it's final up/down direction.

DPart: Assembling DNote(s) into DComplex(es)

The fact that a part might - on the same note value position - have two different voices with two different notes, each containing two different heads with different accidentals, is not reflected in how these notes are treated when it comes to layouting them. In fact, the accidentals for these two notes are assembled into one "group" of accidentals wich is horizontaly formatted as one unit and all placed before the note heads of both voices. This unit, the "join" of two DNote(s) coming from separate DVoice(s) is called a DComplex, and the DPart holds an array of these. In the end, each DPart will have one DComplex for each occupied note value position coming for the one or two voices that are present. Whenever both voices (if two!) have notes on the same note value position, the corresponding DComplex will reference these both notes. If just one voice has a note on the current note value position, the DComplex will reference just that single DNote.

DPart: Calculating virtual rectangle areas for DComplex notes (noteheads, accidentals, dots etc.)

Now, when we have generated the DComplex(es) referencing the DNotes, we have the information we need to calculate the virtual rectangles for the separate notation objects connected to the referenced notes: the accidentals rectangle should be placed to the left of the noteheads rectangle, and the dot rectangle (for dotted note values) should be placed to the right.

DPart - assemble its Dvoice(s)'s DNotes into DComplexes

Dpart - calculate DComplexes min distances

DBar - calculate DColumns min distances (watch out for lyric parts!)

DVoice - Calculate Beaming coordinates

DVoice - Calculate Articulation coordinates

DVoice - Calculate coordinates for BarPart stuff like phrasings, textlines, inter-bar ties

DBar - Apply Allotment rule and calculate min alloted width

LayoutEngine uses AttributeRules, BarspacingRules etc produces DSystems { Check each DBar width depending on AttributeRules, Userset attributes, content width - breaks to new DSystem when overflow Identify inter-system objects and pass them (dangling phrasings, textlines, inter-bar ties etc to) next DSystem }

DSystem - Calculate the stretched width each DBar will get depending on system width overflow

DSystem - draw iterations { draw note lines to full system width draw bar content, using correct attributes and using the calculated stretched width draw DSystem inter-bar content draw inter-system objects }