vectorized rung builder

This commit is contained in:
Tim
2024-04-30 16:43:12 -04:00
parent 2effb1f43a
commit 9094a10fe3
3 changed files with 107 additions and 24 deletions

View File

@@ -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;

View File

@@ -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
View 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
}