Skip to content

Commit fe385af

Browse files
committed
show remaining edges (ties) in score
1 parent afe1018 commit fe385af

File tree

5 files changed

+115
-44
lines changed

5 files changed

+115
-44
lines changed

annotation-tool/src/App/Main.purs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import Data.Either (Either(..))
1111
import Data.Foldable (for_)
1212
import Data.Int (toNumber)
1313
import Data.List as L
14+
import Data.Map as M
1415
import Data.Maybe (Maybe(..), fromMaybe, maybe)
1516
import Effect (Effect)
1617
import Effect.Aff.Class (class MonadAff)
@@ -115,9 +116,13 @@ redrawScore = do
115116
slices = case st.selected of
116117
SelNote { note, parents } -> A.filter (\s -> s.slice.id `A.elem` getParents parents || note `A.elem` (_.note <$> getInnerNotes s.slice)) $ A.fromFoldable graph.slices
117118
_ -> A.filter (\s -> s.depth == 0.0) $ A.fromFoldable graph.slices
119+
transitions = A.filter (\t -> t.left `A.elem` sliceIds && t.right `A.elem` sliceIds)
120+
$ A.fromFoldable (M.values graph.transitions)
121+
where
122+
sliceIds = _.slice.id <$> slices
118123

119124
totalWidth = scalex st.settings (toNumber $ A.length model.piece) + sliceDistance / 2.0
120-
pure $ liftEffect $ insertScore scoreElt $ renderScore (_.slice <$> slices) toX model.styles.staff totalWidth scoreScale
125+
pure $ liftEffect $ insertScore scoreElt $ renderScore (_.slice <$> slices) transitions toX model.styles.staff totalWidth scoreScale
121126
fromMaybe (pure unit) update
122127

123128
autoSaveModel :: forall o m. (MonadEffect m) => H.HalogenM AppState GraphAction AppSlots o m Unit
@@ -171,11 +176,11 @@ handleAction act = do
171176
model = loadPiece piece
172177
in
173178
H.modify_ \st -> st
174-
{ loaded = Just { model, surface: findSurface model.reduction }
179+
{ loaded = Just { model, surface: findSurface false model.reduction }
175180
, name = name
176181
}
177182
ImportModel model -> H.modify_ \st -> st
178-
{ loaded = Just { model, surface: findSurface model.reduction }
183+
{ loaded = Just { model, surface: findSurface false model.reduction }
179184
, name = name
180185
}
181186
-- ImportCurrentSurface ->

model/src/ProtoVoices/Folding.purs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -537,14 +537,16 @@ leftmostToReduction topSegments deriv = do
537537
-- finding the surface of a reduction
538538
-- ==================================
539539

540-
findSurface :: Reduction -> BottomSurface
541-
findSurface red = flip ST.execState { slices: [], transs: [] } $ walkGraph surfaceAlg red.start agenda
540+
findSurface :: Boolean -> Reduction -> BottomSurface
541+
findSurface showAllEdges red = flip ST.execState { slices: [], transs: [] } $ walkGraph surfaceAlg red.start agenda
542542
where
543543
agenda = nothingMore <$> red.segments
544544

545-
split ag { childl, childr } = pure $ map nothingMore $ Cons (addUnusedEdgesLeft childl) $ Cons (addUnusedEdgesRight childl.rslice childr') Nil
545+
split ag { childl, childr } = pure $ map nothingMore $ segLeft : segRight : Nil
546546
where
547547
childr' = attachSegment childr ag.seg.rslice
548+
segLeft = if showAllEdges then addUnusedEdgesLeft childl else childl
549+
segRight = if showAllEdges then addUnusedEdgesRight childl.rslice childr' else childr'
548550

549551
hori _ ag1 ag2 { childl, childm, childr } = pure $ map nothingMore $ Cons childl' $ Cons childm $ Cons childr' Nil
550552
where

model/src/ProtoVoices/RenderSVG.js

Lines changed: 70 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ const VF = Vex.Flow;
66
// Drawing basic score elements
77
// ============================
88

9-
function drawSlice(slice, staffType, scale, useIDs, styles) {
9+
function drawSlice(slice, staffType, scale, id_pfx, styles) {
1010
let div = createSvgElt("g");
1111
let renderer = new VF.Renderer(div, VF.Renderer.Backends.SVG);
1212
//renderer.resize(500, 500);
@@ -27,12 +27,11 @@ function drawSlice(slice, staffType, scale, useIDs, styles) {
2727
});
2828

2929
// add IDs
30-
if (useIDs) {
31-
for (let i = 0; i < notes.length; i++) {
32-
chord._noteHeads[i].attrs.id = notes[i].id;
33-
}
34-
chord.attrs.id = `slice${slice.id}-${clef}`;
30+
for (let i = 0; i < notes.length; i++) {
31+
chord._noteHeads[i].attrs.id = notes[i].id;
3532
}
33+
chord.attrs.id = `${id_pfx}slice${slice.id}-${clef}`;
34+
3635

3736
// add style attributes
3837
if (styles) {
@@ -107,7 +106,7 @@ function drawStaff(width, staffType) {
107106
return elt;
108107
}
109108

110-
function drawSystem(slices, totalWidth, scale, staffType, useIDs, styles = null) {
109+
function drawSystem(slices, totalWidth, scale, staffType, id_pfx, styles = null) {
111110
let container = createSvgElt("g");
112111

113112
// draw staff
@@ -127,7 +126,7 @@ function drawSystem(slices, totalWidth, scale, staffType, useIDs, styles = null)
127126
"translate(" + slice.x + " 0) scale(" + scale + " " + scale + ")",
128127
);
129128
sliceG.setAttribute("id", "slice-" + slice.id);
130-
sliceG.appendChild(drawSlice(slice, staffType, scale, useIDs, styles));
129+
sliceG.appendChild(drawSlice(slice, staffType, scale, id_pfx, styles));
131130

132131
// apply slice styles
133132
if (styles !== null) {
@@ -157,12 +156,71 @@ function drawSystem(slices, totalWidth, scale, staffType, useIDs, styles = null)
157156
// Drawing a score
158157
// ===============
159158

159+
function drawScoreEdge(container, edge, passing) {
160+
// compute coordinates
161+
const bbleft = getNoteBBox(edge.left.id, container);
162+
const bbright = getNoteBBox(edge.right.id, container);
163+
let x1 = bbleft.x + bbleft.width + markerWidth + 2;
164+
let y1 = bbleft.y + bbleft.height / 2;
165+
let x2 = bbright.x - markerWidth - 2;
166+
let y2 = bbright.y + bbright.height / 2;
167+
168+
// compute
169+
let line = createSvgElt("line");
170+
line.setAttribute("x1", x1);
171+
line.setAttribute("y1", y1);
172+
line.setAttribute("x2", x2);
173+
line.setAttribute("y2", y2);
174+
175+
let classes = "pv-score-edge";
176+
if (passing) {
177+
line.setAttribute("stroke-dasharray", "6,3");
178+
classes += " pv-passing";
179+
} else {
180+
classes += " pv-regular";
181+
}
182+
183+
line.setAttribute("class", classes);
184+
185+
return line;
186+
};
187+
160188
export const drawScore =
161-
(slices) => (staffType) => (totalWidth) => (scale) => {
162-
let system = drawSystem(slices, totalWidth, scale, staffType, false);
189+
(slices) => (transitions) => (staffType) => (totalWidth) => (scale) => {
190+
// draw system and notes
191+
let system = drawSystem(slices, totalWidth, scale, staffType, "score-");
163192
let container = createSvgElt("g");
164193
container.appendChild(system.staff);
165194
container.appendChild(system.notes);
195+
196+
// make sure that the container is attached to the DOM (required for computing bboxes)
197+
let fakesvg = createSvgElt("svg");
198+
fakesvg.appendChild(container);
199+
document.body.appendChild(fakesvg);
200+
201+
// draw edges
202+
transitions.forEach(transition => {
203+
let transElt = createSvgElt("g");
204+
transElt.setAttribute("id", `score-transition-${transition.id}`);
205+
transElt.setAttribute("class", "pv-score-transition");
206+
207+
transition.regular.forEach((edge) => {
208+
transElt.appendChild(
209+
drawScoreEdge(container, edge, false),
210+
);
211+
});
212+
transition.passing.forEach((edge) => {
213+
transElt.appendChild(
214+
drawScoreEdge(container, edge, true),
215+
);
216+
});
217+
container.appendChild(transElt);
218+
});
219+
220+
// remove container from DOM
221+
fakesvg.remove();
222+
container.remove();
223+
166224
return container;
167225
};
168226

@@ -371,7 +429,7 @@ export const drawGraph = (graph) => (totalWidth) => (scale) => {
371429
let levelOffset = graph.styles.staffType == "grand" ? 150 : 80;
372430
for (let level = minLevel; level <= graph.maxd; level++) {
373431
let levelSlices = graph.slices.filter((s) => s.depth == level);
374-
let levelG = drawSystem(levelSlices, totalWidth, scale, graph.styles.staffType, true, graph.styles);
432+
let levelG = drawSystem(levelSlices, totalWidth, scale, graph.styles.staffType, "", graph.styles);
375433
let transform = `translate(0 ${(level - minLevel) * levelOffset})`;
376434
levelG.notes.setAttribute("transform", transform);
377435
levelG.staff.setAttribute(
@@ -417,7 +475,7 @@ export const drawGraph = (graph) => (totalWidth) => (scale) => {
417475
});
418476

419477
// draw score
420-
let score = drawScore(graph.surfaceSlices)(graph.styles.staffType)(totalWidth)(scale);
478+
let score = drawScore(graph.surfaceSlices)(graph.surfaceTransitions)(graph.styles.staffType)(totalWidth)(scale);
421479
score.setAttribute(
422480
"transform",
423481
`translate(0 ${(graph.maxd - minLevel + 1) * levelOffset})`,

model/src/ProtoVoices/RenderSVG.purs

Lines changed: 30 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@ import Data.Pitches (alteration, letter, octaves)
1313
import Data.Ratio ((%))
1414
import Effect (Effect)
1515
import ProtoVoices.Common (MBS(..))
16-
import ProtoVoices.Folding (Graph)
16+
import ProtoVoices.Folding (Graph, GraphTransition)
1717
import ProtoVoices.JSONTransport (StylesJSON, stylesToJSON)
18-
import ProtoVoices.Model (BottomSurface, Edges, Note, NoteExplanation(..), Piece, Slice, SliceId, Staff, StartStop(..), Styles, TransId, explParents, getInnerNotes, staffType2JS)
18+
import ProtoVoices.Model (Edges, Note, NoteExplanation(..), Piece, Slice, SliceId, Staff, StartStop(..), Styles, TransId, BottomSurface, explParents, getInnerNotes, staffType2JS)
1919
import Web.DOM.Element (Element)
2020

2121
foreign import data DOMScore :: Type
@@ -38,30 +38,35 @@ type RenderSlice =
3838
}
3939
)
4040

41-
foreign import drawScore :: Array (Record RenderSlice) -> String -> Number -> Number -> DOMScore
41+
type RenderGraphSlice = { depth :: Number | RenderSlice }
42+
43+
type InnerEdge = { left :: Note, right :: Note }
44+
45+
type RenderGraphTransition = { id :: TransId, regular :: Array InnerEdge, passing :: Array InnerEdge }
46+
47+
foreign import drawScore :: Array (Record RenderSlice) -> Array RenderGraphTransition -> String -> Number -> Number -> DOMScore
4248

4349
foreign import insertScore :: Element -> DOMScore -> Effect Unit
4450

4551
renderScore
4652
:: Array Slice -- { x :: Number, id :: SliceId, notes :: Array { note :: Note, expl :: NoteExplanation } }
53+
-> Array GraphTransition
4754
-> (Number -> Number)
4855
-> Staff
4956
-> Number
5057
-> Number
5158
-> DOMScore
52-
renderScore slices toX staffType = drawScore (mkRenderSlice toX <$> slices) (staffType2JS staffType)
59+
renderScore slices transitions toX staffType =
60+
drawScore
61+
(mkRenderSlice toX <$> slices)
62+
(mkRenderTrans <$> transitions)
63+
(staffType2JS staffType)
5364

5465
-- where
5566
-- mkSlice s = s { notes = mkRenderSlice s.notes }
5667

5768
-- Rendering full graph
5869

59-
type RenderGraphSlice = { depth :: Number | RenderSlice }
60-
61-
type InnerEdge = { left :: Note, right :: Note }
62-
63-
type RenderGraphTransition = { id :: TransId, regular :: Array InnerEdge, passing :: Array InnerEdge }
64-
6570
foreign import drawGraph
6671
:: { slices :: Array RenderGraphSlice
6772
, surfaceSlices :: Array (Record RenderSlice)
@@ -92,8 +97,8 @@ renderGraph
9297
renderGraph graph piece surface styles selection selectCallback toX = drawGraph
9398
{ slices: A.fromFoldable $ mkGraphSlice <$> M.values graph.slices
9499
, surfaceSlices: mkRenderSlice toX <$> surface.slices
95-
, transitions: A.fromFoldable $ mkTrans <$> M.values graph.transitions
96-
, surfaceTransitions: mkTrans <$> surface.transs
100+
, transitions: A.fromFoldable $ mkRenderTrans <$> M.values graph.transitions
101+
, surfaceTransitions: mkRenderTrans <$> surface.transs
97102
, horis: A.fromFoldable graph.horis
98103
, times: A.mapWithIndex mkTime $ _.time <$> piece
99104
, maxd: graph.maxd
@@ -114,24 +119,12 @@ renderGraph graph piece surface styles selection selectCallback toX = drawGraph
114119
where
115120
rs = mkRenderSlice toX s.slice
116121

117-
mkTrans :: forall r. { edges :: Edges, id :: TransId | r } -> RenderGraphTransition
118-
mkTrans t =
119-
{ regular: innerEdges $ A.fromFoldable t.edges.regular
120-
, passing: innerEdges $ t.edges.passing
121-
, id: t.id
122-
}
123122
mkTime i time = { x: toX $ toNumber (i + 1), label }
124123
where
125124
label = case time of
126125
Right (MBS { m, b, s }) -> if s == 0 % 1 then show m <> "." <> show b else ""
127126
Left str -> str
128127

129-
innerEdges edges = A.catMaybes $
130-
( \edge -> case edge of
131-
{ left: Inner l, right: Inner r } -> Just { left: l, right: r }
132-
_ -> Nothing
133-
) <$> edges
134-
135128
mkRenderSlice :: (Number -> Number) -> Slice -> Record RenderSlice
136129
mkRenderSlice toX slice =
137130
{ x: toX slice.x
@@ -148,6 +141,19 @@ mkRenderSlice toX slice =
148141
, expl: encodeExplanation n.expl
149142
}
150143

144+
mkRenderTrans :: forall r. { edges :: Edges, id :: TransId | r } -> RenderGraphTransition
145+
mkRenderTrans t =
146+
{ regular: innerEdges $ A.fromFoldable t.edges.regular
147+
, passing: innerEdges $ t.edges.passing
148+
, id: t.id
149+
}
150+
where
151+
innerEdges edges = A.catMaybes $
152+
( \edge -> case edge of
153+
{ left: Inner l, right: Inner r } -> Just { left: l, right: r }
154+
_ -> Nothing
155+
) <$> edges
156+
151157
encodeExplanation :: NoteExplanation -> { typ :: String, parent :: Nullable String }
152158
encodeExplanation expl = case expl of
153159
NoExpl -> { typ: "None", parent: N.null }

viewer/src/Common.purs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ fillCache model step cache =
123123
flip ST.evalState Nothing do
124124
pruned' <- insertItem identity cache.modelPruned
125125
graph' <- insertItem (evalGraph true true <<< _.reduction) cache.graph
126-
surface' <- insertItem (findSurface <<< _.reduction) cache.surface
126+
surface' <- insertItem (findSurface false <<< _.reduction) cache.surface
127127
pure { modelPruned: pruned', graph: graph', surface: surface' }
128128
where
129129
insertItem :: forall a. (Model -> a) -> M.Map Int a -> ST.State (Maybe (Either String Model)) (M.Map Int a)
@@ -156,4 +156,4 @@ cacheGetGraph mpruned step cache = case M.lookup step cache.graph of
156156
cacheGetSurface :: Model -> Int -> ViewerCache -> BottomSurface
157157
cacheGetSurface mpruned step cache = case M.lookup step cache.surface of
158158
Just surfs -> surfs
159-
Nothing -> findSurface mpruned.reduction
159+
Nothing -> findSurface false mpruned.reduction

0 commit comments

Comments
 (0)