vectorized rung builder
This commit is contained in:
@@ -55,7 +55,6 @@ import {HLine} from "@/charts/shape.js";
|
||||
const s = useStore()
|
||||
const os = useOrderStore()
|
||||
const co = useChartOrderStore()
|
||||
const theme = useTheme().current
|
||||
const props = defineProps(['order', 'builder'])
|
||||
const emit = defineEmits(['update:builder'])
|
||||
|
||||
@@ -251,6 +250,7 @@ function setModelValue(model, value) {
|
||||
|
||||
<style scoped lang="scss">
|
||||
td.weight {
|
||||
width: 11em;
|
||||
padding-left: 0.5em;
|
||||
padding-right: 0.5em;
|
||||
text-align: right;
|
||||
|
||||
@@ -41,6 +41,7 @@ import {linspace, sideColor} from "@/misc.js";
|
||||
import {computed, watchEffect} from "vue";
|
||||
import Color from "color";
|
||||
import {cancelDrawing} from "@/charts/chart.js";
|
||||
import {devectorize, vectorAdd, vectorDiv, vectorMul, vectorSub, vectorIsNull, vectorize} from "@/vector.js";
|
||||
|
||||
const os = useOrderStore()
|
||||
const co = useChartOrderStore()
|
||||
@@ -55,11 +56,11 @@ const props = defineProps({
|
||||
mode: { type: Number, default: 0 }, // rung addition mode: 0 = split, 1 = extend
|
||||
flip: { type: Boolean, default: false }, // if true, the skew slider is flipped upside-down
|
||||
orientation: { type: Number, default: 1 }, // 0 = horizontal slider, 1 = vertical
|
||||
// values may be scalars or vector arrays
|
||||
getModelValue: Function, // getModelValue(model) -> value
|
||||
setModelValue: Function, // setModelValue(model,value) -> void
|
||||
getPointsValue: Function, // getValueFromPoints(points) -> value
|
||||
setValues: Function, // setValues(values:Array) -> void
|
||||
setWeights: Function, // setValues(values:Array) -> void
|
||||
setWeights: Function, // setWeights(values:Array) -> void
|
||||
})
|
||||
|
||||
const flippedSign = computed(()=>props.flip?-1:1)
|
||||
@@ -88,37 +89,38 @@ const rungs = computed({
|
||||
return
|
||||
}
|
||||
let [a,b] = endpoints.value
|
||||
const prevR = props.builder.rungs
|
||||
r = Number(r)
|
||||
const prevR = Number(props.builder.rungs)
|
||||
props.builder.rungs = r
|
||||
// console.log('set rungs', r, ...endpoints.value)
|
||||
if ( r > 0 && b === null ) {
|
||||
console.log('set rungs', prevR, r, a, b)
|
||||
if ( r > 0 && vectorIsNull(b) ) {
|
||||
console.log('convert to range')
|
||||
// convert single shape to a range
|
||||
if (props.mode===0) {
|
||||
const width = props.stdWidth
|
||||
const mid = a
|
||||
a = mid - width/2
|
||||
b = mid + width/2
|
||||
a = vectorAdd(mid, -width/2)
|
||||
b = vectorAdd(mid, +width/2)
|
||||
endpoints.value = [a,b]
|
||||
}
|
||||
else if (props.mode===1 ) {
|
||||
endpoints.value = [a, a+props.stdWidth]
|
||||
endpoints.value = [a, vectorAdd(a,props.stdWidth)]
|
||||
}
|
||||
else
|
||||
throw Error(`Unknown rung mode ${props.mode}`)
|
||||
}
|
||||
else if ( r === 1 && b !== null ) {
|
||||
else if ( r === 1 && !vectorIsNull(b) ) {
|
||||
// convert from a range to a single shape
|
||||
if (props.mode===0)
|
||||
a = (a + b) / 2
|
||||
a = vectorDiv(vectorAdd(a,b), 2)
|
||||
b = null
|
||||
endpoints.value = [a, b]
|
||||
}
|
||||
else {
|
||||
// from multi to multi
|
||||
if (props.mode===1) {
|
||||
const width = (b - a) / (prevR-1)
|
||||
b = a + width * (r-1)
|
||||
const width = vectorDiv(vectorSub(b, a), (prevR-1))
|
||||
b = vectorMul(vectorAdd(a, width), (r-1))
|
||||
endpoints.value = [a, b]
|
||||
}
|
||||
}
|
||||
@@ -128,14 +130,27 @@ const rungs = computed({
|
||||
|
||||
const values = computed(()=>{
|
||||
const [a, b] = endpoints.value
|
||||
console.log('values', a, b)
|
||||
const r = props.builder.rungs
|
||||
let result
|
||||
if ( a===null || !r )
|
||||
if ( !r || vectorIsNull(a) )
|
||||
result = [] // no data
|
||||
else if (r===1)
|
||||
result = [a] // single shape
|
||||
else
|
||||
result = linspace(a, b, r) // linear spacing
|
||||
else {
|
||||
const columns = []
|
||||
for (let i=0; i<a.length; i++)
|
||||
columns.push(linspace(a[i], b[i], r)) // linear spacing for each dimension
|
||||
// transpose
|
||||
result = []
|
||||
for (let i=0; i<r; i++) {
|
||||
const vector = []
|
||||
for (let j=0; j<a.length; j++)
|
||||
vector.push(columns[j][i])
|
||||
result.push(devectorize(vector))
|
||||
}
|
||||
}
|
||||
console.log('vectorized values', result)
|
||||
props.setValues(result)
|
||||
return result;
|
||||
})
|
||||
@@ -180,11 +195,21 @@ const colorStyle = computed(() => {
|
||||
// we keep two special control shapes as the edges of the range, with deletable shapes in-between
|
||||
|
||||
function createShape(value, model, onModel, onDelete) {
|
||||
props.setModelValue(model, value)
|
||||
setModelValue(model, value)
|
||||
return new props.shape(model, onModel, onDelete) // props.shape is the constructor function
|
||||
}
|
||||
|
||||
|
||||
function getModelValue(model) {
|
||||
return vectorize(props.getModelValue(model));
|
||||
}
|
||||
|
||||
|
||||
function setModelValue(model, value) {
|
||||
props.setModelValue(model, devectorize(value))
|
||||
}
|
||||
|
||||
|
||||
function translateOnModel(shape) {
|
||||
const oldOnModel = shape.onModel
|
||||
shape.onModel = function (model, oldModel) {
|
||||
@@ -192,15 +217,15 @@ function translateOnModel(shape) {
|
||||
// console.log('translateOnDrag', this.beingDragged(), shape.ourPoints)
|
||||
if (!this.beingDragged())
|
||||
return
|
||||
const prev = props.getModelValue(oldModel)
|
||||
const cur = props.getModelValue(this.model)
|
||||
const prev = getModelValue(oldModel)
|
||||
const cur = getModelValue(this.model)
|
||||
const delta = cur - prev
|
||||
// console.log('delta', shape.id, prev, cur, delta)
|
||||
let [a, b] = endpoints.value
|
||||
if (delta !== 0) {
|
||||
a += delta
|
||||
a = vectorAdd(a, delta)
|
||||
if (rungs.value > 1)
|
||||
b += delta
|
||||
b = vectorAdd(b, delta)
|
||||
endpoints.value = [a, b]
|
||||
}
|
||||
}
|
||||
@@ -213,7 +238,7 @@ function setModelColor(model) {
|
||||
|
||||
const shapeA = createShape(endpoints.value[0], {color: defaultColor},
|
||||
function (model) {
|
||||
const value = props.getModelValue(model);
|
||||
const value = getModelValue(model);
|
||||
if (value !== endpoints.value[0])
|
||||
endpoints.value = [value, endpoints.value[1]]
|
||||
setModelColor(model)
|
||||
@@ -225,7 +250,7 @@ if (props.mode===1)
|
||||
|
||||
const shapeB = createShape(endpoints.value[1], {color:defaultColor},
|
||||
function (model) {
|
||||
const value = props.getModelValue(model);
|
||||
const value = getModelValue(model);
|
||||
if (value !== endpoints.value[1])
|
||||
endpoints.value = [endpoints.value[0], value]
|
||||
setModelColor(model)
|
||||
@@ -261,7 +286,7 @@ function makeModel(index) {
|
||||
amount: props.order.amount * alloc,
|
||||
amountSymbol: amountSymbol.value,
|
||||
}
|
||||
props.setModelValue(result, values.value[index])
|
||||
setModelValue(result, values.value[index])
|
||||
return result
|
||||
}
|
||||
|
||||
|
||||
58
src/vector.js
Normal file
58
src/vector.js
Normal file
@@ -0,0 +1,58 @@
|
||||
export function vectorize(value) {
|
||||
if (value === undefined) {
|
||||
console.warn('vectorizing undefined as null')
|
||||
return null
|
||||
}
|
||||
if (value === null)
|
||||
return null
|
||||
if (value.length === undefined)
|
||||
value = [value]
|
||||
return value;
|
||||
}
|
||||
|
||||
export function devectorize(value) {
|
||||
return value === null || value.length === 0 ? null : value.length === 1 ? value[0] : value
|
||||
}
|
||||
|
||||
|
||||
export function vectorIsNull(value) {
|
||||
console.log('vectorIsNull', value, value === null || value.length === 1 && value[0] === null)
|
||||
return value === null || value.length === 1 && value[0] === null
|
||||
}
|
||||
|
||||
|
||||
export function vectorAdd(a, b) {
|
||||
const result = []
|
||||
const scalarB = b.length === undefined
|
||||
for( let i=0; i<a.length; i++ )
|
||||
result.push(a[i]+(scalarB ? b : b[i]))
|
||||
console.log('vectorAdd', a, b, result)
|
||||
return result
|
||||
}
|
||||
|
||||
export function vectorSub(a, b) {
|
||||
const result = []
|
||||
const scalarB = b.length === undefined
|
||||
for( let i=0; i<a.length; i++ )
|
||||
result.push(a[i]-(scalarB ? b : b[i]))
|
||||
console.log('vectorSub', a, b, result)
|
||||
return result
|
||||
}
|
||||
|
||||
export function vectorMul(a, b) {
|
||||
const result = []
|
||||
const scalarB = b.length === undefined
|
||||
for( let i=0; i<a.length; i++ )
|
||||
result.push(a[i]*(scalarB ? b : b[i]))
|
||||
console.log('vectorMul', a, b, result)
|
||||
return result
|
||||
}
|
||||
|
||||
export function vectorDiv(a, b) {
|
||||
const result = []
|
||||
const scalarB = b.length === undefined
|
||||
for( let i=0; i<a.length; i++ )
|
||||
result.push(a[i]/(scalarB ? b : b[i]))
|
||||
console.log('vectorDiv', a, b, result)
|
||||
return result
|
||||
}
|
||||
Reference in New Issue
Block a user