Highcharts arc with arrow - highcharts

I am trying to come up with solution which will help me drawing arrow on the end of arc (drawn by chart.renderer.arc function). I have seen solution like this How to draw arrows on a line-chart with Highcharts? when you have series but in arc I do not have information about points (except last one).
Now I am trying to draw arrow depending on angle but that looks a bit miserable.
What I am trying to achieve:
arc with arrow
Code sample: https://jsfiddle.net/49hL72pw/1/
chart: {
polar: true,
events: {
load: function() {
var chart = this;
var center = [(chart.plotBox.width) / 2, (chart.plotBox.height) / 2];
var ren = chart.renderer;
var angle = 175;
var result = ren.arc(center[0] + chart.plotBox.x, center[1] + chart.plotBox.y, 50, 50, (Math.PI / 180) * (-90), (Math.PI / 180) * angle).attr({
fill: '#FCFFC5',
stroke: 'black',
'stroke-width': 1,
dashStyle: 'dash'
}).add();
var dValues = result.element.attributes.d.value.split(" ");
var kx = +dValues[9];//203.99829144870202;
var ky = +dValues[10];//280.94598600742796;
var leftArrowX = 7;
var leftArrowY = 5;
var rightArrowX = 5;
var rightArrowY = 10;
if(angle <= 270 && angle >= 250) {
leftArrowX = leftArrowX * -1;
leftArrowY = leftArrowY * -1;
rightArrowX = rightArrowX * -1;
//rightArrowY = rightArrowY * -1;
} else if(angle <= 249 && angle >= 230) {
leftArrowX = (leftArrowX * -1) - 3;
leftArrowY = (leftArrowY * -1) + 5;
rightArrowX = (rightArrowX * -1) + 3;
//rightArrowY = rightArrowY * -1;
} else if(angle <= 229 && angle >= 210) {
leftArrowX = (leftArrowX * -1) - 3;
leftArrowY = (leftArrowY * -1) + 5;
rightArrowX = (rightArrowX * -1) + 7;
//rightArrowY = rightArrowY * -1;
} else if(angle <= 209 && angle >= 200) {
leftArrowX = (leftArrowX * -1) - 3;
leftArrowY = (leftArrowY * -1) + 8;
rightArrowX = (rightArrowX * -1) + 7;
//rightArrowY = rightArrowY * -1;
} else if(angle <= 199 && angle >= 190) {
leftArrowX = (leftArrowX * -1) - 2;
leftArrowY = (leftArrowY * -1) + 10;
rightArrowX = (rightArrowX * -1) + 10;
//rightArrowY = rightArrowY * -1;
} else if(angle <= 189 && angle >= 180) {
leftArrowX = (leftArrowX * -1) - 1;
leftArrowY = (leftArrowY * -1) + 14;
rightArrowX = (rightArrowX * -1) + 12;
//rightArrowY = rightArrowY * -1;
} else if(angle <= 179 && angle >= 170) {
leftArrowX = (leftArrowX * -1) + 1;
leftArrowY = (leftArrowY * -1) + 14;
rightArrowX = (rightArrowX * -1) + 12;
rightArrowY = (rightArrowY) + -2;
} else if(angle <= 89 && angle > 20) {
//leftArrowX = leftArrowX * -1;
//leftArrowY = leftArrowY * -1;
//rightArrowX = rightArrowX * -1;
rightArrowY = rightArrowY * -1;
} else if (angle <= 20 && angle >= -90) {
leftArrowX = leftArrowX * -1;
leftArrowY = leftArrowY * -1;
//rightArrowX = rightArrowX * -1;
rightArrowY = rightArrowY * -1;
}
ren.path([
'M', kx, ky,
'L', kx + leftArrowX, ky + leftArrowY,
'M', kx, ky,
'L', kx + rightArrowX, ky + rightArrowY,
'Z'
])
.attr({
'stroke-width': 1,
stroke: 'black'
})
.add();
}
}
}

Thanks Paweł but I managed to solve it myself (drawing basic arrow and then rotating it):
ren.path([
'M', kx, ky,
'L', kx - 6, ky - 6,
'M', kx, ky,
'L', kx - 6, ky + 6,
'Z'
]).attr({
transform: 'rotate(' + angle + ')',
'stroke-width': 1,
stroke: '#2ecafa'
}).css({
'transform-origin': kx + 'px' + ' ' + ky + 'px'
}).add();

Related

Is the Sharpness filter available in Konvajs, if it is there how to use that?

https://konvajs.org/api/Konva.Filters.html
in this link the sharpness filter is not available
Konva doesn't have such a filter in its core. You have to implement it manually.
For that use case, you can write your own custom filter. See custom filters docs.
I tried to use that sharpen implementation: https://gist.github.com/mikecao/65d9fc92dc7197cb8a7c
// noprotect
const stage = new Konva.Stage({
container: 'container',
width: window.innerWidth,
height: window.innerHeight
});
const layer = new Konva.Layer();
stage.add(layer);
function Sharpen(srcData) {
const mix = 1;
const w = srcData.width;
const h = srcData.height;
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
var x, sx, sy, r, g, b, a, dstOff, srcOff, wt, cx, cy, scy, scx,
weights = [0, -1, 0, -1, 5, -1, 0, -1, 0],
katet = Math.round(Math.sqrt(weights.length)),
half = (katet * 0.5) | 0,
dstData = ctx.createImageData(w, h),
dstBuff = dstData.data,
srcBuff = srcData.data,
y = h;
while (y--) {
x = w;
while (x--) {
sy = y;
sx = x;
dstOff = (y * w + x) * 4;
r = 0;
g = 0;
b = 0;
a = 0;
for (cy = 0; cy < katet; cy++) {
for (cx = 0; cx < katet; cx++) {
scy = sy + cy - half;
scx = sx + cx - half;
if (scy >= 0 && scy < h && scx >= 0 && scx < w) {
srcOff = (scy * w + scx) * 4;
wt = weights[cy * katet + cx];
r += srcBuff[srcOff] * wt;
g += srcBuff[srcOff + 1] * wt;
b += srcBuff[srcOff + 2] * wt;
a += srcBuff[srcOff + 3] * wt;
}
}
}
dstBuff[dstOff] = r * mix + srcBuff[dstOff] * (1 - mix);
dstBuff[dstOff + 1] = g * mix + srcBuff[dstOff + 1] * (1 - mix);
dstBuff[dstOff + 2] = b * mix + srcBuff[dstOff + 2] * (1 - mix);
dstBuff[dstOff + 3] = srcBuff[dstOff + 3];
}
}
for(var i = 0; i < dstData.data.length; i++) {
srcData.data[i] = dstData.data[i];
}
}
Konva.Image.fromURL('https://i.imgur.com/ktWThtZ.png', img => {
img.setAttrs({filters: [Sharpen]});
img.cache();
layer.add(img);
layer.draw();
});
Demo: https://jsbin.com/tejalusano/1/edit?html,js,output

MQL4 increase the width of the COG

Here is the code:
#property indicator_chart_window
#property indicator_buffers 5
#property indicator_color1 RoyalBlue
#property indicator_color2 LimeGreen
#property indicator_color3 LimeGreen
#property indicator_color4 Goldenrod
#property indicator_color5 Goldenrod
//-----------------------------------
extern int bars_back = 100;
extern int m = 2;
extern int i = 0;
extern double kstd = 2.0;
extern int sName = 1102;
//----------------------
double fx[], sqh[], sql[], stdh[], stdl[];
double ai[10,10], b[10], x[10], sx[20];
double sum;
int ip, p, n, f;
double qq, mm, tt;
int ii, jj, kk, ll, nn;
double sq, std;
//*******************************************
int init()
{
IndicatorShortName("Center of Gravity");
SetIndexStyle(0, DRAW_LINE, 2 );
SetIndexBuffer(0, fx);
SetIndexBuffer(1, sqh);
SetIndexBuffer(2, sql);
SetIndexBuffer(3, stdh);
SetIndexBuffer(4, stdl);
p = MathRound(bars_back);
nn = m + 1;
ObjectCreate("pr" + sName, 22, 0, Time[p], fx[p]);
ObjectSet("pr" + sName, 14, 159);
return(0);
}
//----------------------------------------------------------
int deinit()
{
ObjectDelete("pr" + sName);
}
//**********************************************************************************************
int start()
{
int mi;
//-------------------------------------------------------------------------------------------
ip = iBarShift(Symbol(), Period(), ObjectGet("pr" + sName, OBJPROP_TIME1));
p = bars_back;
sx[1] = p + 1;
SetIndexDrawBegin(0, Bars - p - 1);
SetIndexDrawBegin(1, Bars - p - 1);
SetIndexDrawBegin(2, Bars - p - 1);
SetIndexDrawBegin(3, Bars - p - 1);
SetIndexDrawBegin(4, Bars - p - 1);
//----------------------sx-------------------------------------------------------------------
for(mi = 1; mi <= nn * 2 - 2; mi++)
{
sum = 0;
for(n = i; n <= i + p; n++)
{
sum += MathPow(n, mi);
}
sx[mi + 1] = sum;
}
//----------------------syx-----------
for(mi = 1; mi <= nn; mi++)
{
sum = 0.00000;
for(n = i; n <= i + p; n++)
{
if(mi == 1)
sum += Close[n];
else
sum += Close[n] * MathPow(n, mi - 1);
}
b[mi] = sum;
}
//===============Matrix=======================================================================================================
for(jj = 1; jj <= nn; jj++)
{
for(ii = 1; ii <= nn; ii++)
{
kk = ii + jj - 1;
ai[ii, jj] = sx[kk];
}
}
//===============Gauss========================================================================================================
for(kk = 1; kk <= nn - 1; kk++)
{
ll = 0; mm = 0;
for(ii = kk; ii <= nn; ii++)
{
if(MathAbs(ai[ii, kk]) > mm)
{
mm = MathAbs(ai[ii, kk]);
ll = ii;
}
}
if(ll == 0)
return(0);
if(ll != kk)
{
for(jj = 1; jj <= nn; jj++)
{
tt = ai[kk, jj];
ai[kk, jj] = ai[ll, jj];
ai[ll, jj] = tt;
}
tt = b[kk]; b[kk] = b[ll]; b[ll] = tt;
}
for(ii = kk + 1; ii <= nn; ii++)
{
qq = ai[ii, kk] / ai[kk, kk];
for(jj = 1; jj <= nn; jj++)
{
if(jj == kk)
ai[ii, jj] = 0;
else
ai[ii, jj] = ai[ii, jj] - qq * ai[kk, jj];
}
b[ii] = b[ii] - qq * b[kk];
}
}
x[nn] = b[nn] / ai[nn, nn];
for(ii = nn - 1; ii >= 1; ii--)
{
tt = 0;
for(jj = 1; jj <= nn - ii; jj++)
{
tt = tt + ai[ii, ii + jj] * x[ii + jj];
x[ii] = (1 / ai[ii, ii]) * (b[ii] - tt);
}
}
//===========================================================================================================================
for(n = i; n <= i + p; n++)
{
sum = 0;
for(kk = 1; kk <= m; kk++)
{
sum += x[kk + 1] * MathPow(n, kk);
}
fx[n] = x[1] + sum;
}
//-----------------------------------Std-----------------------------------------------------------------------------------
sq = 0.0;
for(n = i; n <= i + p; n++)
{
sq += MathPow(Close[n] - fx[n], 2);
}
sq = MathSqrt(sq / (p + 1)) * kstd;
std = iStdDev(NULL, 0, p, MODE_SMA, 0, PRICE_CLOSE, i) * kstd;
for(n = i; n <= i + p; n++)
{
sqh[n] = fx[n] + sq;
sql[n] = fx[n] - sq;
stdh[n] = fx[n] + std;
stdl[n] = fx[n] - std;
}
//-------------------------------------------------------------------------------
ObjectMove("pr" + sName, 0, Time[p], fx[p]);
//----------------------------------------------------------------------------------------------------------------------------
return(0);
}
//==========================================================================================================================
I would like the increase the lines width to 2.
I solved with
SetIndexStyle(0, DRAW_LINE, EMPTY,2, indicator_color1);
SetIndexStyle(1, DRAW_LINE, EMPTY,2, indicator_color2);
SetIndexStyle(2, DRAW_LINE, EMPTY,2, indicator_color3);
SetIndexStyle(3, DRAW_LINE, EMPTY,2, indicator_color4);
SetIndexStyle(4, DRAW_LINE, EMPTY,2, indicator_color5);

WebGL High GPU Usage

I am drawing thousand of colored quads by using WebGL (no any framework) and on my laptop, around 80k quads moves nicely in 60fps but more than 80K quads, fps starts waving regularly. Like a few frame 30fp, one frame 60 fps. When i check it Chrome's performance tools, i noticed that GPU is taking too much time.
This is how Chrome Performance tool look like when i run 100k quads
This is my example with no moving quads. Dynamic one also has same effect but STATIC one shows my problem better since no JS overhead.
My code here:
var objects = [];
var MAX_COUNT = 10000;
var projectionMatrix;
var gl;
var positionVertexBuffer;
var colorVertexBuffer;
var indicesBuffer;
{
gl = document.getElementById("renderCanvas").getContext("webgl", {preserveDrawingBuffer: false});
gl.disable(gl.STENCIL_TEST);
gl.disable(gl.DEPTH_TEST);
document.getElementById("renderCanvas").onclick = createObjects;
createObjects();
requestAnimationFrame(updateScreen);
}
function createObjects () {
projectionMatrix = new Float32Array([
0.0033333333333333335,0,0,
0,-0.0033333333333333335,0,
0,0,1
]);
var rObject = {};
rObject.projectionMatrix = projectionMatrix;
createPrograms(rObject);
createAttributes(rObject);
createMoveObjects(rObject);
rObject.id = "id_" + objects.length ;
objects.push(rObject);
}
function createMoveObjects (outObject) {
outObject.points = [];
var k = 0;
for (var i = 0; i < MAX_COUNT; i++) {
var x = (Math.random() * 600) - 300;
var y = (Math.random() * 600) - 300;
var vx = (Math.random() * 10) - 5;
var vy = (Math.random() * 10) - 5;
var size = 30 + Math.random() * 1;
var w = 26 / 2;
var h = 37 / 2;
var p = {w:w, h:h, x:x, y:y, vx:vx, vy:vy, size:size};
outObject.points.push(p);
}
}
var shaderProgram;
function createPrograms(outObject) {
var vertexShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader, document.getElementById("vertexShader").textContent );
gl.compileShader(vertexShader);
if ( !gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS) ) {
let finfo = gl.getShaderInfoLog( vertexShader );
console.log("Vertex Shader Fail" , finfo);
}
var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShader, document.getElementById("fragmentShader").textContent);
gl.compileShader(fragmentShader);
if ( !gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS) ) {
let finfo = gl.getShaderInfoLog( fragmentShader );
console.log("Fragment Shader Fail" , finfo);
}
shaderProgram = gl.createProgram();
gl.attachShader(shaderProgram, vertexShader);
gl.attachShader(shaderProgram, fragmentShader);
gl.linkProgram(shaderProgram);
var pmlocation = gl.getUniformLocation(shaderProgram,"projectionMatrix");
gl.useProgram(shaderProgram);
gl.uniformMatrix3fv(pmlocation, false , outObject.projectionMatrix);
outObject.projectionMatrixLocation = pmlocation;
outObject.shaderProgram = shaderProgram;
}
function createAttributes(outObject) {
var vertices = new Float32Array(MAX_COUNT * 8);
var colors = new Float32Array(MAX_COUNT * 12);
var indices = new Uint16Array(6 * MAX_COUNT);
var index = 0;
for (var i = 0; i < indices.length; i+=6) {
indices[i ] = index;
indices[i + 1] = index + 1;
indices[i + 2] = index + 2;
indices[i + 3] = index + 1;
indices[i + 4] = index + 3;
indices[i + 5] = index + 2;
index += 4;
}
var r,g,b;
for (var i = 0; i < colors.length; i+=12) {
r = Math.random();
g = Math.random();
b = Math.random();
colors[i] = r;
colors[i + 1] = g;
colors[i + 2] = b;
colors[i + 3] = r;
colors[i + 4] = g;
colors[i + 5] = b;
colors[i + 6] = r;
colors[i + 7] = g;
colors[i + 8] = b;
colors[i + 9] = r;
colors[i + 10] = g;
colors[i + 11] = b;
}
var k = 0;
var w = 26 / 2;
var h = 37 / 2;
var x,y;
for (var i = 0; i < vertices.length; i++) {
x = (Math.random() * 600) - 300;
y = (Math.random() * 600) - 300;
vertices[k] = -w + x; vertices[k + 1] = h + y;
vertices[k + 2] = -w + x; vertices[k + 3] = -h + y;
vertices[k + 4] = w + x; vertices[k + 5] = h + y;
vertices[k + 6] = w + x; vertices[k + 7] = -h + y;
k +=8;
}
positionVertexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, positionVertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
positionVertexBuffer.location = gl.getAttribLocation(shaderProgram,"position");
gl.vertexAttribPointer(positionVertexBuffer.location,2 ,gl.FLOAT, false, 0,0);
gl.enableVertexAttribArray(positionVertexBuffer.location);
colorVertexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, colorVertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, colors, gl.STATIC_DRAW);
colorVertexBuffer.location = gl.getAttribLocation(shaderProgram,"color");
gl.vertexAttribPointer(colorVertexBuffer.location,3 ,gl.FLOAT, false, 0,0);
gl.enableVertexAttribArray(colorVertexBuffer.location);
indicesBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indicesBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);
outObject.positionVertexBuffer = positionVertexBuffer;
outObject.colorVertexBuffer = colorVertexBuffer;
outObject.indicesBuffer = indicesBuffer;
outObject.vertices = vertices;
outObject.indices = indices;
outObject.colors = colors;
outObject.colorVertexLocation = colorVertexBuffer.location;
outObject.positionVertexLocation = positionVertexBuffer.location;
}
function updateAllPoints() {
var points;
var p;
for (var i = 0; i < objects.length; i++) {
points = objects[i].points;
var k = 0;
for (var j = 0; j < points.length; j++) {
p = points[j];
p.x += p.vx;
p.y += p.vy;
if(p.x >= 300){
p.x = 300;
p.vx *= -1;
} else if(p.x <= -300) {
p.x = -300;
p.vx *= -1;
} else if(p.y >= 300){
p.y = 300;
p.vy *= -1;
} else if(p.y <= -300) {
p.y = -300;
p.vy *= -1;
}
var vertices = objects[i].vertices;
vertices[k] = -p.w + p.x; vertices[k + 1] = p.h + p.y;
vertices[k + 2] = -p.w + p.x; vertices[k + 3] = -p.h + p.y;
vertices[k + 4] = p.w + p.x; vertices[k + 5] = p.h + p.y;
vertices[k + 6] = p.w + p.x; vertices[k + 7] = -p.h + p.y;
k +=8;
}
}
}
function renderScene() {
// updateAllPoints();
var totalDraw = 0;
gl.clearColor(0.3,0.3,0.3,1);
gl.clear(gl.COLOR_BUFFER_BIT);
var rO;
for (var i = 0; i < objects.length; i++) {
rO = objects[i];
drawObjects(rO);
totalDraw += MAX_COUNT;
}
document.getElementById("objectCounter").innerHTML = totalDraw + " Objects"
}
function drawObjects (rO) {
gl.useProgram(rO.shaderProgram);
gl.bindBuffer(gl.ARRAY_BUFFER, rO.positionVertexBuffer);
// gl.bufferSubData(gl.ARRAY_BUFFER, 0, rO.vertices);
gl.vertexAttribPointer(rO.positionVertexLocation,2 ,gl.FLOAT, false, 0,0);
gl.bindBuffer(gl.ARRAY_BUFFER, rO.colorVertexBuffer);
gl.vertexAttribPointer(rO.colorVertexLocation,3 ,gl.FLOAT, false, 0,0);
gl.drawElements(gl.TRIANGLES,MAX_COUNT * 6 , gl.UNSIGNED_SHORT, 0);
}
function updateScreen() {
if(gl){
renderScene();
requestAnimationFrame(updateScreen);
}
}
<script id="vertexShader" type="x-shader/x-vertex">
uniform mat3 projectionMatrix;
attribute vec2 position;
attribute vec3 color;
varying vec3 colorData;
void main() {
colorData = color;
vec3 newPos = vec3(position.x, position.y, 1.0 ) * projectionMatrix;
gl_Position = vec4(newPos , 1.0);
}
</script>
<script id="fragmentShader" type="x-shader/x-fragment">
precision lowp float;
uniform sampler2D uSampler;
varying vec3 colorData;
void main() {
gl_FragColor = vec4(colorData, 1.0);
}
</script>
<canvas id="renderCanvas" width="200" height="200"></canvas>
<div id="objectCounter">10000 Objects</div>
<div>Evevy Click adds 10K Squares </div>
I also checked other examples and found PixiJS's Bunnymark test where you can run 120k bunnies in 60fps but no GPU overhead.
When comparing Bunnymark test, my GPU is taking too much time and I don't know why. I opimized it (of I think I did) but problem insists.
It turned out it is because of i left antialias default as context attributes which seems "true". Can't believe i did not notice.
This code worked for me
canvasDom.getContext("webgl", {antialias : false});
Use scene.remove(mesh) OR mesh.parent.remove(mesh)

What is slices in OpenGL?

In the code bellow , Why we need slices ? and what does it for ?
//https://github.com/danginsburg/opengles-book-samples/blob/604a02cc84f9cc4369f7efe93d2a1d7f2cab2ba7/iPhone/Common/esUtil.h#L110
int esGenSphere(int numSlices, float radius, float **vertices,
float **texCoords, uint16_t **indices, int *numVertices_out) {
int numParallels = numSlices / 2;
int numVertices = (numParallels + 1) * (numSlices + 1);
int numIndices = numParallels * numSlices * 6;
float angleStep = (2.0f * ES_PI) / ((float) numSlices);
if (vertices != NULL) {
*vertices = malloc(sizeof(float) * 3 * numVertices);
}
if (texCoords != NULL) {
*texCoords = malloc(sizeof(float) * 2 * numVertices);
}
if (indices != NULL) {
*indices = malloc(sizeof(uint16_t) * numIndices);
}
for (int i = 0; i < numParallels + 1; i++) {
for (int j = 0; j < numSlices + 1; j++) {
int vertex = (i * (numSlices + 1) + j) * 3;
if (vertices) {
(*vertices)[vertex + 0] = radius * sinf(angleStep * (float)i) * sinf(angleStep * (float)j);
(*vertices)[vertex + 1] = radius * cosf(angleStep * (float)i);
(*vertices)[vertex + 2] = radius * sinf(angleStep * (float)i) * cosf(angleStep * (float)j);
}
if (texCoords) {
int texIndex = (i * (numSlices + 1) + j) * 2;
(*texCoords)[texIndex + 0] = (float)j / (float)numSlices;
(*texCoords)[texIndex + 1] = 1.0f - ((float)i / (float)numParallels);
}
}
}
// Generate the indices
if (indices != NULL) {
uint16_t *indexBuf = (*indices);
for (int i = 0; i < numParallels ; i++) {
for (int j = 0; j < numSlices; j++) {
*indexBuf++ = i * (numSlices + 1) + j;
*indexBuf++ = (i + 1) * (numSlices + 1) + j;
*indexBuf++ = (i + 1) * (numSlices + 1) + (j + 1);
*indexBuf++ = i * (numSlices + 1) + j;
*indexBuf++ = (i + 1) * (numSlices + 1) + (j + 1);
*indexBuf++ = i * (numSlices + 1) + (j + 1);
}
}
}
if (numVertices_out) {
*numVertices_out = numVertices;
}
return numIndices;
}
That code generates a sphere mesh that looks like this:
Source: https://commons.wikimedia.org/wiki/File:Sphere_wireframe_10deg_6r.svg CC BY 3.0
As you can see in the picture, there are horizontal parallel lines, and vertical lines which all meet at the poles. The horizontal lines are typically called parallels whereas the vertical ones are called meridians. The author of that code apparently didn't know this term, so they called it "slices" instead.

Can I create Fill and Eraser tools for winrt app like paint app in windows by Win2d or sharpdx?

I tried to create Fill and Eraser Tools by GDI but this way is too slow for windows phone devices and work with large photos with this method is too hard for this divices.
I search for Alternative soulation for Image Processing and find Win2D and Sharpdx but not sure These Api can help me for create these tools.
this is Fill tool in winrtxamltoolkit
public static void FloodFill(this WriteableBitmap target, int x, int y, int outlineColor, int fillColor, byte maxdiff)
{
var width = target.PixelWidth;
var height = target.PixelHeight;
var queue = new List<Pnt>();
using (var context = target.GetBitmapContext(ReadWriteMode.ReadWrite))
{
queue.Add(new Pnt { X = x, Y = y });
while (queue.Count > 0)
{
var p = queue[queue.Count - 1];
queue.RemoveAt(queue.Count - 1);
if (p.X == -1) continue;
if (p.X == width) continue;
if (p.Y == -1) continue;
if (p.Y == height) continue;
if (context.Pixels[width * p.Y + p.X] == outlineColor) continue;
if (context.Pixels[width * p.Y + p.X] == fillColor) continue;
if (context.Pixels[width * p.Y + p.X].MaxDiff(outlineColor) > maxdiff)
{
context.Pixels[width * p.Y + p.X] = fillColor;
}
else
{
continue;
}
context.Pixels[width * p.Y + p.X] = fillColor;
queue.Add(new Pnt { X = p.X, Y = p.Y - 1 });
queue.Add(new Pnt { X = p.X + 1, Y = p.Y });
queue.Add(new Pnt { X = p.X, Y = p.Y + 1 });
queue.Add(new Pnt { X = p.X - 1, Y = p.Y });
}
target.Invalidate();
}
}
and this is Ereaser tool in WriteableBitmapEx
public static void FillEllipseCenteredTrsnceparent(this WriteableBitmap bmp, int xc, int yc, int xr, int yr, Color color)
{
using (BitmapContext context = bmp.GetBitmapContext())
{
Func<Color, int> toInt32 = c =>
{
var i = ((((c.A << 0x18) | (((c.R * c.A + 1) >> 8) << 0x10)) | (((c.G * c.A + 1) >> 8) << 8)) | ((c.B * c.A + 1) >> 8));
return i;
};
int[] pixels = context.Pixels;
int width = context.Width;
int height = context.Height;
if ((xr >= 1) && (yr >= 1))
{
int num3;
int num4;
int num5;
int num6;
int num7;
int num8;
int num9 = xr;
int num10 = 0;
int num11 = (xr * xr) << 1;
int num12 = (yr * yr) << 1;
int num13 = (yr * yr) * (1 - (xr << 1));
int num14 = xr * xr;
int num15 = 0;
int num16 = num12 * xr;
int num17 = 0;
//int sa = (color >> 0x18) & 0xff;
//int sr = (color >> 0x10) & 0xff;
//int sg = (color >> 8) & 0xff;
//int sb = color & 0xff;
//bool flag = !doAlphaBlend || (sa == 0xff);
while (num16 >= num17)
{
num5 = yc + num10;
num6 = yc - num10;
if (num5 < 0)
{
num5 = 0;
}
if (num5 >= height)
{
num5 = height - 1;
}
if (num6 < 0)
{
num6 = 0;
}
if (num6 >= height)
{
num6 = height - 1;
}
num3 = num5 * width;
num4 = num6 * width;
num8 = xc + num9;
num7 = xc - num9;
if (num8 < 0)
{
num8 = 0;
}
if (num8 >= width)
{
num8 = width - 1;
}
if (num7 < 0)
{
num7 = 0;
}
if (num7 >= width)
{
num7 = width - 1;
}
for (int i = num7; i <= num8; i++)
{
pixels[i + num3] = toInt32(color);
pixels[i + num4] = toInt32(color);
}
num10++;
num17 += num11;
num15 += num14;
num14 += num11;
if ((num13 + (num15 << 1)) > 0)
{
num9--;
num16 -= num12;
num15 += num13;
num13 += num12;
}
}
num9 = 0;
num10 = yr;
num5 = yc + num10;
num6 = yc - num10;
if (num5 < 0)
{
num5 = 0;
}
if (num5 >= height)
{
num5 = height - 1;
}
if (num6 < 0)
{
num6 = 0;
}
if (num6 >= height)
{
num6 = height - 1;
}
num3 = num5 * width;
num4 = num6 * width;
num13 = yr * yr;
num14 = (xr * xr) * (1 - (yr << 1));
num15 = 0;
num16 = 0;
num17 = num11 * yr;
while (num16 <= num17)
{
num8 = xc + num9;
num7 = xc - num9;
if (num8 < 0)
{
num8 = 0;
}
if (num8 >= width)
{
num8 = width - 1;
}
if (num7 < 0)
{
num7 = 0;
}
if (num7 >= width)
{
num7 = width - 1;
}
for (int j = num7; j <= num8; j++)
{
pixels[j + num3] = toInt32(color);
pixels[j + num4] = toInt32(color);
}
num9++;
num16 += num12;
num15 += num13;
num13 += num12;
if ((num14 + (num15 << 1)) > 0)
{
num10--;
num5 = yc + num10;
num6 = yc - num10;
if (num5 < 0)
{
num5 = 0;
}
if (num5 >= height)
{
num5 = height - 1;
}
if (num6 < 0)
{
num6 = 0;
}
if (num6 >= height)
{
num6 = height - 1;
}
num3 = num5 * width;
num4 = num6 * width;
num17 -= num11;
num15 += num14;
num14 += num11;
}
}
}
}
}
Is there a way to conver this code to win2d or Sharpdx?

Resources