Skip to content

Commit

Permalink
feat: support more 2d shape on point mark (#11)
Browse files Browse the repository at this point in the history
* fix: add visibility prop

* chore: remove ndarray-fill dep

* feat: add more 2d point shape

* chore: umd
  • Loading branch information
xiaoiver authored Nov 16, 2023
1 parent 35afc15 commit eaf7b8c
Show file tree
Hide file tree
Showing 34 changed files with 856 additions and 77 deletions.
2 changes: 2 additions & 0 deletions 3d/__tests__/plots/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
export { Scatter } from "./scatter";
export { ScatterPerspective } from "./scatter-perspective";
export { ScatterLegend } from "./scatter-legend";
export { ScatterPoint } from "./scatter-point";
export { ScatterTriangle } from "./scatter-triangle";
export { Line } from "./line";
export { LinePerspective } from "./line-perspective";
export { Bar } from "./bar";
Expand Down
63 changes: 63 additions & 0 deletions 3d/__tests__/plots/scatter-point.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { CameraType } from "@antv/g";
import { Renderer as WebGLRenderer } from "@antv/g-webgl";
import { Plugin as ThreeDPlugin, DirectionalLight } from "@antv/g-plugin-3d";
import { Plugin as ControlPlugin } from "@antv/g-plugin-control";
import { Runtime, extend, corelib } from "@antv/g2";
import { threedlib } from "../../src";

export function ScatterPoint(context) {
const { container } = context;

// Create a WebGL renderer.
const renderer = new WebGLRenderer();
renderer.registerPlugin(new ThreeDPlugin());
renderer.registerPlugin(new ControlPlugin());

const Chart = extend(Runtime, { ...corelib(), ...threedlib() });
const chart = new Chart({
container,
renderer,
depth: 400,
});

chart
.point3D()
.data({
type: "fetch",
value: "data/cars2.csv",
})
.encode("x", "Horsepower")
.encode("y", "Miles_per_Gallon")
.encode("z", "Weight_in_lbs")
.encode("size", "Origin")
.encode("color", "Cylinders")
.encode("shape", "point")
.coordinate({ type: "cartesian3D" })
.scale("x", { nice: true })
.scale("y", { nice: true })
.scale("z", { nice: true })
.legend(false)
.axis("x", { gridLineWidth: 2 })
.axis("y", { gridLineWidth: 2, titleBillboardRotation: -Math.PI / 2 })
.axis("z", { gridLineWidth: 2 })
.style("fillOpacity", 0.8);

const finished = chart.render().then(() => {
const { canvas } = chart.getContext();
const camera = canvas!.getCamera();
camera.setPerspective(0.1, 5000, 45, 500 / 500);
camera.setType(CameraType.ORBITING);

// Add a directional light into scene.
const light = new DirectionalLight({
style: {
intensity: 3,
fill: "white",
direction: [-1, 0, 1],
},
});
canvas!.appendChild(light);
});

return { finished, destroy: () => chart.destroy() };
}
63 changes: 63 additions & 0 deletions 3d/__tests__/plots/scatter-triangle.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { CameraType } from "@antv/g";
import { Renderer as WebGLRenderer } from "@antv/g-webgl";
import { Plugin as ThreeDPlugin, DirectionalLight } from "@antv/g-plugin-3d";
import { Plugin as ControlPlugin } from "@antv/g-plugin-control";
import { Runtime, extend, corelib } from "@antv/g2";
import { threedlib } from "../../src";

export function ScatterTriangle(context) {
const { container } = context;

// Create a WebGL renderer.
const renderer = new WebGLRenderer();
renderer.registerPlugin(new ThreeDPlugin());
renderer.registerPlugin(new ControlPlugin());

const Chart = extend(Runtime, { ...corelib(), ...threedlib() });
const chart = new Chart({
container,
renderer,
depth: 400,
});

chart
.point3D()
.data({
type: "fetch",
value: "data/cars2.csv",
})
.encode("x", "Horsepower")
.encode("y", "Miles_per_Gallon")
.encode("z", "Weight_in_lbs")
.encode("size", "Origin")
.encode("color", "Cylinders")
.encode("shape", "triangle")
.coordinate({ type: "cartesian3D" })
.scale("x", { nice: true })
.scale("y", { nice: true })
.scale("z", { nice: true })
.legend(false)
.axis("x", { gridLineWidth: 2 })
.axis("y", { gridLineWidth: 2, titleBillboardRotation: -Math.PI / 2 })
.axis("z", { gridLineWidth: 2 })
.style("fillOpacity", 0.8);

const finished = chart.render().then(() => {
const { canvas } = chart.getContext();
const camera = canvas!.getCamera();
camera.setPerspective(0.1, 5000, 45, 500 / 500);
camera.setType(CameraType.ORBITING);

// Add a directional light into scene.
const light = new DirectionalLight({
style: {
intensity: 3,
fill: "white",
direction: [-1, 0, 1],
},
});
canvas!.appendChild(light);
});

return { finished, destroy: () => chart.destroy() };
}
17 changes: 7 additions & 10 deletions 3d/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@antv/g2-extension-3d",
"version": "0.1.2",
"version": "0.1.5",
"main": "lib/index.js",
"module": "esm/index.js",
"unpkg": "dist/index.umd.min.js",
Expand All @@ -27,26 +27,23 @@
},
"dependencies": {
"d3-array": "^3.2.2",
"@antv/g-webgl": "^1.9.8",
"@antv/g-plugin-3d": "^1.9.5",
"@antv/g-plugin-control": "^1.9.5",
"@antv/util": "^3.3.5",
"ndarray": "^1.0.19",
"ndarray-fill": "latest",
"ndarray-ops": "latest",
"ndarray-pack": "latest",
"ndarray-gradient": "latest",
"typedarray-pool": "latest",
"colormap": "latest"
"ndarray-ops": "^1.2.2",
"ndarray-pack": "^1.2.1",
"ndarray-gradient": "^1.0.1",
"colormap": "^2.3.2"
},
"peerDependencies": {
"@antv/g": "^5.18.19",
"@antv/g2": "^5.1.8"
},
"devDependencies": {
"@antv/g-webgl": "^1.9.8",
"@antv/g-plugin-control": "^1.9.5",
"@types/d3-array": "3.0.5",
"@types/ndarray": "^1.0.14",
"@types/typedarray-pool": "^1.1.5",
"@types/ndarray-ops": "^1.2.7",
"@types/colormap": "^2.3.4",
"@antv/g": "^5.18.19",
Expand Down
4 changes: 3 additions & 1 deletion 3d/rollup.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@ import { readFileSync } from "fs";
export default createConfig({
pkg: JSON.parse(readFileSync(new URL("./package.json", import.meta.url), "utf8")),
umdName: "G2.Extension3D",
external: ["@antv/g2"],
external: ["@antv/g", "@antv/g-plugin-3d", "@antv/g2"],
globals: {
"@antv/g": "window.G",
"@antv/g-plugin-3d": "window.G.3D",
"@antv/g2": "window.G2",
},
});
Expand Down
40 changes: 39 additions & 1 deletion 3d/src/mark/point3D.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,27 @@
import { Coordinate3D } from "@antv/coord";
import { PointMark, MarkComponent as MC, Vector3, MaybeZeroX, MaybeZeroY, MaybeZeroZ, MaybeSize } from "@antv/g2";
import { baseGeometryChannels, basePostInference, basePreInference, tooltip3d } from "./utils";
import { Cube } from "../shape/point3D/cube";
import { Sphere } from "../shape/point3D/sphere";
import { baseGeometryChannels, basePostInference, basePreInference, tooltip3d } from "./utils";
import { Point } from "../shape/point3D/point";
import { Cross } from "../shape/point3D/cross";
import { Triangle } from "../shape/point3D/triangle";
import { TriangleDown } from "../shape/point3D/triangleDown";
import { HollowPoint } from "../shape/point3D/hollow";
import { HollowDiamond } from "../shape/point3D/hollowDiamond";
import { HollowHexagon } from "../shape/point3D/hollowHexagon";
import { HollowSquare } from "../shape/point3D/hollowSquare";
import { HollowTriangleDown } from "../shape/point3D/hollowTriangleDown";
import { HollowTriangle } from "../shape/point3D/hollowTriangle";
import { HollowBowtie } from "../shape/point3D/hollowBowtie";
import { Plus } from "../shape/point3D/plus";
import { Diamond } from "../shape/point3D/diamond";
import { Square } from "../shape/point3D/square";
import { Hexagon } from "../shape/point3D/hexagon";
import { Bowtie } from "../shape/point3D/bowtie";
import { Hyphen } from "../shape/point3D/hyphen";
import { Tick } from "../shape/point3D/tick";
import { Line } from "../shape/point3D/line";

export type PointOptions = Omit<PointMark, "type">;

Expand Down Expand Up @@ -52,6 +71,25 @@ export const Point3D: MC<PointOptions> = (options) => {
const shape = {
sphere: Sphere,
cube: Cube,
hollow: HollowPoint,
hollowDiamond: HollowDiamond,
hollowHexagon: HollowHexagon,
hollowSquare: HollowSquare,
hollowTriangleDown: HollowTriangleDown,
hollowTriangle: HollowTriangle,
hollowBowtie: HollowBowtie,
point: Point,
plus: Plus,
diamond: Diamond,
square: Square,
triangle: Triangle,
hexagon: Hexagon,
cross: Cross,
bowtie: Bowtie,
hyphen: Hyphen,
line: Line,
tick: Tick,
triangleDown: TriangleDown,
};

Point3D.props = {
Expand Down
15 changes: 8 additions & 7 deletions 3d/src/shape/interval3D/cone.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,23 @@ export const Cone: SC<ConeOptions> = (options, context) => {
// Render border only when colorAttribute is stroke.
const { ...style } = options;

if (!context.coneGeometry) {
const renderer = context.canvas.getConfig().renderer;
if (!context!.coneGeometry) {
const renderer = context!.canvas.getConfig().renderer;
const plugin = renderer.getPlugin("device-renderer");
const device = plugin.getDevice();
// create a cone geometry
context.coneGeometry = new ConeGeometry(device, {
context!.coneGeometry = new ConeGeometry(device, {
peakRadius: 0,
baseRadius: 0.5,
height: 1,
});
// create a material with Lambert lighting model
context.coneMaterial = new MeshLambertMaterial(device);
context!.coneMaterial = new MeshLambertMaterial(device);
}

return (_points, value, defaults) => {
const points = _points as unknown as Vector3[];
const { color: defaultColor } = defaults;
const { color: defaultColor } = defaults!;
const { color = defaultColor, transform, opacity } = value;
const [cx, cy, cz] = getOrigin(points);

Expand All @@ -37,8 +37,8 @@ export const Cone: SC<ConeOptions> = (options, context) => {
x: cx,
y: cy,
z: cz,
geometry: context.coneGeometry,
material: context.coneMaterial,
geometry: context!.coneGeometry,
material: context!.coneMaterial,
},
});
cone.setOrigin(0, 0, 0);
Expand All @@ -48,6 +48,7 @@ export const Cone: SC<ConeOptions> = (options, context) => {
.call(applyStyle, defaults)
.style("fill", color)
.style("transform", transform)
.style("visibility", "visible")
.style(toOpacityKey(options), opacity)
.call(applyStyle, style)
.node();
Expand Down
11 changes: 5 additions & 6 deletions 3d/src/shape/interval3D/cube.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,8 @@ export const Cube: SC<CubeOptions> = (options, context) => {
// Render border only when colorAttribute is stroke.
const { ...style } = options;

// @ts-ignore
if (!context.cubeGeometry) {
const renderer = context.canvas.getConfig().renderer;
if (!context!.cubeGeometry) {
const renderer = context!.canvas.getConfig().renderer;
const plugin = renderer.getPlugin("device-renderer");
const device = plugin.getDevice();
// create a cube geometry
Expand All @@ -24,13 +23,12 @@ export const Cube: SC<CubeOptions> = (options, context) => {
depth: 1,
});
// create a material with Lambert lighting model
// @ts-ignore
context.cubeMaterial = new MeshLambertMaterial(device);
context!.cubeMaterial = new MeshLambertMaterial(device);
}

return (_points, value, defaults) => {
const points = _points as unknown as Vector3[];
const { color: defaultColor } = defaults;
const { color: defaultColor } = defaults!;
const { color = defaultColor, transform, opacity } = value;
const [cx, cy, cz] = getOrigin(points);

Expand All @@ -56,6 +54,7 @@ export const Cube: SC<CubeOptions> = (options, context) => {
.call(applyStyle, defaults)
.style("fill", color)
.style("transform", transform)
.style("visibility", "visible")
.style(toOpacityKey(options), opacity)
.call(applyStyle, style)
.node();
Expand Down
15 changes: 8 additions & 7 deletions 3d/src/shape/interval3D/cylinder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,22 @@ export const Cylinder: SC<CylinderOptions> = (options, context) => {
// Render border only when colorAttribute is stroke.
const { ...style } = options;

if (!context.cylinderGeometry) {
const renderer = context.canvas.getConfig().renderer;
if (!context!.cylinderGeometry) {
const renderer = context!.canvas.getConfig().renderer;
const plugin = renderer.getPlugin("device-renderer");
const device = plugin.getDevice();
// create a cylinder geometry
context.cylinderGeometry = new CylinderGeometry(device, {
context!.cylinderGeometry = new CylinderGeometry(device, {
radius: 0.5,
height: 1,
});
// create a material with Lambert lighting model
context.cylinderMaterial = new MeshLambertMaterial(device);
context!.cylinderMaterial = new MeshLambertMaterial(device);
}

return (_points, value, defaults) => {
const points = _points as unknown as Vector3[];
const { color: defaultColor } = defaults;
const { color: defaultColor } = defaults!;
const { color = defaultColor, transform, opacity } = value;
const [cx, cy, cz] = getOrigin(points);

Expand All @@ -36,8 +36,8 @@ export const Cylinder: SC<CylinderOptions> = (options, context) => {
x: cx,
y: cy,
z: cz,
geometry: context.cylinderGeometry,
material: context.cylinderMaterial,
geometry: context!.cylinderGeometry,
material: context!.cylinderMaterial,
},
});
cylinder.setOrigin(0, 0, 0);
Expand All @@ -47,6 +47,7 @@ export const Cylinder: SC<CylinderOptions> = (options, context) => {
.call(applyStyle, defaults)
.style("fill", color)
.style("transform", transform)
.style("visibility", "visible")
.style(toOpacityKey(options), opacity)
.call(applyStyle, style)
.node();
Expand Down
3 changes: 1 addition & 2 deletions 3d/src/shape/line3D/line.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,10 @@ export type LineOptions = Record<string, any>;

export const Line: SC<LineOptions> = (options, context) => {
return (P, value, defaults) => {
const { color: defaultColor, lineWidth: defaultSize, ...rest } = defaults;
const { color: defaultColor, lineWidth: defaultSize, ...rest } = defaults!;
const { color = defaultColor, size = defaultSize } = value;
const stroke = color;
const finalStyle = {
isBillboard: true,
...rest,
...(stroke && { stroke }),
...(size && { lineWidth: size }),
Expand Down
Loading

0 comments on commit eaf7b8c

Please sign in to comment.