# Oblique view of an {x,y} and {x,z} plot : is ListPointPlot3D the right strategy?

Seeking advice for how to construct an oblique chart plot of {x,y} and {x,z} value lists in a 3D View where the viewer can trace a line from {x,y,0} to {x,0,0}, and then jump to the associated {x,0,z} value.

Idea here is to present two related variables sharing a common x-value on one graphic.

In the following sample code of 10 points (although I typically have to present hundreds of points), I have two (possibly 3) issues in my code:

1. {x,0,z} points are correctly connected via the line to their corresponding {x,0,0} point. How do I specify the same for the {x,y,0} points so that they match up with their corresponding {x,0,0} point?

2. How do I eliminate the bounding 3D Box view?

3. Am I completely headed in the wrong direction (e.g., I should generate 2D ListPointPlots and then "marry" them at the X-Axis by projecting each as the inside face of a 3D cube)?

values[{x, z}] = Table[{i, 0, RandomInteger[{10, 15}]}, {i, 0, 10}];
values[{x, y}] = Table[{i, RandomInteger[{1, 10}], 0}, {i, 0, 10}];
ListPointPlot3D[{values[{x, z}], values[{x, y}]}
, Filling -> Axis
, AxesLabel -> {"X-Axis", "Y-Axis", "Z-Axis"}
, ViewPoint -> {0, 2, 2.75}
, ViewVertical -> {0, 1, 0.04}]


Attached is a reference example for an Oblique data chart of two variables relative to a common X-Value.

For a start:

valxz = Table[{i, 0, RandomInteger[{10, 15}]}, {i, 0, 10}];
valxy = Table[{i, RandomInteger[{1, 10}], 0}, {i, 0, 10}];
Graphics3D[{PointSize[0.03],
Point[valxy], Point[valxz], Thickness[0.01],
Line[{{{1, 0, 0} #, #}}] & /@ valxy,
Line[{{{1, 0, 0} #, #}}] & /@ valxz
}, Axes -> True, Boxed -> False, AxesOrigin -> {0, 0, 0},
AxesLabel -> {"X", "Y", "Z"}]


You may beatify it using e.g. Color, Style e.t.c.

• Oh -- this is GREAT!!! THANK YOU!!!! Oct 11, 2021 at 16:37
• Did you mean beatify or beautify? I suspect the latter, but like the former rather more! Oct 11, 2021 at 17:58
• Well, I suppose it is nor good enough for the former. Oct 11, 2021 at 19:02

An alternative using Tube

Clear["Global*"]

SeedRandom[1234];

values[{x, z}] = Table[{i, 0, RandomInteger[{10, 15}]}, {i, 0, 10}];
values[{x, y}] = Table[{i, RandomInteger[{1, 10}], 0}, {i, 0, 10}];

Graphics3D[{
CapForm["Square"],
Tube[{ReplacePart[#, 3 -> 0], #}, 1/4] & /@ values[{x, z}],
Tube[{ReplacePart[#, 2 -> 0], #}, 1/4] & /@ values[{x, y}]},
Axes -> True,
AxesLabel -> {"X-Axis", "Y-Axis", "Z-Axis"},
ViewPoint -> {1, 1.7, 2.75},
ViewVertical -> {0, 1, 0.04},
Boxed -> False,
AxesEdge -> {Automatic, {1, -1}, {1, -1}}]


• Bob -- THANK YOU -- that is fantastic as well! Oct 12, 2021 at 1:39
SeedRandom[1];
systolic = ReverseSort /@ RandomInteger[{70, 180}, {24, 2}];
diastolic = ReverseSort /@ RandomInteger[{40, 120}, {24, 2}];


We can use PairedBarChart and post-process the output to get a 3D look as in the example in OP:

barspacing = {0, 2, 0};

pbc = PairedBarChart[systolic, diastolic,
BarOrigin -> "XAxis",
BarSpacing -> barspacing,
PlotRangePadding -> {{0, 2}, {Automatic, Automatic}},
PerformanceGoal -> "Speed",
ImageSize -> Large,
ChartStyle -> {Directive[EdgeForm[{Opacity[1], Black}], Black, HatchFilling[Pi/4, 1]],
Directive[EdgeForm[{Opacity[1], Black}], GrayLevel[.7]]},
Epilog -> {Text[Style["systolic", 14],
{-2 (3 + barspacing[[2]]), 75}, {Center, Bottom}, {0, 1}],
Text[Style["diastolic", 14],
{-2 (3 + barspacing[[2]]), -75}, {Center, Top}, {0, -1}],
Line[{{0, 70}, {1 + (2 + barspacing[[2]]) Length @ systolic , 70}}],
Text[Style[70, 14], Offset[{5, 0},
{1 + (2 + barspacing[[2]]) Length @ systolic, 70}], {Left, Center}],
Line[{{0, -40}, {1 + (2 + barspacing[[2]]) Length @ systolic, -40}}],
Text[Style[40, 14], Offset[{5, 0},
{1 + (2 + barspacing[[2]]) Length@systolic , -40}], {Left, Center}]}]


Use ShearingTransform to modify the rectangle, line and text primitives in the lower panel:

pbc /. rlt : (_Rectangle | _Line | _Text ) /; Not[FreeQ[rlt, {_, _?Negative}]] :>
GeometricTransformation[rlt, ShearingTransform[3 Degree, {1, 0}, {0, 1}]]


An alternative approach using the option ChartElementFunction:

st = ShearingTransform[5 Degree, {1, 0}, {0, 1}];

bs = 1;
pbc1 = PairedBarChart[systolic -> ChartElementData["Rectangle"],
diastolic -> (GeometricTransformation[ChartElementData["Rectangle"][##], st] &),
Axes -> False,
BarSpacing -> {0, bs, 0},
BarOrigin -> "XAxis",
ImageSize -> 800,
ChartElementFunction -> (#3[[1]][##] &)]


We can construct the axes using AxisObject:

axes = AxisObject[Line[{{0, 0}, #}], {0, #2},
AxisLabel -> Placed[Style[#3, 16], {0.5, {0.5, -1.25}}],
RotateLabel -> #4 Degree ,
TickDirection -> "Outward",
TickLabelPositioning -> "Tip",
AxisStyle -> FontSize -> 16] & @@@
{{st[{0, -Max @ diastolic}], Max@diastolic, "diastolic", 55 },
{{0, Max @ systolic}, Max @ systolic, "systolic", 90 }};


and add axes and other annotations using the option Epilog:

Show[pbc1,
Epilog -> {axes,
Line[{{0, 70}, {(2 + bs) Length @ systolic, 70}}],
Text[Style[70, 16], {1 + (2 + bs) Length @ systolic, 70}, {-1, 0}],
Line[st /@ {{0, -40}, {(2 + bs) Length @ systolic, -40}}],
Text[Style[40, 16], st @ {1 + (2 + bs) Length @ systolic, -40}, {-1, 0}]},
`