How to shade outside a circle in JSXgraph - javascript

I'm currently trying to shade inside and outside a circle in JSXgraph, similar to an inequality.
My current code to create a circle:
var A = board.create('point', [h, k], { name: '', size: 0, fixed: true}),
B = board.create('point', [h, k+r], { name: '', size: 0, fixed: true}),
graph = board.create('circle', [A, B], { id: field, size: 0, fixed: true });
graph.on('down', function (e, i) {
showMaster(this.id);
});
graphMap.set(field, graph);
inequality(">", field, graph, color);
I have found that you can shade inside using these object proprieties:
{strokeWidth: 2, dash: 2, fillColor: 'red', fillOpacity: 0.3}
However, nothing in shading outside.
Any suggestions ?

Related

Cesium polygon callback using javascript

I am trying to edit the change the edit or redraw the polygon. this is my code.
Error
An error occurred while rendering. Rendering has stopped.
TypeError: this._callback is not a function
TypeError: this._callback is not a function
using pickedObject.id i got the exect polygon i want to reposition, but call back issue.
var points = [-95.8079865631313, 30.24038650541154, -
60.10509002138564, 23.526593580490083, -59.06372427570612, 2.245934026097194, -
117.00668212362282, 3.938434130034481
];
function loadPoly(points) {
redPolygon = viewer.entities.add({
id: "myArray",
name: "myArray",
polygon: {
hierarchy: Cesium.Cartesian3.fromDegreesArray(points),
material: Cesium.Color.fromBytes(221, 240, 235, 160)
}
});
polygonCollection.push(redPolygon);
adding_billboard(-95.8079865631313, 30.24038650541154, "A", "-95.8079865631313, 30.24038650541154");
adding_billboard(-60.10509002138564, 23.526593580490083, "A", "-60.10509002138564, 23.526593580490083");
adding_billboard(-59.06372427570612, 2.245934026097194, "A", "-59.06372427570612, 2.245934026097194");
adding_billboard(-117.00668212362282, 3.938434130034481, "A", "-117.00668212362282, 3.938434130034481");
viewer.flyTo(redPolygon);
}
function adding_billboard(lon, lat, name, popup) {
var entity = viewer.entities.add({
name: name,
position: Cesium.Cartesian3.fromDegrees(lon, lat, 2000),
billboard: {
image: 'https://cdn0.iconfinder.com/data/icons/small-n-flat/24/678111-map-marker-512.png',
show: true, // default
pixelOffset: new Cesium.Cartesian2(0, -20), // default: (0, 0)
eyeOffset: new Cesium.Cartesian3(0.0, 0.0, 0.0), // default
horizontalOrigin: Cesium.HorizontalOrigin.bottom, // default
alignedAxis: Cesium.Cartesian3.ZERO, // default
width: 20, // default: undefined
height: 25, // default: undefined
//disableDepthTestDistance: Number.POSITIVE_INFINITY, // draws the label in front of terrain
// on ground show
},
label: {
text: popup,
font: "7pt sans-serif",
heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
horizontalOrigin: Cesium.HorizontalOrigin.LEFT,
verticalOrigin: Cesium.VerticalOrigin.BASELINE,
fillColor: Cesium.Color.BLACK,
showBackground: true,
backgroundColor: new Cesium.Color(1, 1, 1, 0.7),
backgroundPadding: new Cesium.Cartesian2(8, 4),
disableDepthTestDistance: Number
.POSITIVE_INFINITY, // draws the label in front of terrain
},
});
pointsCollection.push(entity);
}
var coordinates = [76.82071632075994, 33.4134542888633, 77.83750798568438, 33.39276536442791, 77.32892923803021,
32.93547457354476
];
var handler = new Cesium.ScreenSpaceEventHandler(scene.canvas);
handler.setInputAction(function(click) {
var pickedObject = scene.pick(click.position);
if (Cesium.defined(pickedObject)) {
console.log("Second ");
console.log("pickedObject.id.id ", pickedObject.id.id);
console.log("pickedObject.id.name ", pickedObject.id.name);
console.log("pickedObject.id..polygon.hierarchy ", pickedObject.id.polygon.hierarchy.valueOf());
var data = pickedObject.id.polygon.hierarchy.valueOf();
console.log("data ", data.positions.valueOf());
pickedObject.id.polygon = {
hierarchy: new Cesium.CallbackProperty(new Cesium.Cartesian3.fromDegreesArray(coordinates),
false),
material: Cesium.Color.fromBytes(221, 240, 235, 160)
//pickedObject.id = redPolygon;// tried this but dailed due to same id then i removed it.
if (pickedObject.id.name == 'C') {
// $('#modal-activity').modal('show');
}
}
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
i want to shift polygon to some other coordiante but unable to use call back properly can some one guild me how can I do ?
i did some google searches which are given below but my issues not solved.
here i was trying to make polygon points dynamic but line disappers in tarrains. fist time it was ok after moving point it disappers.
https://sandcastle.cesium.com/?#c=zVTRbpswFP2VK14gEjMhWTaJ0Whd0odpnVpl0vZQ+uDCTWvN2Mg2yVjVf5/BkKRZ1VV9mnjhHp9zfH2uYUMVbBhuUcEJCNzCAjWrS/K9wwI/78qFFIYygcoffchE+2ysDoVhpomt0DmQDmCoCS2K4D4TAKxIwP+8jP2wrQQtESywwgLOOGeVRpACdK3WNEfHqaS2HlIkMLSyoMrYNyqmZK1kucRbhaiDN3E8I+MQpu/JeNRLmTAJdBvbiv1C/o39xgSm49BhueRSJTvjtiKrs2W/KmvD7SEXT5A+nZ8uvjym/WCFuUsgJrMWfsjEg8tmn8zkBclMXpPMP4N52wXz7v8Lpl1/LpVK8qbl7JvtD62Tw9t52aOXSlaoTHOqFG2CKyeBQ+YK16hQ5DhQg6O9w/5+whX4w2Y+XMMofLXb5Am3wex677t1Oc12QEkNKkb50VFdIhcu3K89Z9fA/aB+foQvHuLxGCdujHaQo8NxeqGXatNwnLvVj6yspDJQKx4QEhksK25b1dFNnf9EQ3KtW1kaDaK0YBv7EZxk3tEvJvMg51Rru7KueXdRM2+eRpb/SMYlLZi4vdig4rRpKXfx/NyBhJA0suXfKiMlv6HqwPEP
second :Dynamically change polygon position in cesium
it also gives error because i don't know where to use callback.
please guild me. thank you.
Here's Sandcastle link.
const {
Cartesian3,
CallbackProperty,
Color,
defined,
ScreenSpaceEventHandler,
ScreenSpaceEventType,
Viewer
} = window.Cesium;
const viewer = new Viewer("cesiumContainer");
let redPolygon;
const polygonCollection = [];
const pointsCollection = [];
const polygonId = "myArray";
let polygonPoints = [
-95.8079865631313, 30.24038650541154, -60.10509002138564, 23.526593580490083, -59.06372427570612,
2.245934026097194, -117.00668212362282, 3.938434130034481
];
function loadPoly() {
redPolygon = viewer.entities.add({
id: polygonId,
name: "myArray",
polygon: {
hierarchy: new CallbackProperty(() => {
return {
positions: Cartesian3.fromDegreesArray(polygonPoints)
};
}, false),
material: Color.fromBytes(221, 240, 235, 160)
}
});
polygonCollection.push(redPolygon);
adding_billboard(-95.8079865631313, 30.24038650541154, "A", "-95.8079865631313, 30.24038650541154");
adding_billboard(-60.10509002138564, 23.526593580490083, "A", "-60.10509002138564, 23.526593580490083");
adding_billboard(-59.06372427570612, 2.245934026097194, "A", "-59.06372427570612, 2.245934026097194");
adding_billboard(-117.00668212362282, 3.938434130034481, "A", "-117.00668212362282, 3.938434130034481");
viewer.flyTo(redPolygon);
}
function adding_billboard(lon, lat, name, popup) {
const entity = viewer.entities.add({
name: name,
position: Cartesian3.fromDegrees(lon, lat, 2000),
billboard: {
image: "https://cdn0.iconfinder.com/data/icons/small-n-flat/24/678111-map-marker-512.png",
show: true, // default
pixelOffset: new Cesium.Cartesian2(0, -20), // default: (0, 0)
eyeOffset: new Cartesian3(0.0, 0.0, 0.0), // default
horizontalOrigin: Cesium.HorizontalOrigin.bottom, // default
alignedAxis: Cesium.Cartesian3.ZERO, // default
width: 20, // default: undefined
height: 25 // default: undefined
//disableDepthTestDistance: Number.POSITIVE_INFINITY, // draws the label in front of terrain
// on ground show
},
label: {
text: popup,
font: "7pt sans-serif",
heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
horizontalOrigin: Cesium.HorizontalOrigin.LEFT,
verticalOrigin: Cesium.VerticalOrigin.BASELINE,
fillColor: Color.BLACK,
showBackground: true,
backgroundColor: new Color(1, 1, 1, 0.7),
backgroundPadding: new Cesium.Cartesian2(8, 4),
disableDepthTestDistance: Number.POSITIVE_INFINITY // draws the label in front of terrain
}
});
pointsCollection.push(entity);
}
loadPoly();
const scene = viewer.scene;
const handler = new ScreenSpaceEventHandler(scene.canvas);
handler.setInputAction(function (click) {
const pickedObject = scene.pick(click.position);
if (defined(pickedObject) && pickedObject.id && pickedObject.id.id === polygonId) {
const newPolygonPoints = [
76.82071632075994, 33.4134542888633, 77.83750798568438, 33.39276536442791, 77.32892923803021,
32.93547457354476
];
polygonPoints = newPolygonPoints;
viewer.camera.flyTo({
destination: Cartesian3.fromDegrees(76.82071632075994, 33.4134542888633, 1000)
});
}
}, ScreenSpaceEventType.LEFT_CLICK);

Echart: How to set mark area to fill sections in xAxis

I have a problem with marking area: i need to be able to select a bar area based on xAxis, for example from 0 to 1, from 1 to 2, etc. But when i try to provide options for bar like
[{xAxis: 0, itemStyle: {color: red}},{xAxis: 1}]
it marks an area from a middle of xAxis area with an index of 0 to a middle of xAxis area with an index of 1. Is there a way to make it mark from start of an area to an end. Currently i managed to do so only with x option in pixels:
https://codesandbox.io/s/react-echart-markarea-ksj31?file=/src/index.js:714-726
Is there a better way to do it?
I can't imagine a method that would cover your requirements. It seems there is no such but nothing prevents to do it ourselves, see below.
When call function with join = true markedArea will calc as range from first to last.
calcMarkAreaByBarIndex(myChart, join = true, [4, 9])
When call function with join = false markedArea will calc for each bar.
calcMarkAreaByBarIndex(myChart, join = true, [4, 5, 6, 9])
var myChart = echarts.init(document.getElementById('main'));
var option = {
tooltip: {},
xAxis: {
data: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
},
yAxis: {},
series: [
{
id: 'myBar',
name: 'Series',
type: 'bar',
data: [11, 11, 11, 11, 12, 13, 110, 123, 113, 134, 93, 109],
markArea: {
data: [
[{x: 184},{x: 216}],
[{x: 224},{x: 256}],
]
},
},
]
};
myChart.setOption(option);
function calcMarkAreaByBarIndex(chartInstance, join = false, barIdx){
var series = chartInstance.getModel().getSeriesByType('bar');
var seriesData = series.map((s, idx) => s.getData())[0];
var barNum = seriesData.count();
var barCoors = [];
var layout = idx => seriesData.getItemLayout(idx);
for(var i = 0; i < barNum; i++){
if(!barIdx.includes(i)) continue;
barCoors.push([
{ x: layout(i).x },
{ x: layout(i).x + layout(i).width },
])
}
if(join){
return [
[
{ x: barCoors[0][0].x },
{ x: barCoors[barCoors.length - 1][1].x }
]
]
} else {
return barCoors
}
}
var markedAreas = {
series: {
id: 'myBar',
markArea: {
data: calcMarkAreaByBarIndex(myChart, join = true, [4,9])
}
}
};
myChart.setOption(markedAreas);
<script src="https://cdn.jsdelivr.net/npm/echarts#4.7.0/dist/echarts.min.js"></script>
<div id="main" style="width: 600px;height:400px;"></div>
I found a solution, that worked for me:
Basically, you need to manually set yAxis's max props, add another xAxis, make it invisible, create a custom series with type 'bar' and set xAxisIndex to 1:
data: [maxYaxisValue,maxYaxisValue...], //length === xAxis.data.length
type: 'bar',
barWidth: '100%',
color: transparent,
xAxisIndex: 1,
And style a bar by index with background color and borderWidth
You can check the working example here
https://codesandbox.io/s/react-echart-markarea-m0mgq?file=/src/index.js

Chart JS plugin to change line color depending on value

I am attempting to create a line chart where the color of the line (and the points) is dependant upon the value being plotted. For example if the value is above the following thresholds [0, 115, 125] then the color would be either ['green', 'yellow', 'red'] respectively.
The requirement is nearly identical to that which is achieved in this example: https://jsfiddle.net/egamegadrive16/zjdwr4fh/
The difference is that I am using react-chart-js-2 and as a result, the draw() method is not accessible in the same way. Instead, it is suggested to create a plugin to manipulate the chart.
This is the plugin code at present:
import { Chart } from "react-chartjs-2";
class variableLineColorUtils {
selectColor(value, thresholds, colors) {
let color = colors[0];
thresholds.every((limit, index) => {
if (value < limit) return false;
else color = colors[index];
return true;
});
return color;
}
}
const variableLineColor = {
id: "variableLineColor",
afterDraw: (chart, easing) => {
const options = chart.options.variableLineColor;
if (options) {
const utils = new variableLineColorUtils();
const datasets = chart.config.data.datasets;
datasets.forEach((set, i) => {
const points = chart.getDatasetMeta(i).data;
points.forEach((point, index) => {
const color = utils.selectColor(
datasets[i].data[point._index],
options.thresholds,
options.colors
);
point.custom = { borderColor: color, backgroundColor: color };
});
chart.update();
});
}
}
};
Chart.pluginService.register(variableLineColor);
export default variableLineColor;
And these are the options used for the plugin:
variableLineColor: {
thresholds: [0, 115, 125],
colors: ["green", "yellow", "red"]
}
This approach only amends the color of the points themselves, not the line between the points. The line remains in the chart's default backgroundColor.
How can I amend the color of the line itself?
You can use the plugins array to create a new beforeRender plugin that will accomplish this.
plugins: [{
beforeRender: (x, options) => {
const c = x.chart;
const dataset = x.data.datasets[0];
const yScale = x.scales['y-axis-0'];
const yPos = yScale.getPixelForValue(0);
const gradientFill = c.ctx.createLinearGradient(0, 0, 0, c.height);
gradientFill.addColorStop(0, 'rgb(86,188,77)');
gradientFill.addColorStop(yPos / c.height, 'rgb(86,188,77)');
gradientFill.addColorStop(yPos / c.height, 'rgb(229,66,66)');
gradientFill.addColorStop(1, 'rgb(229,66,66)');
const model = x.data.datasets[0]._meta[Object.keys(dataset._meta)[0]].dataset._model;
model.borderColor = gradientFill;
},
}];
The result will look something like this:
This will also work for the background color just by changing the model.borderColor line to model.backgroundColor. For example:
For that, you will have to manipulate your data something as I did check out the below code. I doubt if you can do it with the plugin.
import React from 'react';
import { Line } from 'react-chartjs-2';
const data = {
labels: [1, 2, 3, 4, 5, 6, 7, 8, 9],
datasets: [
{
label: 'First one',
fill: false,
borderColor: 'gray',
data: [null, null, 2, 0, 3],
},
{
label: 'Second one',
fill: false,
borderColor: 'blue',
data: [2, 4, 2, null, null, null, null, null, null],
},
{
label: 'Third one',
fill: false,
borderColor: 'cyan',
data: [null, null, null, null, 3, 4, 1, null, null],
},
],
}
function App() {
return (
<div>
<Line
data={data}
/>
</div>
);
}
export default App
Try to use borderColor instead of backgroundColor and Please refer ChartJs StackOverflow. It may solve your problem.
Use borderColor or color instead of backgroundColor of line.

How can you transform text to latex using mathJax included in JSXgraph?

I'm trying to render an equation using mathJax that comes with the JSXgraph 0.99.7.
Simple forms seem to render (r^2=(x-h)^2+(y-k)^2), but not functions or fractions (1=\frac{(x-h)^2}{a^2}+\frac{(y-k)^2}{b^2}).
Here is an image
Current code to draw an ellipse:
var graph = board.create('ellipse', [A, B, C], {
id: field,
fixed: true,
useMathJax: true,
withLabel: true,
name: '',
strokeColor: color,
strokeWidth: 2,
fillColor: shade,
fillOpacity: 0.3,
size: 2,
dash: dashed,
highlightStrokeColor: 'red',
highlightStrokeWidth: 3,
highlightFillColor: shade,
highlightFillOpacity: op
});
graph.on('down', function (e, i) {
showMaster(this.id);
graph.setName('1=\\frac{(x-h)^2}{a^2}+\\frac{(y-k)^2}{b^2}');
});
Any suggestions ?
By default, labels are not parsed for MathJax content. The necessary change is to add
label: {useMathJax: true, visible: false}
to the ellipse declaration.
Additionally, I would like to suggest to set the name when creating the ellipse and just set the label to visible on the down event.
Here is the full example:
MathJax.Hub.Config({
extensions: ["tex2jax.js","TeX/AMSmath.js","TeX/AMSsymbols.js"],
jax: ["input/TeX", "output/HTML-CSS"],
tex2jax: {
inlineMath: [ ['$','$'], ["\\(","\\)"] ],
displayMath: [ ['$$','$$'], ["\\[","\\]"] ],
},
"HTML-CSS": { availableFonts: ["TeX"] }
});
var A = board.create('point', [-2, 0]);
var B = board.create('point', [1, 0]);
var C = board.create('point', [0, 2]);
var graph = board.create('ellipse', [A, B, C], {
withLabel: true,
strokeColor: 'black',
strokeWidth: 2,
fillColor: '#cccccc',
fillOpacity: 0.3,
highlightStrokeColor: 'red',
highlightStrokeWidth: 3,
name: '$1=\\frac{(x-h)^2}{a^2}+\\frac{(y-k)^2}{b^2}$',
label: {useMathJax: true, visible: false}
});
graph.on('down', function (e, i) {
graph.label.setAttribute({visible: true});
});
See it live at http://jsfiddle.net/r3fxcp54/1/

JSXGraph: Applying a line transformation with applyOnce()

I'm trying to apply a one-time transformation to a Line in JSXGraph.
Based on the documentation, I'm trying to transform a Line like this:
var f = function(x) {
return x;
};
var l1 = board.create('functiongraph', [f], {
name: 'line 1',
withLabel: true,
strokeWidth: 2,
strokeColor: 'orange',
fixed: false
});
// Rotate about an intersection point with another line
var i = board.create('intersection', [l1, l2, 0], {
name: 'intersection',
fixed: true,
showInfobox: false
});
var rot = board.create(
'transform', [
function() {
// This gets the value from a slider
return s.Value();
}, i
], {
type:'rotate'
});
rot.applyOnce(l1);
board.update();
The full source is here: http://maldive.ccnmtl.columbia.edu/js/ncustom.js and you can see the error I'm describing here: http://maldive.ccnmtl.columbia.edu/js/functiongraph-rotation.html
I get the error: t[n].coords is undefined. In the full application that I'm trying this in, I get the error: TypeError: Cannot read property 'usrCoords' of undefined
So, anyways, has anyone else tried to transform a line like this?
Update: After looking at the source, it's obvious this method only works with points. So, I don't know if this will be possible with my functiongraph. I am just using a straight line here though, so it's possible I can do something with points.
Yes, applyOnce is implemented only for points, texts and images, yet. The alternative is to bind the transformation to the curve. Here is the full example (relevant is only the very last line):
var board = JXG.JSXGraph.initBoard('jxgbox', {
boundingbox: [-10, 10, 10, -10],
axis:true
});
var f = function(x) {
return x;
};
var l1 = board.create('functiongraph', [f], {
name: 'line 1', withLabel: true, fixed: false
});
var f2 = function(x) {
var alpha = 0.3;
return (1 - alpha) *
(1.4 *
1.6 ** alpha) *
(x ** -alpha);
};
var l2 = board.create('functiongraph', [f2], {
name: 'line 2', withLabel: true, fixed: false
});
// Rotate about an intersection point with another line
var intrsct = board.create('intersection', [l1, l2, 0], {
name: 'intersection', fixed: true,
});
var s = board.create(
'slider', [
[-1, -1],
[2, -1],
[0, 0, 2]
], { name:'angle'});
var rot = board.create(
'transform', [
function() {
// This gets the value from a slider
return s.Value();
}, intrsct
], { type:'rotate' });
rot.bindTo(l1);
Alternatively, in the upcoming version 0.99.7 (already available in the nightly builds), you can create a new curve which is the transformed curve of an original curve:
var l1a = board.create('curve', [l1, rot], {
name: 'line 1a',
withLabel: true,
strokeWidth: 2,
strokeColor: 'orange',
fixed: false
});

Categories

Resources