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