How do I create larger polygons out of a smaller polygons - functional-programming

I would like to transform the following list of polygons:
[
%{height: 32, width: 32, x: 0, y: 0},
%{height: 32, width: 32, x: 32, y: 0},
%{height: 32, width: 32, x: 64, y: 0},
%{height: 32, width: 32, x: 256, y: 0},
%{height: 32, width: 32, x: 288, y: 0}
]
Into a list where the adjacent polygons are joined as follows:
[
%{height: 32, width: 96, x: 0, y: 0},
%{height: 32, width: 64, x: 256, y: 0}
]
I've tried using Enum.reduce_while as follows:
Enum.reduce_while(polys, 0, fn poly, max_x ->
if poly.x - max_x <= 32, do: {:cont, max_x + 32}, else: {:halt, max_x}
end)
That works to give me the first polygon, but how do I get the subsequent polygons and is it possible to get all of them in 1 pass?

This would be a perfect use-case for Enum.chunk_while/4:
input = [
%{height: 32, width: 32, x: 0, y: 0},
%{height: 32, width: 32, x: 32, y: 0},
%{height: 32, width: 32, x: 64, y: 0},
%{height: 32, width: 32, x: 256, y: 0},
%{height: 32, width: 32, x: 288, y: 0}
]
chunk_fun = fn
i, [] -> {:cont, i}
%{width: iw, x: ix}, %{height: ah, width: aw, x: ax, y: ay}
when ax + aw == ix ->
{:cont, %{height: ah, width: aw + iw, x: ax, y: ay}}
%{height: ih, y: iy}, %{height: ah, width: aw, x: ax, y: ay}
when ay + ah == iy ->
{:cont, %{height: ah + ih, width: aw, x: ax, y: ay}}
i, acc -> {:cont, acc, i}
end
after_fun = fn
[] -> {:cont, []}
acc -> {:cont, acc, []}
end
input
|> Enum.chunk_while([], chunk_fun, after_fun)
|> IO.inspect()
#⇒ [%{height: 32, width: 96, x: 0, y: 0},
# %{height: 32, width: 64, x: 256, y: 0}]
Please note, that the example above also handles the y-axis joins. The example is interesting due to the unusual use of a map instance as an accumulator.

I'd use Enum.reduce here. Enum.reduce_while is meant for cases when you want to stop processing the list further based on some condition. You do want to process the whole list in this case.
What I do is collect polygons in the accumulator, starting with a list with only the first polygon. Then, in each reduction, I check whether the previous polygon's x + width is the same as the new polygon's x. If it is, I merge the polygons by adding the widths, if not I prepend the polygon.
The list is collected in reverse so I use Enum.reverse after the reduction.
[
%{height: 32, width: 32, x: 0, y: 0},
%{height: 32, width: 32, x: 32, y: 0},
%{height: 32, width: 32, x: 64, y: 0},
%{height: 32, width: 32, x: 256, y: 0},
%{height: 32, width: 32, x: 288, y: 0}
]
|> Enum.reduce(nil, fn
x, nil ->
[x]
x, [h | t] ->
if h.x + h.width == x.x do
[%{h | width: x.width + h.width} | t]
else
[x, h | t]
end
end)
|> Enum.reverse()
|> IO.inspect()
Output:
[%{height: 32, width: 96, x: 0, y: 0}, %{height: 32, width: 64, x: 256, y: 0}]

Related

Qt Qml 3 different graphs connected to a single y-axis

I want to create 3 graphs one under the other. When I move the mouse on the screen, I want to see the x value in the 3 graphs corresponding to the y value at that point. The chart I want and the outputs of my own work are as in the images. Maybe I can achieve what I want by putting a rectangle on the charts I make. But is there a more useful way or example of this?
Another problem is if I am going to continue with my own method;
When I make 3 separate charts, only the lowest one has the y axis, so there are tick counts on it. It doesn't happen in the 1st and 2nd charts. This doesn't look good either. How can I make the tick counts in the 3rd chart invisible?
When I activate the plotArea command lines and make the graphics larger and closer to each other, as in the 3rd picture, the plot description is not fully readable and 2 of the 5 numbers on the x-axis become unreadable.
for example;
output of my own code
with plotAreas open
ColumnLayout{
id: qmlWindow6GridLayout
anchors.fill: parent
ChartView {
//title: "Spline1"
id: chart1
Layout.fillWidth:true
Layout.fillHeight:true
legend.visible: true
backgroundColor: "black"
antialiasing: true
//plotArea: Qt.rect(35, 35, parent.width - 75, parent.height / 3 - 75)
SplineSeries {
//name: "Altimeter"
name: "Chart 1"
color: "red"
axisX: ValuesAxis {
visible: false
}
axisY: ValuesAxis{
labelsColor: "white"
}
XYPoint { x: toMsecsSinceEpoch(new Date(0, 0, 0, 15, 29, 00)); y: 50 }
XYPoint { x: toMsecsSinceEpoch(new Date(0, 0, 0, 15, 29, 20)); y: 100 }
XYPoint { x: toMsecsSinceEpoch(new Date(0, 0, 0, 16, 29, 37)); y: 150 }
XYPoint { x: toMsecsSinceEpoch(new Date(0, 0, 0, 16, 30, 20)); y: 200 }
XYPoint { x: toMsecsSinceEpoch(new Date(0, 0, 0, 16, 45, 00)); y: 250 }
XYPoint { x: toMsecsSinceEpoch(new Date(0, 0, 0, 16, 50, 00)); y: 300 }
}
}
ChartView {
//title: "Spline2"
id: chart2
Layout.fillWidth:true //yes, if wanted
Layout.fillHeight:true //yes, if wanted
legend.visible: true
backgroundColor: "black"
antialiasing: true
//plotArea: Qt.rect(35, 35, parent.width - 75, parent.height / 3 - 75)
SplineSeries {
name: "Chart 2"
color: "cyan"
axisX: ValuesAxis {
visible: false
}
axisY: ValuesAxis{
labelsColor: "white"
}
XYPoint { x: toMsecsSinceEpoch(new Date(0, 0, 0, 15, 29, 00)); y: 50 }
XYPoint { x: toMsecsSinceEpoch(new Date(0, 0, 0, 15, 29, 20)); y: 100 }
XYPoint { x: toMsecsSinceEpoch(new Date(0, 0, 0, 16, 29, 37)); y: 150 }
XYPoint { x: toMsecsSinceEpoch(new Date(0, 0, 0, 16, 30, 20)); y: 200 }
XYPoint { x: toMsecsSinceEpoch(new Date(0, 0, 0, 16, 45, 00)); y: 250 }
XYPoint { x: toMsecsSinceEpoch(new Date(0, 0, 0, 16, 50, 00)); y: 300 }
}
}
ChartView {
Layout.fillWidth: true
Layout.fillHeight: true
legend.visible: true
backgroundColor: "black"
antialiasing: true
//plotArea: Qt.rect(75, 75, parent.width - 125, parent.height / 3 - 125)
SplineSeries {
name: "Chart 3"
color: "purple"
axisX: DateTimeAxis {
format: "hh:mm:ss"
labelsColor: "white"
}
axisY: ValuesAxis{
labelsColor: "white"
}
XYPoint { x: toMsecsSinceEpoch(new Date(0, 0, 0, 15, 29, 00)); y: 50 }
XYPoint { x: toMsecsSinceEpoch(new Date(0, 0, 0, 15, 29, 20)); y: 100 }
XYPoint { x: toMsecsSinceEpoch(new Date(0, 0, 0, 16, 29, 37)); y: 150 }
XYPoint { x: toMsecsSinceEpoch(new Date(0, 0, 0, 16, 30, 20)); y: 200 }
XYPoint { x: toMsecsSinceEpoch(new Date(0, 0, 0, 16, 45, 00)); y: 250 }
XYPoint { x: toMsecsSinceEpoch(new Date(0, 0, 0, 16, 50, 00)); y: 300 }
}
}
}

Does fabricjs support radial-gradient?

I'm working with Fabric to create Radial-gradient like this
It can create very easily by css. Like this
<!DOCTYPE html>
<html>
<head>
<style>
#grad1 {
width: 100px;
height: 100px;
border-radius: 50%;
background: radial-gradient(ellipse at center, #1e5799 0%,rgba(255, 255, 255, 0) 100%);
}
</style>
</head>
<body>
<h3>Radial Gradient - Evenly Spaced Color Stops</h3>
<div id="grad1"></div>
<p><strong>Note:</strong> Internet Explorer 9 and earlier versions do not support gradients.</p>
</body>
</html>
But seem fabricJS do not support it. It only support gradient from side to side (?)
Does anyone work with this before. Please give me support.
Thank you
Yes
Some example: http://jsfiddle.net/fabricjs/58y8b/
// initialize fabric canvas and assign to global windows object for debug
var canvas = window._canvas = new fabric.Canvas('c');
// Do some initializing stuff
fabric.Object.prototype.set({
transparentCorners: false,
cornerColor: 'rgba(102,153,255,0.5)',
cornerSize: 12,
padding: 5
});
// Initialze the example
var rect1 = new fabric.Rect({
left: 100,
top: 100,
width: 100,
height: 100,
fill: '#ffda4f'
});
var rect2 = new fabric.Rect({
left: 250,
top: 100,
width: 100,
height: 100,
fill: 'rgb(111,154,211)'
});
var rect3 = new fabric.Rect({
left: 400,
top: 100,
width: 100,
height: 100,
fill: 'rgb(166,111,213)'
});
var rect4 = new fabric.Rect({
left: 100,
top: 400,
width: 100,
height: 100,
fill: '#ffda4f'
});
var rect5 = new fabric.Rect({
left: 250,
top: 400,
width: 100,
height: 100,
fill: 'rgb(111,154,211)'
});
var rect6 = new fabric.Rect({
left: 400,
top: 400,
width: 100,
height: 100,
fill: 'rgb(166,111,213)'
});
canvas.add(rect1, rect2, rect3, rect4, rect5, rect6);
/**
* setGradient linear gradients example
*/
// horizontal linear gradient
rect1.setGradient('fill', {
type: 'linear',
x1: -rect1.width / 2,
y1: 0,
x2: rect1.width / 2,
y2: 0,
colorStops: {
0: '#ffe47b',
1: 'rgb(111,154,211)'
}
});
// vertical linear gradient
rect2.setGradient('fill', {
type: 'linear',
x1: 0,
y1: -rect2.height / 2,
x2: 0,
y2: rect2.height / 2,
colorStops: {
0: '#ff4040',
1: '#e6399b'
}
});
// diagonal linear gradient
rect3.setGradient('fill', {
type: 'linear',
x1: -rect3.width / 2,
y1: -rect3.height / 2,
x2: rect3.width / 2,
y2: rect3.height / 2,
colorStops: {
0: 'rgb(166,111,213)',
0.5: 'rgba(106, 72, 215, 0.5)',
1: '#200772'
}
});
/**
* setGradient radial gradients example
*/
// radial gradient
rect4.setGradient('fill', {
type: 'radial',
r1: rect4.width / 2,
r2: 10,
x1: 0,
y1: 0,
x2: 0,
y2: 0,
colorStops: {
0: '#FF4F4F',
1: 'rgb(255, 239, 64)'
}
});
// radial gradient
rect5.setGradient('fill', {
type: 'radial',
r1: rect5.width / 2,
r2: 10,
x1: 0,
y1: 0,
x2: rect4.width / 4,
y2: rect4.height / 4,
colorStops: {
0: '#ffe47b',
0.5: 'rgb(111,154,211)',
1: 'rgb(166,111,213)'
}
});
// radial gradient
rect6.setGradient('fill', {
type: 'radial',
r1: 50,
r2: 80,
x1: 45,
y1: 45,
x2: 52,
y2: 50,
colorStops: {
0: 'rgb(155, 237, 0)',
1: 'rgba(0, 164, 128,0.4)'
}
});
canvas.renderAll();
You can do it like this:
let cir = new fabric.Circle({
left: 100,
top: 100,
radius: 30,
fill: 'rgba(0, 0, 0, 0)'
})
cir.setGradient('fill', {
type: 'radial',
r1: 30,
r2: 2,
x1: 30,
y1: 30,
x2: 30,
y2: 30,
colorStops: {
1: 'rgb(113,182,203)',
0: 'rgba(0, 0, 0, 0)'
}
});
fabricCanvas.add(cir);
fabricCanvas.renderAll();
http://jsfiddle.net/Kyashar/z6428pta/

Can google charts treemap customize the borders of boxes?

I know this is very trivial but there is nothing in the documentation. I am using google charts treemap for monitoring something. If all the parent level rectangles are green, the distinct boxes aren't much clear because they are just divided by very thin white line. Can we customize the borders of each rectangle, like black line or increasing the width among each rectangle.
You can provide your own css, just keep in mind the chart is svg.
To change the border color, something like this should work.
rect {
stroke: black;
stroke-width: 2;
}
See following example...
google.charts.load('current', {
callback: function () {
var data = google.visualization.arrayToDataTable([
['Location', 'Parent', 'Market trade volume (size)', 'Market increase/decrease (color)'],
['Global', null, 0, 0],
['America', 'Global', 0, 0],
['Europe', 'Global', 0, 0],
['Asia', 'Global', 0, 0],
['Australia', 'Global', 0, 0],
['Africa', 'Global', 0, 0],
['Brazil', 'America', 11, 10],
['USA', 'America', 52, 31],
['Mexico', 'America', 24, 12],
['Canada', 'America', 16, -23],
['France', 'Europe', 42, -11],
['Germany', 'Europe', 31, -2],
['Sweden', 'Europe', 22, -13],
['Italy', 'Europe', 17, 4],
['UK', 'Europe', 21, -5],
['China', 'Asia', 36, 4],
['Japan', 'Asia', 20, -12],
['India', 'Asia', 40, 63],
['Laos', 'Asia', 4, 34],
['Mongolia', 'Asia', 1, -5],
['Israel', 'Asia', 12, 24],
['Iran', 'Asia', 18, 13],
['Pakistan', 'Asia', 11, -52],
['Egypt', 'Africa', 21, 0],
['S. Africa', 'Africa', 30, 43],
['Sudan', 'Africa', 12, 2],
['Congo', 'Africa', 10, 12],
['Zaire', 'Africa', 8, 10]
]);
new google.visualization.TreeMap(document.getElementById('chart_div')).draw(data, {
minColor: '#f00',
midColor: '#ddd',
maxColor: '#0d0',
headerHeight: 15,
fontColor: 'black',
showScale: true
});
},
packages:['treemap']
});
rect {
stroke: black;
stroke-width: 2;
}
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart_div"></div>

Using pyeda function get the following error

I'am a beginner on Python and i am studying Boolean Algebra, and i was testing this function:
from pyeda.inter import *
list(iter_points([z, y, x]))
[{x: 0, y: 0, z: 0},
{x: 0, y: 0, z: 1},
{x: 0, y: 1, z: 0},
{x: 0, y: 1, z: 1},
{x: 1, y: 0, z: 0},
{x: 1, y: 0, z: 1},
{x: 1, y: 1, z: 0},
{x: 1, y: 1, z: 1}]
i have already install pyeda.
When i execute file I've get the following error:
Traceback (most recent call last):
File "tabela.py", line 3, in
list(iter_points[z, y, x])
NameError: name 'z' is not defined
Any one can help me on this issue?
Thanks i lot guys.
BM
PyEDA author here:
Try this instead:
>>> from pyeda.inter import *
>>> x, y, z = map(exprvar, 'xyz')
>>> list(iter_points([z, y, x]))
x = 0
y = 0
z = 0
print(list(iter_points([z, y, x])))
Also remove the x/y/z list you show here. This is what your result should look like.

How to rewrite Erlang combinations algorithm in Elixir?

I've been tinkering with Elixir for the last few weeks. I just came across this succinct combinations algorithm in Erlang, which I tried rewriting in Elixir but got stuck.
Erlang version:
comb(0,_) ->
[[]];
comb(_,[]) ->
[];
comb(N,[H|T]) ->
[[H|L] || L <- comb(N-1,T)]++comb(N,T).
Elixir version I came up with this, but it's not correct:
def combination(0, _), do: [[]]
def combination(_, []), do: []
def combination(n, [x|xs]) do
for y <- combination(n - 1, xs), do: [x|y] ++ combination(n, xs)
end
Example usage, with incorrect results:
iex> combination(2, [1,2,3])
[[1, 2, [3], [2, 3]]]
Any pointers on what I'm doing wrong?
Thanks!
Sean
You need to wrap the for expression in parentheses like the Erlang code.
def combination(n, [x|xs]) do
(for y <- combination(n - 1, xs), do: [x|y]) ++ combination(n, xs)
end
Demo:
iex(1)> defmodule Foo do
...(1)> def combination(0, _), do: [[]]
...(1)> def combination(_, []), do: []
...(1)> def combination(n, [x|xs]) do
...(1)> (for y <- combination(n - 1, xs), do: [x|y]) ++ combination(n, xs)
...(1)> end
...(1)> end
{:module, Foo,
<<70, 79, 82, 49, 0, 0, 6, 100, 66, 69, 65, 77, 69, 120, 68, 99, 0, 0, 0, 137, 131, 104, 2, 100, 0, 14, 101, 108, 105, 120, 105, 114, 95, 100, 111, 99, 115, 95, 118, 49, 108, 0, 0, 0, 2, 104, 2, ...>>,
{:combination, 2}}
iex(2)> Foo.combination 2, [1, 2, 3]
[[1, 2], [1, 3], [2, 3]]

Resources