Dynamic (auto increment) input length (count) on a linear regression channel drawing, starting from given bar_index/datetime in Pine Script language - plot

My question is about the Linear Regression drawing.
The example in the documentation uses a fixed length (100), and is therefore :
shifting to the right on each new bar
of constant width (here 100 bars)
I'm trying to make it start from a custom point in time (x bars from now or bar_index or datetime...), so that :
it keeps extending on each new bar
but the starting point remains on the same location (until we change it in the settings).
That means that the length (input) would be dynamic and increase on each new bar.
I am getting the following error : Pine cannot determine the referencing length of a series. Try using max_bars_back in the study or strategy function.
Is it possible to do ?
Here is the code
//#version=4
study("Linear Regression", shorttitle="LinReg", overlay=true)
upperMult = input(title="Upper Deviation", defval=2)
lowerMult = input(title="Lower Deviation", defval=-2)
useUpperDev = input(title="Use Upper Deviation", defval=true)
useLowerDev = input(title="Use Lower Deviation", defval=true)
showPearson = input(title="Show Pearson's R", defval=true)
extendLines = input(title="Extend Lines", defval=false)
// ====================================================================
// ====================================================================
// Original parameter (the one that should increments)
// len = input(title="Count", defval=100)
// Unsuccessful attempt : "Starting from given bar_index"
barIndexOfStartingBar = 6392 - 80 // 6392 : Current bar_index, 80 : Offset to the starting bar
len = bar_index - barIndexOfStartingBar
len := nz(len[1]) + 1
// Unsuccessful attempt : "x bars from current bar"
startingPointFromCurrentBar = input(title="Count", defval=80)
len = (bar_index + startingPointFromCurrentBar) - bar_index
len := nz(len[1]) + 1
// ====================================================================
// ====================================================================
src = input(title="Source", defval=close)
extend = extendLines ? extend.right : extend.none
calcSlope(src, len) =>
if not barstate.islast or len <= 1
[float(na), float(na), float(na)]
else
sumX = 0.0
sumY = 0.0
sumXSqr = 0.0
sumXY = 0.0
for i = 0 to len - 1
val = src[i]
per = i + 1.0
sumX := sumX + per
sumY := sumY + val
sumXSqr := sumXSqr + per * per
sumXY := sumXY + val * per
slope = (len * sumXY - sumX * sumY) / (len * sumXSqr - sumX * sumX)
average = sumY / len
intercept = average - slope * sumX / len + slope
[slope, average, intercept]
[s, a, i] = calcSlope(src, len)
startPrice = i + s * (len - 1)
endPrice = i
var line baseLine = na
if na(baseLine) and not na(startPrice)
baseLine := line.new(bar_index - len + 1, startPrice, bar_index, endPrice, width=1, extend=extend, color=color.red)
else
line.set_xy1(baseLine, bar_index - len + 1, startPrice)
line.set_xy2(baseLine, bar_index, endPrice)
na
calcDev(src, len, slope, average, intercept) =>
upDev = 0.0
dnDev = 0.0
stdDevAcc = 0.0
dsxx = 0.0
dsyy = 0.0
dsxy = 0.0
periods = len - 1
daY = intercept + (slope * periods) / 2
val = intercept
for i = 0 to periods
price = high[i] - val
if (price > upDev)
upDev := price
price := val - low[i]
if (price > dnDev)
dnDev := price
price := src[i]
dxt = price - average
dyt = val - daY
price := price - val
stdDevAcc := stdDevAcc + price * price
dsxx := dsxx + dxt * dxt
dsyy := dsyy + dyt * dyt
dsxy := dsxy + dxt * dyt
val := val + slope
stdDev = sqrt(stdDevAcc / (periods == 0 ? 1 : periods))
pearsonR = dsxx == 0 or dsyy == 0 ? 0 : dsxy / sqrt(dsxx * dsyy)
[stdDev, pearsonR, upDev, dnDev]
[stdDev, pearsonR, upDev, dnDev] = calcDev(src, len, s, a, i)
upperStartPrice = startPrice + (useUpperDev ? upperMult * stdDev : upDev)
upperEndPrice = endPrice + (useUpperDev ? upperMult * stdDev : upDev)
var line upper = na
lowerStartPrice = startPrice + (useLowerDev ? lowerMult * stdDev : -dnDev)
lowerEndPrice = endPrice + (useLowerDev ? lowerMult * stdDev : -dnDev)
var line lower = na
if na(upper) and not na(upperStartPrice)
upper := line.new(bar_index - len + 1, upperStartPrice, bar_index, upperEndPrice, width=1, extend=extend, color=#0000ff)
else
line.set_xy1(upper, bar_index - len + 1, upperStartPrice)
line.set_xy2(upper, bar_index, upperEndPrice)
na
if na(lower) and not na(lowerStartPrice)
lower := line.new(bar_index - len + 1, lowerStartPrice, bar_index, lowerEndPrice, width=1, extend=extend, color=#0000ff)
else
line.set_xy1(lower, bar_index - len + 1, lowerStartPrice)
line.set_xy2(lower, bar_index, lowerEndPrice)
na
// Pearson's R
var label r = na
transparent = color.new(color.white, 100)
label.delete(r[1])
if showPearson and not na(pearsonR)
r := label.new(bar_index - len + 1, lowerStartPrice, tostring(pearsonR, "#.################"), color=transparent, textcolor=#0000ff, size=size.normal, style=label.style_labelup)

With these changes you should be able to go back a few thousand bars:
study("Linear Regression", shorttitle="LinReg", overlay=true, max_bars_back = 4999)
and either one of these:
// #1
offsetToStart = input(100, minval = 1, step = 100)
len = max(1, offsetToStart)
// #2
startingBar = input(10000, minval = 1, step = 100)
len = max(1, bar_index - startingBar)

What you are looking for is called anchoring. You can do this with a trick. What I usually do is the following:
p = input("D", title="Period", type=input.resolution)
offsetToStart = input(0, title="Begin Offset") // remove the minval
newbar(p) => change(time(p)) == 0?0:1
nb = newbar(p)
bars = barssince(nb) + offsetToStart
var line l1 = na
l1 := line.new(bar_index[bars], open, bar_index[bars], open + syminfo.mintick, extend=extend.both)
line.delete(l1[1])
Remember to remove the minval. Chose the period and you can now anchor beginning of your indicator. Playaround with p

Related

Tradingview Pine Script plotshape function not working with conditional series - where's the error?

I am trying to convert a strategy Pine Script into a study one to just plot buy and sell signals, but I can't figure out how to make the function plotshape work. I keep getting error message:
Cannot call 'plotshape' with arguments (series[bool], style=const
string, text=literal string, color=const color, size=const string,
location=const string, transp=literal bool); available overloads:
plotshape(series[bool], const string, input string, input string,
series[color], input integer, series[integer], const string,
series[color], const bool, const string, input integer, const integer,
string) =void; plotshape(<arg_series_type>, const string, input
string, input string, <arg_color_type>, input integer,
series[integer], const string, <arg_textcolor_type>, const bool, const
string, input integer, const integer, string) =void
Where's the error?
//#version=4
study(title="Trend Following Long Only", overlay=true)
lookback_length = input(200, type=input.integer, minval=1,
title="Lookback Length") smoother_length = input(3,
type=input.integer, minval=1, title="Smoother Length") atr_length =
input(10, type=input.integer, minval=1, title="ATR Length")
atr_multiplier = input(0.5, type=input.float, minval=0.0, title="ATR
Multiplier")
vola = atr(atr_length) * atr_multiplier price = sma(close, 3)
l = ema(lowest(low, lookback_length), smoother_length) h =
ema(highest(high, lookback_length), smoother_length) center = (h + l)
* 0.5 upper = center + vola lower = center - vola trend = ema(price upper ? 1 : (price < lower ? -1 : 0), 3) c1 = trend < 0 ? upper :
(trend 0 ? lower: center)
buy_signal = crossover(trend, 0) plotshape(buy_signal ? true : na,style=shape.triangleup,text="Buy",color=color.green,size=size.small,location=location.belowbar,transp=false)
sell_signal = crossunder(trend, 0) plotshape(sell_signal ? true :
na,style=shape.triangledown,text="Sell",color=color.red,size=size.small,location=location.abovebar,transp=false)
phigh = plot(h, color=color.green) plow = plot(l, color=color.red)
pcenter = plot(center, color=color.black) pclose = plot(close,
transp=100)
clr = trend 0.0 ? color.green : (trend < -0.0 ? color.red :
color.yellow) fill(pcenter, pclose, color=clr, transp=85) fill(phigh,
pcenter, color=color.green, transp=95) fill(plow, pcenter,
color=color.red, transp=95)
The problem was that you were using a boolean for the transp= argument in plotshape().
The transp argument must be an integer from 0 to 100.
This will work:
//#version=4
study(title="Trend Following Long Only", overlay=true)
lookback_length = input(200, type=input.integer, minval=1, title="Lookback Length")
smoother_length = input(3, type=input.integer, minval=1, title="Smoother Length")
atr_length = input(10, type=input.integer, minval=1, title="ATR Length")
atr_multiplier = input(0.5, type=input.float, minval=0.0, title="ATR Multiplier")
vola = atr(atr_length) * atr_multiplier
price = sma(close, 3)
l = ema(lowest(low, lookback_length), smoother_length)
h = ema(highest(high, lookback_length), smoother_length)
center = (h + l) * 0.5
upper = center + vola
lower = center - vola
trend = ema(price > upper ? 1 : (price < lower ? -1 : 0), 3)
c1 = trend < 0 ? upper : (trend > 0 ? lower : center)
buy_signal = crossover(trend, 0)
plotshape(buy_signal,style=shape.triangleup,text="Buy",color=color.green,size=size.small,location=location.belowbar,transp=80)
sell_signal = crossunder(trend, 0)
plotshape(sell_signal,style=shape.triangledown,text="Sell",color=color.red,size=size.small,location=location.abovebar,transp=80)
phigh = plot(h, color=color.green)
plow = plot(l, color=color.red)
pcenter = plot(center, color=color.black)
pclose = plot(close,transp=100)
clr = trend > 0.0 ? color.green : (trend < -0.0 ? color.red : color.yellow)
fill(pcenter, pclose, color=clr, transp=85)
fill(phigh, pcenter, color=color.green, transp=95)
fill(plow, pcenter, color=color.red, transp=95)

How to use optim.jl to estimate ARMA(p,q) MLE?

I'm trying to estimate ARMA(p,q) models with julia. I have a problem with the optimization of the log-likelihood function.
I have a function named "SsfLogLikConc" that estimates my concentrated log-likelihood and i would like to see it as function of vP, that is the value of my parameters phi and theta, and then optimize this function starting from the value vP0=zeros(cp+cq,1)where cp and cp represent the p and q orders of my ARMA(p,q) model. I tried to do it in this way:
vP0=zeros(cp+cq,1)
function f(vP)
SsfLogLikConc(vP, vy, cp, cq)
end
using Optim
res=optimize(f, vP0, BFGS())
But i keep getting errors from the optimize function even if change the method. Here is the full code:
function FisherInvTransform(Vp)
vt = (exp(2*vP)-1) ./ (exp(2*vP)+1)
end
function ReparAR(vr)
cp = length(vr)
vphi = zeros(cp,1);
vphi[1] = vr[1]
for k=2:cp
vphi[1:k-1] = vphi[1:k-1] - vr[k] * vphi[k-1:-1:1]
vphi[k] = vr[k]
end
end
function ReparMA(vr)
cq = length(vr)
vtheta = zeros(cq,1)
vtheta[1] = vr[1]
for k = 2:cq
vtheta[1:k-1] = vtheta[1:k-1] + vr[k] * vtheta[k-1:-1:1]
vtheta[k] = vr[k]
end
end
function SetStateSpaceModel(vP, cp, cq)
cm = max(cp,cq)
vphi = zeros(cm, 1)
vtheta = zeros(cm, 1)
if (cp > 0)
vphi[1:cp] = ReparAR(FisherInvTransform(vP[1:cp]))
end
if (cq > 0)
vtheta[1:cq] = ReparMA(FisherInvTransform(vP[cp+1:cp+cq]));
end
#Measurement equation: % y_{t} = Z_t \alpha_{t} + G_t \epsilon_t
mZ = [1, zeros(1, cm-1)]
mGG = 1 #G_t * G_t'
#Transition equation: % \alpha_{t+1} = T_t \alpha_{t} + H_t \epsilon_t
mT = [vphi, [eye(cm-1); zeros(1, cm-1)] ]
disp(mT)
disp( vphi)
mH = vtheta+vphi
mHH = mH*mH' #H_t * H_t'
mHG = mH
#initial conditions
va = zeros(cm,1)
mP = reshape(inv(eye(cm^2)-kron(mT,mT)) * reshape(mHH, cm^2,1) , cm, cm)
end
function KalmanFilter(vy, mZ, mGG, mT, mHH, mHG, va, mP)
cm = length(va) #n. of state elements and of diffuse elements
ck = 1
cn = length(vy)
#Initialisation of matrices and scalars
dLogf = 0
dSumSquares = 0
vInnovations = NaN(1, cn) #stores the KF innovations
vVarInnovations = NaN(1, cn)
mStatePred = NaN(cm, cn) #stores the states predictions
mCovStatePred = NaN(cm, cn)
for i = 1:cn
dv = vy[i] - mZ * va; dF = mZ * mP * mZ' + mGG;
vK = (mT * mP * mZ' + mHG) / dF;
va = mT * va + vK * dv; mP = mT * mP * mT' + mHH - vK * vK' * dF ;
if (i > ck)
vInnovations[i] = dv; vVarInnovations[i] = dF;
dLogf = dLogf + log(dF); dSumSquares = dSumSquares + dv^2 /dF;
end
mStatePred[:,i] = va; mCovStatePred[:,i] = diag(mP);
end
dSigma = dSumSquares/(cn-ck);
dLogLik = -0.5 * ((cn - ck) * log(2 * pi) + dLogf + dSumSquares );
dLogLikConc = -0.5*((cn - ck)* (log(2 * pi * dSigma)+1) + dLogf );
dPev = dSigma * dF ; # Final prediction error variance
end
function SsfLogLikConc(vP, vy, cp, cq)
SetStateSpaceModel(vP, cp, cq)
dLogF = 0; dSumSquares = 0;
cn = length(vy)
for i = 1:cn
dv = vy[i] - mZ * va; dF = mZ * mP * mZ' + mGG;
vK = (mT * mP * mZ' + mHG) / dF;
va = mT * va + vK * dv; mP = mT * mP * mT' + mHH - vK * dF * vK' ;
dLogF = dLogF + log(dF);
dSumSquares = dSumSquares + dv^2 /dF;
end
dSigma2 = dSumSquares/cn;
dLogLikConc = 0.5*( cn * (log(dSigma2)+1) + dLogF ); # concentrated LF (change of sign)
end
#Pkg.add("DataFrames")
using DataFrames;
cd("$(homedir())/Desktop")
pwd()
df=readtable("df.csv")
df
o=df[2]
mean(o)
vy=zeros(1000)
for i=1:length(o)
vy[i]=o[i]-mean(o)
end
cp = 1; cq =1;
vP0 = zeros(cp+cq,1)
function f(vP)
SsfLogLikConc(vP, vy, cp, cq)
end
#Pkg.add("Optim")
using Optim
res=optimize(f, vP0, BFGS())
Thank you for reading, I hope that someone will help me!

How to get length of path?

I want to know the length of a Path.
For example, if I have a straight line I can just compute the length with its start x,y and end x,y values. But it gets quickly very tricky if I use QuadCurves or CubicCurves.
Is there any way to get the length or an approximation of the length of a Path?
For example the following path:
Path path = new Path();
MoveTo moveTo = new MoveTo(start.getX(), start.getY());
double controlPointX = 50;
CubicCurveTo cubicCurveTo = new CubicCurveTo(start.getX() + controlPointX, start.getY(),
start.getX() + controlPointX, end.getY(), end.getX(), end.getY());
path.getElements().addAll(moveTo, cubicCurveTo);
I needed this recently as well. I couldn't find any solutions online, but it occurred to me PathTransition must be calculating it. It does, see PathTransition.recomputeSegment, where totalLength is calculated.
Unfortunately, it uses many internal APIs in Node and the PathElement to convert the Path to a java.awt.geom.Path2D. I extracted these methods out and replaced other usages of com.sun classes with java.awt ones, then pulled the parts relevant to calculating length out of PathTransition.recomputeSegments.
The resulting code is below. It is in Kotlin not Java, but it should be easy to convert it back to Java. I have not yet tested it extensively but it seems to be working on the fairly complex paths I have tested it against. I've compared my results to the length calculated by PathTransition and they are very close, I believe the discrepancies are due to my code using Path2D.Double where as Path2D.Float is used by PathElement.impl_addTo.
fun Transform.toAffineTransform(): AffineTransform {
if(!isType2D) throw UnsupportedOperationException("Conversion of 3D transforms is unsupported")
return AffineTransform(mxx, myx, mxy, myy, tx, ty)
}
val Path.totalLength: Double
get() {
var length = 0.0
val coords = DoubleArray(6)
var pt = 0 // Previous segment type
var px = 0.0 // Previous x-coordinate
var py = 0.0 // Previous y-coordinate
var mx = 0.0 // Last move to x-coordinate
var my = 0.0 // Last move to y-coordinate
val pit = toPath2D().getPathIterator(localToParentTransform.toAffineTransform(), 1.0)
while(!pit.isDone) {
val type = pit.currentSegment(coords)
val x = coords[0]
val y = coords[1]
when(type) {
PathIterator.SEG_MOVETO -> {
mx = x
my = y
}
PathIterator.SEG_LINETO -> {
val dx = x - px
val dy = y - py
val l = sqrt(dx * dx + dy * dy)
if(l >= 1 || pt == PathIterator.SEG_MOVETO) length += l
}
PathIterator.SEG_CLOSE -> {
val dx = x - mx
val dy = y - my
val l = sqrt(dx * dx + dy * dy)
if(l >= 1 || pt == PathIterator.SEG_MOVETO) length += l
}
}
pt = type
px = x
py = y
pit.next()
}
return length
}
fun Path.toPath2D(): Path2D {
val path: Path2D = Path2D.Double(if(fillRule == FillRule.EVEN_ODD) Path2D.WIND_EVEN_ODD else Path2D.WIND_NON_ZERO)
for(e in elements) {
when(e) {
is Arc2D -> append(e as ArcTo, path) // Why isn't this smart casted?
is ClosePath -> path.closePath()
is CubicCurveTo -> append(e, path)
is HLineTo -> append(e, path)
is LineTo -> append(e, path)
is MoveTo -> append(e, path)
is QuadCurveTo -> append(e, path)
is VLineTo -> append(e, path)
else -> throw UnsupportedOperationException("Path contains unknown PathElement type: " + e::class.qualifiedName)
}
}
return path
}
private fun append(arcTo: ArcTo, path: Path2D) {
val x0 = path.currentPoint.x
val y0 = path.currentPoint.y
val localX = arcTo.x
val localY = arcTo.y
val localSweepFlag = arcTo.isSweepFlag
val localLargeArcFlag = arcTo.isLargeArcFlag
// Determine target "to" position
val xto = if(arcTo.isAbsolute) localX else localX + x0
val yto = if(arcTo.isAbsolute) localY else localY + y0
// Compute the half distance between the current and the final point
val dx2 = (x0 - xto) / 2.0
val dy2 = (y0 - yto) / 2.0
// Convert angle from degrees to radians
val xAxisRotationR = Math.toRadians(arcTo.xAxisRotation)
val cosAngle = Math.cos(xAxisRotationR)
val sinAngle = Math.sin(xAxisRotationR)
//
// Step 1 : Compute (x1, y1)
//
val x1 = cosAngle * dx2 + sinAngle * dy2
val y1 = -sinAngle * dx2 + cosAngle * dy2
// Ensure radii are large enough
var rx = abs(arcTo.radiusX)
var ry = abs(arcTo.radiusY)
var Prx = rx * rx
var Pry = ry * ry
val Px1 = x1 * x1
val Py1 = y1 * y1
// check that radii are large enough
val radiiCheck = Px1 / Prx + Py1 / Pry
if (radiiCheck > 1.0) {
rx *= sqrt(radiiCheck)
ry *= sqrt(radiiCheck)
if(rx == rx && ry == ry) {/* not NANs */ }
else {
path.lineTo(xto, yto)
return
}
Prx = rx * rx
Pry = ry * ry
}
//
// Step 2 : Compute (cx1, cy1)
//
var sign = if (localLargeArcFlag == localSweepFlag) -1.0 else 1.0
var sq = (Prx * Pry - Prx * Py1 - Pry * Px1) / (Prx * Py1 + Pry * Px1)
sq = if (sq < 0.0) 0.0 else sq
val coef = sign * Math.sqrt(sq)
val cx1 = coef * (rx * y1 / ry)
val cy1 = coef * -(ry * x1 / rx)
//
// Step 3 : Compute (cx, cy) from (cx1, cy1)
//
val sx2 = (x0 + xto) / 2.0
val sy2 = (y0 + yto) / 2.0
val cx = sx2 + (cosAngle * cx1 - sinAngle * cy1)
val cy = sy2 + (sinAngle * cx1 + cosAngle * cy1)
//
// Step 4 : Compute the angleStart (angle1) and the angleExtent (dangle)
//
val ux = (x1 - cx1) / rx
val uy = (y1 - cy1) / ry
val vx = (-x1 - cx1) / rx
val vy = (-y1 - cy1) / ry
// Compute the angle start
var n = sqrt(ux * ux + uy * uy)
var p = ux // (1 * ux) + (0 * uy)
sign = if (uy < 0.0) -1.0 else 1.0
var angleStart = (sign * Math.acos(p / n)).toDegrees()
// Compute the angle extent
n = Math.sqrt((ux * ux + uy * uy) * (vx * vx + vy * vy))
p = ux * vx + uy * vy
sign = if (ux * vy - uy * vx < 0.0) -1.0 else 1.0
var angleExtent = Math.toDegrees(sign * Math.acos(p / n))
if(!localSweepFlag && angleExtent > 0) angleExtent -= 360.0
else if(localSweepFlag && angleExtent < 0) angleExtent += 360.0
angleExtent %= 360
angleStart %= 360
//
// We can now build the resulting Arc2D
//
val arcX = cx - rx
val arcY = cy - ry
val arcW = rx * 2.0
val arcH = ry * 2.0
val arcStart = -angleStart
val arcExtent = -angleExtent
val arc = Arc2D.Double(OPEN).apply { setArc(arcX, arcY, arcW, arcH, arcStart, arcExtent, OPEN) }
val xform: AffineTransform? = when(xAxisRotationR) {
0.0 -> null
else -> AffineTransform().apply { setToRotation(xAxisRotationR, cx, cy) }
}
val pi = arc.getPathIterator(xform)
// RT-8926, append(true) converts the initial moveTo into a
// lineTo which can generate huge miter joins if the segment
// is small enough. So, we manually skip it here instead.
pi.next()
path.append(pi, true)
}
private fun append(cubicCurveTo: CubicCurveTo, path: Path2D) {
if(cubicCurveTo.isAbsolute) {
path.curveTo(cubicCurveTo.controlX1, cubicCurveTo.controlY1,
cubicCurveTo.controlX2, cubicCurveTo.controlY2,
cubicCurveTo.x, cubicCurveTo.y)
}
else {
val dx = path.currentPoint.x
val dy = path.currentPoint.y
path.curveTo(cubicCurveTo.controlX1 + dx, cubicCurveTo.controlY1 + dy,
cubicCurveTo.controlX2 + dx, cubicCurveTo.controlY2 + dy,
cubicCurveTo.x + dx, cubicCurveTo.y + dy)
}
}
private fun append(hLineTo: HLineTo, path: Path2D) {
if(hLineTo.isAbsolute) path.lineTo(hLineTo.x, path.currentPoint.y)
else path.lineTo(path.currentPoint.x + hLineTo.x, path.currentPoint.y)
}
private fun append(lineTo: LineTo, path: Path2D) {
if(lineTo.isAbsolute) path.lineTo(lineTo.x, lineTo.y)
else path.lineTo(path.currentPoint.x + lineTo.x, path.currentPoint.y + lineTo.y)
}
private fun append(moveTo: MoveTo, path: Path2D) {
if(moveTo.isAbsolute) path.moveTo(moveTo.x, moveTo.y)
else path.moveTo((path.currentPoint.x + moveTo.x), path.currentPoint.y + moveTo.y)
}
private fun append(quadCurveTo: QuadCurveTo, path: Path2D) {
if(quadCurveTo.isAbsolute) {
path.quadTo(quadCurveTo.controlX, quadCurveTo.controlY,
quadCurveTo.x, quadCurveTo.y)
}
else {
val dx = path.currentPoint.x
val dy = path.currentPoint.y
path.quadTo(quadCurveTo.controlX + dx, quadCurveTo.controlY + dy,
quadCurveTo.x + dx, quadCurveTo.y + dy)
}
}
private fun append(vLineTo: VLineTo, path: Path2D) {
if(vLineTo.isAbsolute) path.lineTo(path.currentPoint.x, vLineTo.y)
else path.lineTo(path.currentPoint.x, path.currentPoint.y + vLineTo.y)
}

Function Plotter error in Dart (with three.dart): Breaking on exception: The null object does not have a method 'crossInto'

The calculations are done in the following code:
var MIN = -10.0,
MAX = 10.0,
RANGE = MAX - MIN;
getColor(max, min, val) {
var MIN_L = 40,
MAX_L = 100;
var color = new Color();
var h = 0 / 240;
var s = 80 / 240;
var l = (((MAX_L - MIN_L) / (max - min)) * val) / 240;
color.setHSL(h, s, l);
return color;
}
initGraph() {
var x = MIN,
y = MIN,
z = 0.0;
initData() {
var data = [];
for (var i = MIN; i < MAX; i++) {
var row = [];
for (var j = MIN; j < MAX; j++) {
double z = 2*( x * x + y * y);
print('$z');
row.add({
x: x,
y: y,
z: z
});
y++;
}
data.add(row);
x++;
}
return data;
}
var data = initData();
var geometry = new Geometry();
var colors = [];
var RANGE = data.length,
height = data[0].length;
data.forEach((col) {
col.forEach((val) {
geometry.vertices.add(new Vector3(x.toDouble(), y.toDouble(), z.toDouble()));
colors.add(getColor(2.5, 0, z.toDouble()));
});
});
offset(x, y) {
return x * RANGE + y;
}
for (var x = 0; x < RANGE - 1; x++) {
for (var y = 0; y < height - 1; y++) {
Vector3 vec0;
Vector3 vec1;
Vector3 n_vec;
// one of two triangle polygons in one rectangle
vec0 = (geometry.vertices[offset(x, y)] - geometry.vertices[offset(x + 1, y)]);
vec1 = (geometry.vertices[offset(x, y)] - geometry.vertices[offset(x, y + 1)]);
n_vec.crossInto(vec0, vec1).normalize();
geometry.faces.add(new Face3(offset(x, y), offset(x + 1, y), offset(x, y + 1), n_vec, [colors[offset(x, y)], colors[offset(x + 1, y)], colors[offset(x, y + 1)]]));
geometry.faces.add(new Face3(offset(x, y), offset(x, y + 1), offset(x + 1, y), n_vec.negate(), [colors[offset(x, y)], colors[offset(x, y + 1)], colors[offset(x + 1, y)]]));
// the other one
vec0 = (geometry.vertices[offset(x + 1, y)] - geometry.vertices[offset(x + 1, y + 1)]);
vec1 = (geometry.vertices[offset(x, y + 1)] - geometry.vertices[offset(x + 1, y + 1)]);
n_vec.crossInto(vec0, vec1).normalize();
geometry.faces.add(new Face3(offset(x + 1, y), offset(x + 1, y + 1), offset(x, y + 1), n_vec, [colors[offset(x + 1, y)], colors[offset(x + 1, y + 1)], colors[offset(x, y + 1)]]));
geometry.faces.add(new Face3(offset(x + 1, y), offset(x, y + 1), offset(x + 1, y + 1), n_vec.negate(), [colors[offset(x + 1, y)], colors[offset(x, y + 1)], colors[offset(x + 1, y + 1)]]));
}
}
var material = new MeshLambertMaterial(vertexColors: VertexColors);
var mesh = new Mesh(geometry, material);
scene.add(mesh);
}
The error seems to be on the occurrence of this line:
n_vec.crossInto(vec0, vec1).normalize();
What is the null object here and how do I solve this? Could the variable 'z' be causing the issue? It first showed null, and caused a similar error (that '*' cannot be applied) and I declared it as double and that got solved. I also have a suspicion in the below lines:
data.forEach((col) {
col.forEach((val) {
geometry.vertices.add(new Vector3(x.toDouble(), y.toDouble(), z.toDouble()));
n_vec is never initialized with an instance of Vector3. crossInto requires to be called on an instance, Either you create an instance first:
Vector3 n_vec = new Vector3.zero();
...
n_vec.crossInto(vec0, vec1).normalize();
Or you use the cross method, but it creates a new instance of Vector3 (you might want to avoid new instances, than I would move the variables out of the loop):
n_vec = vec0.cross(vec1).normalize();

sorting two dimensional array asp classic

So I have a 2d array that I want to Sort. I can sort it easily when one dimensional.
I Hope you can help me guys.
This is my Data.
top5(0,0) = Greeting
top5(0,1) = 2
top5(1,0) = VerifyingInformation
top5(1,1) = 5
top5(2,0) = Calibration
top5(2,1) = 4
I can sort It no problem when one dimensional.
I'm using this code for one dimensional.
For i = LBound(top5) to UBound(top5)
For j = LBound(top5) to UBound(top5) - 1
If top5(j,1) < top5(j + 1,1) Then
TempValue = top5(j + 1,1)
top5(j + 1,1) = top5(j,1)
top5(j,1) = TempValue
End If
next
Next
The result I want to have is this.
VerifyingInformation 5
Calibration 4
Greeting 2
THIS WORKS FOR ME
function sort_arr_mult(byref ArrTmp, ordPlace)
' ordPlace - the place of the order value in the array
' create the new array
Redim arrRet (Ubound(ArrTmp, 1), Ubound(ArrTmp, 2))
for j = 0 to Ubound(ArrTmp, 2)
orderVal = ArrTmp(ordPlace, j)
if j = 0 then ' first enter insert to first column
for i = 0 to Ubound(ArrTmp, 1)
arrRet(i, j) = ArrTmp(i, j)
next
else
' check the first value if smaller or equal
' move the columnbs one field up
' at the end insert to currenct column
for k = 0 to Ubound(arrRet, 2)
if isEmp(arrRet(0, k)) then ' if empty fied the column
for i = 0 to Ubound(arrRet, 1)
arrRet(i, k) = ArrTmp(i, j)
next
exit for
else
if orderVal<=arrRet(ordPlace, k) then
for x = Ubound(arrRet, 2) to k+1 step -1
for i = 0 to Ubound(arrRet, 1)
arrRet(i, x) = arrRet(i, x-1)
next
next
for i = 0 to Ubound(arrRet, 1)
arrRet(i, k) = ArrTmp(i, j)
next
exit for
end if
end if
next ' for k = 0 to Ubound(arrRet, 2)
end if
next
sort_arr_mult = arrRet
end function
It looks like you are actually performing a one-dimensional sort of the numeric value with an associated text string just along for the ride.
Your example code is close but you will need 2 temp values to represent the array values you will be shifting around.
For i = LBound(top5) to UBound(top5)
For j = LBound(top5) to UBound(top5) - 1
If top5(j,1) < top5(j + 1,1) Then
TempValue = top5(j + 1,1)
TempText = top5(j + 1,0)
top5(j + 1,1) = top5(j,1)
top5(j + 1,0) = top5(j,0)
top5(j,1) = TempValue
top5(j,0) = TempText
End If
Next
Next
Extending raam's answer with 3rd parameter as sorting direction "ASC" or "DESC"
Function sortArrayMulti(byref ArrTmp, ordPlace, so)
''so: sortorder "ASC" or "DESC"
Dim j, i, k, orderVal, x
Redim arrRet(Ubound(ArrTmp, 1), Ubound(ArrTmp, 2))
for j = 0 To Ubound(ArrTmp, 2)
orderVal = ArrTmp(ordPlace, j)
if j = 0 Then
for i = 0 to Ubound(ArrTmp, 1)
arrRet(i, j) = ArrTmp(i, j)
next
else
for k = 0 to Ubound(arrRet, 2)
if isEmpty(arrRet(0, k)) then
for i = 0 to Ubound(arrRet, 1)
arrRet(i, k) = ArrTmp(i, j)
next
exit for
else
if so = "ASC" then
if orderVal <= arrRet(ordPlace, k) then
for x = Ubound(arrRet, 2) to k + 1 step -1
for i = 0 to Ubound(arrRet, 1)
arrRet(i, x) = arrRet(i, x - 1)
next
next
for i = 0 to Ubound(arrRet, 1)
arrRet(i, k) = ArrTmp(i, j)
next
exit for
end if
else
if orderVal >= arrRet(ordPlace, k) then
for x = Ubound(arrRet, 2) to k + 1 step -1
for i = Ubound(arrRet, 1) to 0 step -1
arrRet(i, x) = arrRet(i, x - 1)
next
next
for i = 0 to Ubound(arrRet, 1)
arrRet(i, k) = ArrTmp(i, j)
next
exit for
end if
end if
end if
next
end if
next
sortArrayMulti = arrRet
End Function

Resources