Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(track,core): support clockwise orientation in circular track #1078

Draft
wants to merge 8 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/compiler/create-higlass-models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,8 @@ export function renderHiGlass(
innerRadius: d.track.innerRadius!,
outerRadius: d.track.outerRadius!,
startAngle: d.track.startAngle!,
endAngle: d.track.endAngle!
endAngle: d.track.endAngle!,
clockwise: d.track.clockwise!
}
};
});
Expand Down
1 change: 1 addition & 0 deletions src/compiler/gosling-to-higlass.ts
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,7 @@ export function goslingToHiGlass(
height: firstResolvedSpec.height,
startAngle: firstResolvedSpec.startAngle,
endAngle: firstResolvedSpec.endAngle,
clockwise: firstResolvedSpec.clockwise,
theme
});
}
Expand Down
7 changes: 5 additions & 2 deletions src/compiler/higlass-model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ export class HiGlassModel {
endAngle?: number;
innerRadius?: number;
outerRadius?: number;
clockwise?: boolean;
}
) {
if (!fromViewUid) return;
Expand All @@ -169,7 +170,8 @@ export class HiGlassModel {
startAngle: style?.startAngle,
endAngle: style?.endAngle,
innerRadius: style?.innerRadius,
outerRadius: style?.outerRadius
outerRadius: style?.outerRadius,
clockwise: style?.clockwise
}
});
return this;
Expand Down Expand Up @@ -313,6 +315,7 @@ export class HiGlassModel {
startAngle?: number;
endAngle?: number;
theme: Required<CompleteThemeDeep>;
clockwise?: boolean;
}
) {
if (!this.hg.views) return this;
Expand Down Expand Up @@ -342,7 +345,7 @@ export class HiGlassModel {
// circular axis: superpose an axis track on top of the `center` track
this.addTrackToCombined({
...axisTrackTemplate,
options: { ...axisTrackTemplate.options, layout: 'circular' }
options: { ...axisTrackTemplate.options, layout: 'circular', clockwise: options.clockwise}
});
} else {
// linear axis: place an axis track on the top, left, bottom, or right
Expand Down
22 changes: 15 additions & 7 deletions src/core/mark/area.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export function drawArea(HGC: import('@higlass/types').HGC, track: any, tile: Ti

/* circular parameters */
const circular = spec.layout === 'circular';
const isClockwise = spec.clockwise ?? false;
const trackInnerRadius = spec.innerRadius ?? 220; // TODO: should default values be filled already
const trackOuterRadius = spec.outerRadius ?? 300; // TODO: should be smaller than Math.min(width, height)
const startAngle = spec.startAngle ?? 0;
Expand Down Expand Up @@ -104,7 +105,8 @@ export function drawArea(HGC: import('@higlass/types').HGC, track: any, tile: Ti
trackCenterX,
trackCenterY,
startAngle,
endAngle
endAngle,
isClockwise
);
areaPointsTop.push([pos.x, pos.y]);
areaPointsBottom.push([pos.x, pos.y]);
Expand All @@ -118,7 +120,8 @@ export function drawArea(HGC: import('@higlass/types').HGC, track: any, tile: Ti
trackCenterX,
trackCenterY,
startAngle,
endAngle
endAngle,
isClockwise
);
areaPointsTop.push([posTop.x, posTop.y]);

Expand All @@ -130,7 +133,8 @@ export function drawArea(HGC: import('@higlass/types').HGC, track: any, tile: Ti
trackCenterX,
trackCenterY,
startAngle,
endAngle
endAngle,
isClockwise
);
areaPointsBottom.push([posBot.x, posBot.y]);

Expand All @@ -144,7 +148,8 @@ export function drawArea(HGC: import('@higlass/types').HGC, track: any, tile: Ti
trackCenterX,
trackCenterY,
startAngle,
endAngle
endAngle,
isClockwise
);
areaPointsTop.push([pos.x, pos.y]);
areaPointsBottom.push([pos.x, pos.y]);
Expand Down Expand Up @@ -228,7 +233,8 @@ export function drawArea(HGC: import('@higlass/types').HGC, track: any, tile: Ti
trackCenterX,
trackCenterY,
startAngle,
endAngle
endAngle,
isClockwise
);
baselinePoints.push([baselinePos.x, baselinePos.y]);

Expand All @@ -245,7 +251,8 @@ export function drawArea(HGC: import('@higlass/types').HGC, track: any, tile: Ti
trackCenterX,
trackCenterY,
startAngle,
endAngle
endAngle,
isClockwise
);
areaPoints.push(pos.x, pos.y);

Expand All @@ -260,7 +267,8 @@ export function drawArea(HGC: import('@higlass/types').HGC, track: any, tile: Ti
trackCenterX,
trackCenterY,
startAngle,
endAngle
endAngle,
isClockwise
);

areaPoints.push(curPos.x, curPos.y);
Expand Down
21 changes: 11 additions & 10 deletions src/core/mark/bar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export function drawBar(track: any, tile: Tile, model: GoslingTrackModel) {

/* circular parameters */
const circular = spec.layout === 'circular';
const isClockwise = spec.clockwise ?? false;
const trackInnerRadius = spec.innerRadius ?? 220;
const trackOuterRadius = spec.outerRadius ?? 300; // TODO: should be smaller than Math.min(width, height)
const startAngle = spec.startAngle ?? 0;
Expand Down Expand Up @@ -116,14 +117,14 @@ export function drawBar(track: any, tile: Tile, model: GoslingTrackModel) {
const ye = isFlippedY ? barHeight + prevYEnd : rowHeight - y - prevYEnd;
const nearR = trackOuterRadius - (ye / trackHeight) * trackRingSize;

const sPos = cartesianToPolar(xs, trackWidth, nearR, cx, cy, startAngle, endAngle);
const startRad = valueToRadian(xs, trackWidth, startAngle, endAngle);
const endRad = valueToRadian(xs + barWidth, trackWidth, startAngle, endAngle);
const sPos = cartesianToPolar(xs, trackWidth, nearR, cx, cy, startAngle, endAngle, isClockwise);
const startRad = valueToRadian(xs, trackWidth, startAngle, endAngle, isClockwise);
const endRad = valueToRadian(xs + barWidth, trackWidth, startAngle, endAngle, isClockwise);

g.beginFill(colorToHex(color), color === 'none' ? 0 : actualOpacity);
g.moveTo(sPos.x, sPos.y);
g.arc(cx, cy, nearR, startRad, endRad, true);
g.arc(cx, cy, farR, endRad, startRad, false);
g.arc(cx, cy, nearR, startRad, endRad, !isClockwise);
g.arc(cx, cy, farR, endRad, startRad, isClockwise);
polygonForMouseEvents = Array.from(g.currentPath.points);
g.closePath();
} else {
Expand Down Expand Up @@ -207,14 +208,14 @@ export function drawBar(track: any, tile: Tile, model: GoslingTrackModel) {
const farR = trackOuterRadius - (ys / trackHeight) * trackRingSize;
const nearR = trackOuterRadius - (ye / trackHeight) * trackRingSize;

const sPos = cartesianToPolar(xs, trackWidth, nearR, cx, cy, startAngle, endAngle);
const startRad = valueToRadian(xs, trackWidth, startAngle, endAngle);
const endRad = valueToRadian(xs + barWidth, trackWidth, startAngle, endAngle);
const sPos = cartesianToPolar(xs, trackWidth, nearR, cx, cy, startAngle, endAngle, isClockwise);
const startRad = valueToRadian(xs, trackWidth, startAngle, endAngle, isClockwise);
const endRad = valueToRadian(xs + barWidth, trackWidth, startAngle, endAngle, isClockwise);

g.beginFill(colorToHex(color), color === 'none' ? 0 : actualOpacity);
g.moveTo(sPos.x, sPos.y);
g.arc(cx, cy, nearR, startRad, endRad, true);
g.arc(cx, cy, farR, endRad, startRad, false);
g.arc(cx, cy, nearR, startRad, endRad, !isClockwise);
g.arc(cx, cy, farR, endRad, startRad, isClockwise);
polygonForMouseEvents = Array.from(g.currentPath.points);
g.closePath();
} else {
Expand Down
9 changes: 5 additions & 4 deletions src/core/mark/betweenLink.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export function drawBetweenLink(g: PIXI.Graphics, trackInfo: any, model: Gosling

/* circular parameters */
const circular = spec.layout === 'circular';
const isClockwise = spec.clockwise ?? false;
const trackInnerRadius = spec.innerRadius ?? 220;
const trackOuterRadius = spec.outerRadius ?? 300;
const startAngle = spec.startAngle ?? 0;
Expand Down Expand Up @@ -118,10 +119,10 @@ export function drawBetweenLink(g: PIXI.Graphics, trackInfo: any, model: Gosling

// https://pixijs.download/dev/docs/PIXI.Graphics.html#bezierCurveTo
const r = trackOuterRadius - (rowPosition / trackHeight) * trackRingSize;
const posX = cartesianToPolar(_x1, trackWidth, r, tcx, tcy, startAngle, endAngle);
const posXE = cartesianToPolar(_x2, trackWidth, r, tcx, tcy, startAngle, endAngle);
const posX1 = cartesianToPolar(_x3, trackWidth, r, tcx, tcy, startAngle, endAngle);
const posX1E = cartesianToPolar(_x4, trackWidth, r, tcx, tcy, startAngle, endAngle);
const posX = cartesianToPolar(_x1, trackWidth, r, tcx, tcy, startAngle, endAngle, isClockwise);
const posXE = cartesianToPolar(_x2, trackWidth, r, tcx, tcy, startAngle, endAngle, isClockwise);
const posX1 = cartesianToPolar(_x3, trackWidth, r, tcx, tcy, startAngle, endAngle, isClockwise);
const posX1E = cartesianToPolar(_x4, trackWidth, r, tcx, tcy, startAngle, endAngle, isClockwise);

g.moveTo(posX.x, posX.y);

Expand Down
22 changes: 12 additions & 10 deletions src/core/mark/grid.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export function drawRowGrid(trackInfo: any, tm: GoslingTrackModel, theme: Requir

/* circular parameters */
const circular = tm.spec().layout === 'circular';
const isClockwise = spec.clockwise ?? false;
const trackInnerRadius = spec.innerRadius ?? 220;
const trackOuterRadius = spec.outerRadius ?? 300; // TODO: should be smaller than Math.min(width, height)
const startAngle = spec.startAngle ?? 0;
Expand Down Expand Up @@ -72,9 +73,9 @@ export function drawRowGrid(trackInfo: any, tm: GoslingTrackModel, theme: Requir
const farR = midR + strokeWidth / 2.0;
const nearR = midR - strokeWidth / 2.0;

const sPos = cartesianToPolar(0, trackWidth, nearR, cx, cy, startAngle, endAngle);
const startRad = valueToRadian(0, trackWidth, startAngle, endAngle);
const endRad = valueToRadian(trackWidth, trackWidth, startAngle, endAngle);
const sPos = cartesianToPolar(0, trackWidth, nearR, cx, cy, startAngle, endAngle, isClockwise);
const startRad = valueToRadian(0, trackWidth, startAngle, endAngle, isClockwise);
const endRad = valueToRadian(trackWidth, trackWidth, startAngle, endAngle, isClockwise);

// For circular grid, we draw 'filled' arc w/ zero strokeWidth
graphics.lineStyle(
Expand All @@ -86,8 +87,8 @@ export function drawRowGrid(trackInfo: any, tm: GoslingTrackModel, theme: Requir

graphics.beginFill(colorToHex(theme.axis.gridColor), 1);
graphics.moveTo(trackX + sPos.x, trackY + sPos.y);
graphics.arc(trackX + cx, trackY + cy, nearR, startRad, endRad, true);
graphics.arc(trackX + cx, trackY + cy, farR, endRad, startRad, false);
graphics.arc(trackX + cx, trackY + cy, nearR, startRad, endRad, !isClockwise);
graphics.arc(trackX + cx, trackY + cy, farR, endRad, startRad, isClockwise);
graphics.closePath();
}
});
Expand All @@ -109,6 +110,7 @@ export function drawYGridQuantitative(trackInfo: any, tm: GoslingTrackModel, the

/* circular parameters */
const circular = tm.spec().layout === 'circular';
const isClockwise = spec.clockwise ?? false;
const trackInnerRadius = spec.innerRadius ?? 220;
const trackOuterRadius = spec.outerRadius ?? 300; // TODO: should be smaller than Math.min(width, height)
const startAngle = spec.startAngle ?? 0;
Expand Down Expand Up @@ -185,9 +187,9 @@ export function drawYGridQuantitative(trackInfo: any, tm: GoslingTrackModel, the
const farR = midR + strokeWidth / 2.0;
const nearR = midR - strokeWidth / 2.0;

const sPos = cartesianToPolar(0, trackWidth, nearR, cx, cy, startAngle, endAngle);
const startRad = valueToRadian(0, trackWidth, startAngle, endAngle);
const endRad = valueToRadian(trackWidth, trackWidth, startAngle, endAngle);
const sPos = cartesianToPolar(0, trackWidth, nearR, cx, cy, startAngle, endAngle, isClockwise);
const startRad = valueToRadian(0, trackWidth, startAngle, endAngle, isClockwise);
const endRad = valueToRadian(trackWidth, trackWidth, startAngle, endAngle, isClockwise);

// For circular grid, we draw 'filled' arc w/ zero strokeWidth
graphics.lineStyle(
Expand All @@ -199,8 +201,8 @@ export function drawYGridQuantitative(trackInfo: any, tm: GoslingTrackModel, the

graphics.beginFill(colorToHex(theme.axis.gridColor), 1);
graphics.moveTo(trackX + sPos.x, trackY + sPos.y);
graphics.arc(trackX + cx, trackY + cy, nearR, startRad, endRad, true);
graphics.arc(trackX + cx, trackY + cy, farR, endRad, startRad, false);
graphics.arc(trackX + cx, trackY + cy, nearR, startRad, endRad, !isClockwise);
graphics.arc(trackX + cx, trackY + cy, farR, endRad, startRad, isClockwise);
graphics.closePath();
});
}
Expand Down
4 changes: 3 additions & 1 deletion src/core/mark/line.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export function drawLine(g: PIXI.Graphics, model: GoslingTrackModel, trackWidth:

/* circular parameters */
const circular = spec.layout === 'circular';
const isClockwise = spec.clockwise ?? false;
const trackInnerRadius = spec.innerRadius ?? 220; // TODO: should default values be filled already
const trackOuterRadius = spec.outerRadius ?? 300; // TODO: should be smaller than Math.min(width, height)
const startAngle = spec.startAngle ?? 0;
Expand Down Expand Up @@ -76,7 +77,8 @@ export function drawLine(g: PIXI.Graphics, model: GoslingTrackModel, trackWidth:
trackCenterX,
trackCenterY,
startAngle,
endAngle
endAngle,
isClockwise
);

if (i === 0) {
Expand Down
3 changes: 2 additions & 1 deletion src/core/mark/point.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export function drawPoint(track: any, g: PIXI.Graphics, model: GoslingTrackModel

/* circular parameters */
const circular = spec.layout === 'circular';
const isClockwise = spec.clockwise ?? false;
const trackInnerRadius = spec.innerRadius ?? 220;
const trackOuterRadius = spec.outerRadius ?? 300;
const startAngle = spec.startAngle ?? 0;
Expand Down Expand Up @@ -72,7 +73,7 @@ export function drawPoint(track: any, g: PIXI.Graphics, model: GoslingTrackModel

if (circular) {
const r = trackOuterRadius - ((rowPosition + rowHeight - cy) / trackHeight) * trackRingSize;
const pos = cartesianToPolar(cx, trackWidth, r, tcx, tcy, startAngle, endAngle);
const pos = cartesianToPolar(cx, trackWidth, r, tcx, tcy, startAngle, endAngle, isClockwise);
g.beginFill(colorToHex(color), actualOpacity);
g.drawCircle(pos.x, pos.y, radius);

Expand Down
11 changes: 6 additions & 5 deletions src/core/mark/rect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export function drawRect(HGC: import('@higlass/types').HGC, track: any, tile: Ti

/* circular parameters */
const circular = spec.layout === 'circular';
const isClockwise = spec.clockwise ?? false;
const trackInnerRadius = spec.innerRadius ?? 220;
const trackOuterRadius = spec.outerRadius ?? 300; // TODO: should be smaller than Math.min(width, height)
const startAngle = spec.startAngle ?? 0;
Expand Down Expand Up @@ -106,14 +107,14 @@ export function drawRect(HGC: import('@higlass/types').HGC, track: any, tile: Ti
nearR = midR + absoluteHeight / 2.0;
}

const sPos = cartesianToPolar(xs, trackWidth, nearR, cx, cy, startAngle, endAngle);
const startRad = valueToRadian(xs, trackWidth, startAngle, endAngle);
const endRad = valueToRadian(xe, trackWidth, startAngle, endAngle);
const sPos = cartesianToPolar(xs, trackWidth, nearR, cx, cy, startAngle, endAngle, isClockwise);
const startRad = valueToRadian(xs, trackWidth, startAngle, endAngle, isClockwise);
const endRad = valueToRadian(xe, trackWidth, startAngle, endAngle, isClockwise);

g.beginFill(colorToHex(color === 'none' ? 'white' : color), color === 'none' ? 0 : actualOpacity);
g.moveTo(sPos.x, sPos.y);
g.arc(cx, cy, nearR, startRad, endRad, true);
g.arc(cx, cy, farR, endRad, startRad, false);
g.arc(cx, cy, nearR, startRad, endRad, !isClockwise);
g.arc(cx, cy, farR, endRad, startRad, isClockwise);
polygonForMouseEvent = Array.from(g.currentPath.points);
g.closePath();
} else {
Expand Down
Loading
Loading