hefeihvac_java/node_modules/echarts-gl/lib/util/geometry/Lines2D.js

447 lines
12 KiB
JavaScript
Raw Permalink Normal View History

2024-04-07 18:15:00 +08:00
/**
* Lines geometry
* Use screen space projected lines lineWidth > MAX_LINE_WIDTH
* https://mattdesl.svbtle.com/drawing-lines-is-hard
* @module echarts-gl/util/geometry/LinesGeometry
* @author Yi Shen(http://github.com/pissang)
*/
import Geometry from 'claygl/src/Geometry';
import * as echarts from 'echarts/lib/echarts';
import dynamicConvertMixin from './dynamicConvertMixin';
import glmatrix from 'claygl/src/dep/glmatrix';
var vec2 = glmatrix.vec2; // var CURVE_RECURSION_LIMIT = 8;
// var CURVE_COLLINEAR_EPSILON = 40;
var sampleLinePoints = [[0, 0], [1, 1]];
/**
* @constructor
* @alias module:echarts-gl/util/geometry/LinesGeometry
* @extends clay.Geometry
*/
var LinesGeometry = Geometry.extend(function () {
return {
segmentScale: 4,
dynamic: true,
/**
* Need to use mesh to expand lines if lineWidth > MAX_LINE_WIDTH
*/
useNativeLine: true,
attributes: {
position: new Geometry.Attribute('position', 'float', 2, 'POSITION'),
normal: new Geometry.Attribute('normal', 'float', 2),
offset: new Geometry.Attribute('offset', 'float', 1),
color: new Geometry.Attribute('color', 'float', 4, 'COLOR')
}
};
},
/** @lends module: echarts-gl/util/geometry/LinesGeometry.prototype */
{
/**
* Reset offset
*/
resetOffset: function () {
this._vertexOffset = 0;
this._faceOffset = 0;
this._itemVertexOffsets = [];
},
/**
* @param {number} nVertex
*/
setVertexCount: function (nVertex) {
var attributes = this.attributes;
if (this.vertexCount !== nVertex) {
attributes.position.init(nVertex);
attributes.color.init(nVertex);
if (!this.useNativeLine) {
attributes.offset.init(nVertex);
attributes.normal.init(nVertex);
}
if (nVertex > 0xffff) {
if (this.indices instanceof Uint16Array) {
this.indices = new Uint32Array(this.indices);
}
} else {
if (this.indices instanceof Uint32Array) {
this.indices = new Uint16Array(this.indices);
}
}
}
},
/**
* @param {number} nTriangle
*/
setTriangleCount: function (nTriangle) {
if (this.triangleCount !== nTriangle) {
if (nTriangle === 0) {
this.indices = null;
} else {
this.indices = this.vertexCount > 0xffff ? new Uint32Array(nTriangle * 3) : new Uint16Array(nTriangle * 3);
}
}
},
_getCubicCurveApproxStep: function (p0, p1, p2, p3) {
var len = vec2.dist(p0, p1) + vec2.dist(p2, p1) + vec2.dist(p3, p2);
var step = 1 / (len + 1) * this.segmentScale;
return step;
},
/**
* Get vertex count of cubic curve
* @param {Array.<number>} p0
* @param {Array.<number>} p1
* @param {Array.<number>} p2
* @param {Array.<number>} p3
* @return number
*/
getCubicCurveVertexCount: function (p0, p1, p2, p3) {
var step = this._getCubicCurveApproxStep(p0, p1, p2, p3);
var segCount = Math.ceil(1 / step);
if (!this.useNativeLine) {
return segCount * 2 + 2;
} else {
return segCount * 2;
}
},
/**
* Get face count of cubic curve
* @param {Array.<number>} p0
* @param {Array.<number>} p1
* @param {Array.<number>} p2
* @param {Array.<number>} p3
* @return number
*/
getCubicCurveTriangleCount: function (p0, p1, p2, p3) {
var step = this._getCubicCurveApproxStep(p0, p1, p2, p3);
var segCount = Math.ceil(1 / step);
if (!this.useNativeLine) {
return segCount * 2;
} else {
return 0;
}
},
/**
* Get vertex count of line
* @return {number}
*/
getLineVertexCount: function () {
return this.getPolylineVertexCount(sampleLinePoints);
},
/**
* Get face count of line
* @return {number}
*/
getLineTriangleCount: function () {
return this.getPolylineTriangleCount(sampleLinePoints);
},
/**
* Get how many vertices will polyline take.
* @type {number|Array} points Can be a 1d/2d list of points, or a number of points amount.
* @return {number}
*/
getPolylineVertexCount: function (points) {
var pointsLen;
if (typeof points === 'number') {
pointsLen = points;
} else {
var is2DArray = typeof points[0] !== 'number';
pointsLen = is2DArray ? points.length : points.length / 2;
}
return !this.useNativeLine ? (pointsLen - 1) * 2 + 2 : (pointsLen - 1) * 2;
},
/**
* Get how many triangles will polyline take.
* @type {number|Array} points Can be a 1d/2d list of points, or a number of points amount.
* @return {number}
*/
getPolylineTriangleCount: function (points) {
var pointsLen;
if (typeof points === 'number') {
pointsLen = points;
} else {
var is2DArray = typeof points[0] !== 'number';
pointsLen = is2DArray ? points.length : points.length / 2;
}
return !this.useNativeLine ? (pointsLen - 1) * 2 : 0;
},
/**
* Add a cubic curve
* @param {Array.<number>} p0
* @param {Array.<number>} p1
* @param {Array.<number>} p2
* @param {Array.<number>} p3
* @param {Array.<number>} color
* @param {number} [lineWidth=1]
*/
addCubicCurve: function (p0, p1, p2, p3, color, lineWidth) {
if (lineWidth == null) {
lineWidth = 1;
} // incremental interpolation
// http://antigrain.com/research/bezier_interpolation/index.html#PAGE_BEZIER_INTERPOLATION
var x0 = p0[0],
y0 = p0[1];
var x1 = p1[0],
y1 = p1[1];
var x2 = p2[0],
y2 = p2[1];
var x3 = p3[0],
y3 = p3[1];
var step = this._getCubicCurveApproxStep(p0, p1, p2, p3);
var step2 = step * step;
var step3 = step2 * step;
var pre1 = 3.0 * step;
var pre2 = 3.0 * step2;
var pre4 = 6.0 * step2;
var pre5 = 6.0 * step3;
var tmp1x = x0 - x1 * 2.0 + x2;
var tmp1y = y0 - y1 * 2.0 + y2;
var tmp2x = (x1 - x2) * 3.0 - x0 + x3;
var tmp2y = (y1 - y2) * 3.0 - y0 + y3;
var fx = x0;
var fy = y0;
var dfx = (x1 - x0) * pre1 + tmp1x * pre2 + tmp2x * step3;
var dfy = (y1 - y0) * pre1 + tmp1y * pre2 + tmp2y * step3;
var ddfx = tmp1x * pre4 + tmp2x * pre5;
var ddfy = tmp1y * pre4 + tmp2y * pre5;
var dddfx = tmp2x * pre5;
var dddfy = tmp2y * pre5;
var t = 0;
var k = 0;
var segCount = Math.ceil(1 / step);
var points = new Float32Array((segCount + 1) * 3);
var points = [];
var offset = 0;
for (var k = 0; k < segCount + 1; k++) {
points[offset++] = fx;
points[offset++] = fy;
fx += dfx;
fy += dfy;
dfx += ddfx;
dfy += ddfy;
ddfx += dddfx;
ddfy += dddfy;
t += step;
if (t > 1) {
fx = dfx > 0 ? Math.min(fx, x3) : Math.max(fx, x3);
fy = dfy > 0 ? Math.min(fy, y3) : Math.max(fy, y3);
}
}
this.addPolyline(points, color, lineWidth);
},
/**
* Add a straight line
* @param {Array.<number>} p0
* @param {Array.<number>} p1
* @param {Array.<number>} color
* @param {number} [lineWidth=1]
*/
addLine: function (p0, p1, color, lineWidth) {
this.addPolyline([p0, p1], color, lineWidth);
},
/**
* Add a straight line
* @param {Array.<Array> | Array.<number>} points
* @param {Array.<number> | Array.<Array>} color
* @param {number} [lineWidth=1]
* @param {number} [arrayOffset=0]
* @param {number} [pointsCount] Default to be amount of points in the first argument
*/
addPolyline: function () {
var dirA = vec2.create();
var dirB = vec2.create();
var normal = vec2.create();
var tangent = vec2.create();
var point = [],
nextPoint = [],
prevPoint = [];
return function (points, color, lineWidth, arrayOffset, pointsCount) {
if (!points.length) {
return;
}
var is2DArray = typeof points[0] !== 'number';
if (pointsCount == null) {
pointsCount = is2DArray ? points.length : points.length / 2;
}
if (pointsCount < 2) {
return;
}
if (arrayOffset == null) {
arrayOffset = 0;
}
if (lineWidth == null) {
lineWidth = 1;
}
this._itemVertexOffsets.push(this._vertexOffset);
var notSharingColor = is2DArray ? typeof color[0] !== 'number' : color.length / 4 === pointsCount;
var positionAttr = this.attributes.position;
var colorAttr = this.attributes.color;
var offsetAttr = this.attributes.offset;
var normalAttr = this.attributes.normal;
var indices = this.indices;
var vertexOffset = this._vertexOffset;
var pointColor;
for (var k = 0; k < pointsCount; k++) {
if (is2DArray) {
point = points[k + arrayOffset];
if (notSharingColor) {
pointColor = color[k + arrayOffset];
} else {
pointColor = color;
}
} else {
var k2 = k * 2 + arrayOffset;
point = point || [];
point[0] = points[k2];
point[1] = points[k2 + 1];
if (notSharingColor) {
var k4 = k * 4 + arrayOffset;
pointColor = pointColor || [];
pointColor[0] = color[k4];
pointColor[1] = color[k4 + 1];
pointColor[2] = color[k4 + 2];
pointColor[3] = color[k4 + 3];
} else {
pointColor = color;
}
}
if (!this.useNativeLine) {
var offset;
if (k < pointsCount - 1) {
if (is2DArray) {
vec2.copy(nextPoint, points[k + 1]);
} else {
var k2 = (k + 1) * 2 + arrayOffset;
nextPoint = nextPoint || [];
nextPoint[0] = points[k2];
nextPoint[1] = points[k2 + 1];
} // TODO In case dir is (0, 0)
// TODO miterLimit
if (k > 0) {
vec2.sub(dirA, point, prevPoint);
vec2.sub(dirB, nextPoint, point);
vec2.normalize(dirA, dirA);
vec2.normalize(dirB, dirB);
vec2.add(tangent, dirA, dirB);
vec2.normalize(tangent, tangent);
var miter = lineWidth / 2 * Math.min(1 / vec2.dot(dirA, tangent), 2);
normal[0] = -tangent[1];
normal[1] = tangent[0];
offset = miter;
} else {
vec2.sub(dirA, nextPoint, point);
vec2.normalize(dirA, dirA);
normal[0] = -dirA[1];
normal[1] = dirA[0];
offset = lineWidth / 2;
}
} else {
vec2.sub(dirA, point, prevPoint);
vec2.normalize(dirA, dirA);
normal[0] = -dirA[1];
normal[1] = dirA[0];
offset = lineWidth / 2;
}
normalAttr.set(vertexOffset, normal);
normalAttr.set(vertexOffset + 1, normal);
offsetAttr.set(vertexOffset, offset);
offsetAttr.set(vertexOffset + 1, -offset);
vec2.copy(prevPoint, point);
positionAttr.set(vertexOffset, point);
positionAttr.set(vertexOffset + 1, point);
colorAttr.set(vertexOffset, pointColor);
colorAttr.set(vertexOffset + 1, pointColor);
vertexOffset += 2;
} else {
if (k > 1) {
positionAttr.copy(vertexOffset, vertexOffset - 1);
colorAttr.copy(vertexOffset, vertexOffset - 1);
vertexOffset++;
}
}
if (!this.useNativeLine) {
if (k > 0) {
var idx3 = this._faceOffset * 3;
var indices = this.indices; // 0-----2
// 1-----3
// 0->1->2, 1->3->2
indices[idx3] = vertexOffset - 4;
indices[idx3 + 1] = vertexOffset - 3;
indices[idx3 + 2] = vertexOffset - 2;
indices[idx3 + 3] = vertexOffset - 3;
indices[idx3 + 4] = vertexOffset - 1;
indices[idx3 + 5] = vertexOffset - 2;
this._faceOffset += 2;
}
} else {
colorAttr.set(vertexOffset, pointColor);
positionAttr.set(vertexOffset, point);
vertexOffset++;
}
}
this._vertexOffset = vertexOffset;
};
}(),
/**
* Set color of single line.
*/
setItemColor: function (idx, color) {
var startOffset = this._itemVertexOffsets[idx];
var endOffset = idx < this._itemVertexOffsets.length - 1 ? this._itemVertexOffsets[idx + 1] : this._vertexOffset;
for (var i = startOffset; i < endOffset; i++) {
this.attributes.color.set(i, color);
}
this.dirty('color');
}
});
echarts.util.defaults(LinesGeometry.prototype, dynamicConvertMixin);
export default LinesGeometry;