Related
I found a post a while back were someone made a corner blob animation similar to the one on the old discord login page (jsfiddle). I want to move it to the right side of the page. I don't know exactly how it works.
const SCALE = 0.25;
const TWO_PI = Math.PI * 2;
const HALF_PI = Math.PI / 2;
const canvas = document.createElement("canvas");
const c = canvas.getContext("2d");
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
document.body.appendChild(canvas);
class Blob {
constructor() {
this.wobbleIncrement = 0;
// use this to change the size of the blob
this.radius = 500;
// think of this as detail level
// number of conections in the `bezierSkin`
this.segments = 12;
this.step = HALF_PI / this.segments;
this.anchors = [];
this.radii = [];
this.thetaOff = [];
const bumpRadius = 100;
const halfBumpRadius = bumpRadius / 2;
for (let i = 0; i < this.segments + 2; i++) {
this.anchors.push(0, 0);
this.radii.push(Math.random() * bumpRadius - halfBumpRadius);
this.thetaOff.push(Math.random() * TWO_PI);
}
this.theta = 0;
this.thetaRamp = 0;
this.thetaRampDest = 12;
this.rampDamp = 25;
}
update() {
this.thetaRamp += (this.thetaRampDest - this.thetaRamp) / this.rampDamp;
this.theta += 0.03;
this.anchors = [0, this.radius];
for (let i = 0; i <= this.segments + 2; i++) {
const sine = Math.sin(this.thetaOff[i] + this.theta + this.thetaRamp);
const rad = this.radius + this.radii[i] * sine;
const theta = this.step * i;
const x = rad * Math.sin(theta);
const y = rad * Math.cos(theta);
this.anchors.push(x, y);
}
c.save();
c.translate(-10, -10);
c.scale(SCALE, SCALE);
c.fillStyle = "blue";
c.beginPath();
c.moveTo(0, 0);
bezierSkin(this.anchors, false);
c.lineTo(0, 0);
c.fill();
c.restore();
}
}
const blob = new Blob();
function loop() {
c.clearRect(0, 0, canvas.width, canvas.height);
blob.update();
window.requestAnimationFrame(loop);
}
loop();
// array of xy coords, closed boolean
function bezierSkin(bez, closed = true) {
const avg = calcAvgs(bez);
const leng = bez.length;
if (closed) {
c.moveTo(avg[0], avg[1]);
for (let i = 2; i < leng; i += 2) {
let n = i + 1;
c.quadraticCurveTo(bez[i], bez[n], avg[i], avg[n]);
}
c.quadraticCurveTo(bez[0], bez[1], avg[0], avg[1]);
} else {
c.moveTo(bez[0], bez[1]);
c.lineTo(avg[0], avg[1]);
for (let i = 2; i < leng - 2; i += 2) {
let n = i + 1;
c.quadraticCurveTo(bez[i], bez[n], avg[i], avg[n]);
}
c.lineTo(bez[leng - 2], bez[leng - 1]);
}
}
// create anchor points by averaging the control points
function calcAvgs(p) {
const avg = [];
const leng = p.length;
let prev;
for (let i = 2; i < leng; i++) {
prev = i - 2;
avg.push((p[prev] + p[i]) / 2);
}
// close
avg.push((p[0] + p[leng - 2]) / 2, (p[1] + p[leng - 1]) / 2);
return avg;
}
I hope these 2 changes in update function help you:
c.translate(canvas.width-10, -10);
c.rotate(Math.PI / 2)
Full Code:
const SCALE = 0.25;
const TWO_PI = Math.PI * 2;
const HALF_PI = Math.PI / 2;
const canvas = document.createElement("canvas");
const c = canvas.getContext("2d");
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
document.body.appendChild(canvas);
class Blob {
constructor() {
this.wobbleIncrement = 0;
// use this to change the size of the blob
this.radius = 500;
// think of this as detail level
// number of conections in the `bezierSkin`
this.segments = 12;
this.step = HALF_PI / this.segments;
this.anchors = [];
this.radii = [];
this.thetaOff = [];
const bumpRadius = 100;
const halfBumpRadius = bumpRadius / 2;
for (let i = 0; i < this.segments + 2; i++) {
this.anchors.push(0, 0);
this.radii.push(Math.random() * bumpRadius - halfBumpRadius);
this.thetaOff.push(Math.random() * TWO_PI);
}
this.theta = 0;
this.thetaRamp = 0;
this.thetaRampDest = 12;
this.rampDamp = 25;
}
update() {
this.thetaRamp += (this.thetaRampDest - this.thetaRamp) / this.rampDamp;
this.theta += 0.03;
this.anchors = [0, this.radius];
for (let i = 0; i <= this.segments + 2; i++) {
const sine = Math.sin(this.thetaOff[i] + this.theta + this.thetaRamp);
const rad = this.radius + this.radii[i] * sine;
const theta = this.step * i;
const x = rad * Math.sin(theta);
const y = rad * Math.cos(theta);
this.anchors.push(x, y);
}
c.save();
c.translate(canvas.width-10, -10);
c.rotate(Math.PI / 2)
c.scale(SCALE, SCALE);
c.fillStyle = "blue";
c.beginPath();
c.moveTo(0, 0);
bezierSkin(this.anchors, false);
c.lineTo(0, 0);
c.fill();
c.restore();
}
}
const blob = new Blob();
function loop() {
c.clearRect(0, 0, canvas.width, canvas.height);
blob.update();
window.requestAnimationFrame(loop);
}
loop();
// array of xy coords, closed boolean
function bezierSkin(bez, closed = true) {
const avg = calcAvgs(bez);
const leng = bez.length;
if (closed) {
c.moveTo(avg[0], avg[1]);
for (let i = 2; i < leng; i += 2) {
let n = i + 1;
c.quadraticCurveTo(bez[i], bez[n], avg[i], avg[n]);
}
c.quadraticCurveTo(bez[0], bez[1], avg[0], avg[1]);
} else {
c.moveTo(bez[0], bez[1]);
c.lineTo(avg[0], avg[1]);
for (let i = 2; i < leng - 2; i += 2) {
let n = i + 1;
c.quadraticCurveTo(bez[i], bez[n], avg[i], avg[n]);
}
c.lineTo(bez[leng - 2], bez[leng - 1]);
}
}
// create anchor points by averaging the control points
function calcAvgs(p) {
const avg = [];
const leng = p.length;
let prev;
for (let i = 2; i < leng; i++) {
prev = i - 2;
avg.push((p[prev] + p[i]) / 2);
}
// close
avg.push((p[0] + p[leng - 2]) / 2, (p[1] + p[leng - 1]) / 2);
return avg;
}
i am using electron(nodejs framework ) and i want to render crispy text for convert it into bitmap and show it on led brick.
like led show software please help.
my code is working but it's system dependent it working fine in some computer but to blurry in some computer.
calling parameter in main.js.
let height = 96;
let width = 288;
let letterSpacing = 1;
var font = "Arial";
var fontSize = 11;
let text_x = 1;
let text_y = 1;
const canvas = new Canvas(height, width, letterSpacing, font, fontSize, text_x, text_y);
here is my canvas.js file.
class Canvas {
constructor(height, width, latterSpacing = 1, font, fontSize, text_x, text_y) {
this.width = width;
this.height = height;
this.letterSpacing = latterSpacing;
this.font = font;
this.fontSize = fontSize;
this.text_x = text_x;
this.text_y = text_y;
this.maxWidth = 32;
this.offset = 0.5;
this.canvas = document.getElementById("myCanvas");
this.ctx = this.canvas.getContext("2d");
}
PIXEL_RATIO = (function () {
// var ctx = document.createElement("canvas").getContext("2d"),
var ctx = document.getElementById("myCanvas").getContext("2d"),
// var ctx = this.ctx,
dpr = window.devicePixelRatio || 1,
bsr = ctx.webkitBackingStorePixelRatio ||
ctx.mozBackingStorePixelRatio ||
ctx.msBackingStorePixelRatio ||
ctx.oBackingStorePixelRatio ||
ctx.backingStorePixelRatio || 1;
return dpr / bsr;
})();
setwidth(maxwidth) {
this.maxWidth = maxwidth;
// this.offset = ofset;
}
setoffset(ofset) {
// this.maxWidth = maxwidth;
this.offset = ofset;
}
createHiDPICanvas = function (w, h, ratio) {
if (!ratio) { ratio = this.PIXEL_RATIO; }
// var can = document.createElement("canvas");
var can = this.canvas;
can.width = w * ratio;
can.height = h * ratio;
can.style.width = w + "px";
can.style.height = h + "px";
can.getContext("2d").setTransform(ratio, 0, 0, ratio, 0, 0);
return can;
}
createCanvas() {
try {
const canvas = document.getElementById("myCanvas");
this.canvas.retinaResolutionEnabled = false;
// this.canvas.style.letterSpacing = "1px";
this.canvas.height = this.height;
this.canvas.width = this.width;
this.canvas.style.letterSpacing = `${this.letterSpacing}px`
/*word spacing*/
// var can = this.createHiDPICanvas(this.width, this.height, 4)
// this.ctx = can.getContext("2d")
this.ctx.beginPath();
// this.ctx = this.canvas.getContext("2d");
this.ctx.fillStyle = "#FF0000";
this.ctx.font = `${this.fontSize}px ` + this.font;
/*Font style and size*/
this.ctx.strokeStyle = "#FF0000";
this.ctx.textBaseline = "top";
this.ctx.textAlign = 'start';
this.ctx.shadowOffsetX = 0;
this.canvas.retinaResolutionEnabled = false;
// this.ctx.fillText("WELCOME TO TICO", 10, 20);
return true;
} catch (error) {
return false;
}
}
clrCanvas(ix = 0, iy = 0, ex = this.canvas.width, ey = this.canvas.height) {
this.ctx.clearRect(ix, iy, ex, ey);
}
fillTextCanvas(str, row = 0, col = 0, vac = 0, hac = 1, _fontSize = this.fontSize, _font = this.font)
{
this.ctx.font = `${_fontSize}px ` + _font;
if (vac) {
col = ((this.canvas.height - (str.length * _fontSize)) / 2) + 1;
}
if (hac) {
this.ctx.textAlign = "center";
row = this.width / 2;
}
for (let index = 0; index < str.length; index++) {
// const element = array[index];
let y = (_fontSize * index) + col;
// this.ctx.fillText(str[index], width / 2, y);
/*text,x,y*/
this.ctx.fillText(str[index], row - 0.8, y - 0.8);
/*text,x,y*/
// this.ctx.fillText("hello", width/2, y);
/*text,x,y*/
}
// display_hex["Screen2"] = jsonArr;
// fillMatrix(jsonArr);
}
async getBitmap() {
var jsonArr = {};
var bin = '';
for (var j = 0; j < this.canvas.width; j++) {
bin = ""
for (var i = 0; i <= this.canvas.height; i++) {
var data = this.ctx.getImageData(j, i, 1, 1); /*getPixel,x,y*/
if (!(i % 32) && i) {
// jsonArr[j + (width * (Math.floor(i / 32) - 1))] = ("0x" + (("00000000" +
ConvertBase.bin2hex(bin)).substr(-8)));
jsonArr[j + (this.width * (Math.floor(i / 32) - 1))] =
parseInt(ConvertBase.bin2dec(bin));
bin = "";
}
if (data['data'][0] >= 200 && data['data'][3] >= 90) {
bin += "1";
} else {
bin += "0";
}
}
}
return jsonArr;
}
fillCanvas(_char, row, col, _fontSize = 11, _font = "Arial") {
this.clrCanvas();
this.ctx.font = `${_fontSize}px ` + _font;
this.ctx.textAlign = "start";
this.ctx.imageSmoothingEnabled = false;
// let linesPos = [[0, 45, 80, 119, 157, 196, 235], [1, 24, 36, 48, 60, 72, 84]]
// let linesPos = [[0, 49, 81, 119, 157, 196, 235], [1, 22, 33, 44, 55, 66, 77]]
let linesPos = [[0, 60, 98, 135, 174, 213, 252], [1, 23, 34, 45, 56, 67, 78]]
this.findColPos(_char);
// console.log(_char)
for (let _row = row; _row < _char.length; _row++) {
// let y = parseInt(text_y) + ((parseInt(fontSize) + 2) * _row);
let y = parseInt(this.text_y + 1) + ((parseInt(_fontSize)) * _row);
for (let index = col; index < _char[_row].length; index++) {
let x = parseInt(this.text_x) + linesPos[0][index];
console.log(this.ctx.measureText(_char[_row][index]).width)
// this.ctx.fillText(_char[_row][index], x + 1.8, y + 0.8,32);
/*text,x,y*/
this.ctx.fillText(_char[_row][index], x + this.offset, y + this.offset, this.maxWidth);
/*text,x,y*/
this.ctx.moveTo(0, linesPos[1][index + 1] + 0.5);
this.ctx.lineTo(this.canvas.width, linesPos[1][index + 1] + 0.5);
this.ctx.moveTo(linesPos[0][index] + 0.5, 0);
this.ctx.lineTo(linesPos[0][index] + 0.5, this.canvas.height);
}
}
this.ctx.stroke();
this.ctx.strokeRect(0, 0, this.canvas.width, this.canvas.height);
// display_hex["Screen1"] = jsonArr;
// canvasImg["Screen1"] = ($('#myCanvas')[0]).toDataURL("image/png");
// fillMatrix(jsonArr);
// return jsonArr;
}
findColPos(__char) {
let maxRow = []
maxRow[0] = 0;
let splitData = [];
maxRow[0] = [];
maxRow[1] = [];
for (let pos = 0; pos < __char[0].length; pos++) {
if (__char[0][pos].split(" ")[1]) {
splitData.push(__char[0][pos].split(" ")[1]);
} else {
// __char[0][pos] = "";
splitData[pos] = " "
}
__char[0][pos] = __char[0][pos].trim().split(" ")[0]; //_char[0][pos] _char[0].splice[];
// _char[0][pos] = splitData[0];
// _char[0].splice
// console.log(_char[0][pos].split(" ")[0]); //_char[0][pos] _char[0].splice[];
}
console.log(__char)
__char.splice(1, 0, splitData)
console.log(__char)
for (let row = 0; row < __char.length; row++) {
for (let col = 0; col < __char[row].length; col++) {
let width = this.ctx.measureText(__char[row][col]).width + 3;
if (!maxRow[0][col + 1]) {
maxRow[0][col + 1] = 0;
}
maxRow[0][col + 1] = maxRow[0][col + 1] < width ? width : maxRow[0][col + 1];
}
}
// console.log(maxRow)
for (let i = 1; i < maxRow.length; i++) {
maxRow[0][i] = maxRow[0][i] + maxRow[0][i - 1];
}
/* for (let index = 0; index < _char.length; index++) {
// const element = array[index];
maxRow[index] = ctx.measureText(_char[index]).width;
} */
// _char = __char
return maxRow;
}
createFonts(start, end) {
let arr = [];
// clearEvents();
for (let index = "/".charCodeAt(0); index <= ":".charCodeAt(0); index++) {
// const element = array[index];
// fillCanvas(index);
let txt = String.fromCharCode(index);
fillTextCanvas(txt, 0, 0, 1, 0, 32);
createCanvas(32, this.ctx.measureText(txt).width, 32);
this.ctx.textBaseline = "middle";
// fillTextCanvas(txt, text_x, text_y);
this.clrCanvas();
fillTextCanvas(txt, 0, 0, 1, 0, 32);
arr.push(display_hex);
// fillMatrix();
}
console.log(JSON.stringify(arr));
// startEvents();
}
findFirstPositive(b, a, i, c) {
c = (d, e) => e >= d ? (a = d + (e - d) / 2, 0 < b(a) && (a == d || 0 >= b(a - 1)) ? a : 0 >=
b(a) ? c(a + 1, e) : c(d, a - 1)) : -1
for (i = 1; 0 >= b(i);) i *= 2
return c(i / 2, i) | 0
}
getDPI() {
var dpi = findFirstPositive(x => matchMedia(`(max-resolution: ${x}dpi)`).matches);
return dpi
}
getImage() {
return this.canvas.toDataURL('image/png', 1.0);
}
}
if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') {
module.exports = Canvas;
}
The canvas does not respect your devices pixel ratio, this is not a specific electron issue.
The code you have copy and pasted from another StackOverflow won't work because you change the size/height again without respecting the ratio. If you uncomment it and adjust it correctly, it will work.
I met a weird question.I have been using FFmpeg's NVENC to encode video .It is strange that I can use h264_nvenc smoothly without problem,but when I replace h264_nvenc with hevc_nvenc,I got the problem "No NVENC capable devices found".The FFmpeg version I am using is 3.2,and I use command line to encode with hevc_nvenc,it works ok.My code is here:
#include "stdafx.h"
int flush_encoder(AVFormatContext *fmt_ctx, unsigned int stream_index)
{
int ret;
int got_frame;
AVPacket enc_pkt;
if (!(fmt_ctx->streams[stream_index]->codec->codec->capabilities &
CODEC_CAP_DELAY))
return 0;
while (1) {
printf("Flushing stream #%u encoder\n", stream_index);
//ret = encode_write_frame(NULL, stream_index, &got_frame);
enc_pkt.data = NULL;
enc_pkt.size = 0;
av_init_packet(&enc_pkt);
ret = avcodec_encode_video2(fmt_ctx->streams[stream_index]->codec, &enc_pkt,
NULL, &got_frame);
av_frame_free(NULL);
if (ret < 0)
break;
if (!got_frame){
ret = 0;
break;
}
printf("Succeed to encode 1 frame! 编码成功1帧!\n");
/* mux encoded frame */
ret = av_write_frame(fmt_ctx, &enc_pkt);
if (ret < 0)
break;
}
return ret;
}
int main(int argc, char* argv[])
{
AVFormatContext* pFormatCtx;
AVOutputFormat* fmt;
AVStream* video_st;
AVCodecContext* pCodecCtx;
AVCodec* pCodec;
uint8_t* picture_buf;
AVFrame* picture;
int size;
FILE *in_file = fopen("test_yuv420p_320x180.yuv", "rb"); //Input YUV data 视频YUV源文件
int in_w = 320, in_h = 180;//宽高
int framenum = 100;
const char* out_file = "ds.hevc";
av_register_all();
//Method1 方法1.组合使用几个函数
pFormatCtx = avformat_alloc_context();
//Guess Format 猜格式
fmt = av_guess_format(NULL, out_file, NULL);
pFormatCtx->oformat = fmt;
//Method 2 方法2.更加自动化一些
//avformat_alloc_output_context2(&pFormatCtx, NULL, NULL, out_file);
//fmt = pFormatCtx->oformat;
//Output Format 注意输出路径
if (avio_open(&pFormatCtx->pb, out_file, AVIO_FLAG_READ_WRITE) < 0)
{
printf("Failed to open output file! 输出文件打开失败");
return -1;
}
video_st = avformat_new_stream(pFormatCtx, 0);
video_st->time_base.num = 1;
video_st->time_base.den = 25;
if (video_st == NULL)
{
return -1;
}
//Param that must set
pCodecCtx = video_st->codec;
pCodecCtx->codec_id =AV_CODEC_ID_HEVC;
//pCodecCtx->codec_id = fmt->video_codec;
pCodecCtx->codec_type = AVMEDIA_TYPE_VIDEO;
pCodecCtx->pix_fmt = AV_PIX_FMT_YUV420P;
pCodecCtx->width = in_w;
pCodecCtx->height = in_h;
pCodecCtx->time_base.num = 1;
pCodecCtx->time_base.den = 25;
pCodecCtx->bit_rate = 400000;
pCodecCtx->gop_size = 12;
//H264
//pCodecCtx->me_range = 16;
//pCodecCtx->max_qdiff = 4;
//pCodecCtx->qcompress = 0.6;
pCodecCtx->qmin = 10;
pCodecCtx->qmax = 51;
//Optional Param
pCodecCtx->max_b_frames = 3;
// Set Option
AVDictionary *param = 0;
//H.264
if (pCodecCtx->codec_id == AV_CODEC_ID_H264) {
av_dict_set(¶m, "preset", "slow", 0);
av_dict_set(¶m, "tune", "zerolatency", 0);
}
//H.265
if (pCodecCtx->codec_id == AV_CODEC_ID_H265){
av_dict_set(¶m, "x265-params", "qp=20", 0);
av_dict_set(¶m, "preset", "default", 0);
av_dict_set(¶m, "tune", "zero-latency", 0);
}
//Dump Information 输出格式信息
av_dump_format(pFormatCtx, 0, out_file, 1);
//pCodec = avcodec_find_encoder(pCodecCtx->codec_id);
pCodec = avcodec_find_encoder_by_name("hevc_nvenc");
if (!pCodec){
printf("Can not find encoder! 没有找到合适的编码器!\n");
return -1;
}
if (avcodec_open2(pCodecCtx, pCodec, ¶m) < 0){
printf("Failed to open encoder! 编码器打开失败!\n");
return -1;
}
picture = av_frame_alloc();
size = avpicture_get_size(pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height);
picture_buf = (uint8_t *)av_malloc(size);
avpicture_fill((AVPicture *)picture, picture_buf, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height);
//Write File Header 写文件头
avformat_write_header(pFormatCtx, NULL);
AVPacket pkt;
int y_size = pCodecCtx->width * pCodecCtx->height;
av_new_packet(&pkt, y_size * 3);
for (int i = 0; i<framenum; i++){
//Read YUV 读入YUV
if (fread(picture_buf, 1, y_size * 3 / 2, in_file) < 0){
printf("Failed to read YUV data! 文件读取错误\n");
return -1;
}
else if (feof(in_file)){
break;
}
picture->data[0] = picture_buf; // 亮度Y
picture->data[1] = picture_buf + y_size; // U
picture->data[2] = picture_buf + y_size * 5 / 4; // V
//PTS
picture->pts = i;
picture->format = pCodecCtx->pix_fmt;
picture->width = in_w;
picture->height = in_h;
int got_picture = 0;
//Encode 编码
int ret = avcodec_encode_video2(pCodecCtx, &pkt, picture, &got_picture);
if (ret < 0){
printf("Failed to encode! 编码错误!\n");
return -1;
}
if (got_picture == 1){
printf("Succeed to encode 1 frame! 编码成功1帧!\n");
pkt.stream_index = video_st->index;
ret = av_write_frame(pFormatCtx, &pkt);
av_free_packet(&pkt);
}
}
//Flush Encoder
int ret = flush_encoder(pFormatCtx, 0);
if (ret < 0) {
printf("Flushing encoder failed\n");
return -1;
}
//Write file trailer 写文件尾
av_write_trailer(pFormatCtx);
//Clean 清理
if (video_st){
avcodec_close(video_st->codec);
av_free(picture);
av_free(picture_buf);
}
avio_close(pFormatCtx->pb);
avformat_free_context(pFormatCtx);
fclose(in_file);
system("pause");
return 0;
}
Help!!!!
after a few days of strugglling,once again I try anwser the question myself.The key point is ,when encoding with hevc_nvenc,you must set pCodecCtx->max_b_frames = 0;(at least for version 3.2 of ffmpeg).
If one knows the "weights" of red, green, and blue, one can create a color using a class like
.blaRGB {
color: rgb(128, 128, 128)
}
.blaHSL {
color: hsl(33%, 34%, 33%)
}
and use it in HTML like so:
<p class="blaRGB">BLA RGB</p>
<p class="blaHSL">BLA HSL</p>
With the values shown above, blaRGB is dingy gray and blaHSL is white.
But what if one wants to represent combinations of other colors, such as green, blue, orange, and gold?
Is there a way to define such colors with a notation like the following?
.CyndiLauper {
color: truecolors(24, 13, 11, 12)
}
Or with color: gbog(24, 13, 11, 12) where the letters in gbog stand for green, blue, orange, and gold respectively?
The intent is that with the CSS definition above, the HTML
<p class="CyndiLauper">These are your True Colors, shining through!</p>
would display the text in a weighted combination of those four colors.
I believe this is possible using some convoluted math using the RGB values of green, blue, orange, and gold, but I don't know how to proceed with that.
UPDATE
I realize that a key component to the question, which I initially omitted, would be, "What exactly do you mean by green, blue, orange, and gold"?
To answer that, according to the official "True Colors" website, and using the ColorZilla browser add-in, the RGB values for these colors are:
green = 15, 167, 73
blue = 0, 152, 215
orange = 243, 123, 38
gold = 255, 230, 101
(They actually look more like forest green, dodger blue, red-orange, and yellow to me.)
There are many ways to mix colors, depending on what color model you're using:
additive mixing
subtractive mixing
alpha compositing
The following code snippet demonstrates two mixing methods. The leftmost column displays the four original colors. The next column shows the same colors with 0.25 opacity, resulting in translucent colors. The third column layers the translucent colors on top of one another, which is equivalent to alpha compositing.
The fourth column shows an alternative approach to mixing. Here we see the result of separately averaging the R, G, and B components of each of the four original colors.
var Colors = {
names: ['green', 'blue', 'orange', 'gold'],
values: {
green: { r: 15, g: 167, b: 73 },
blue: { r: 0, g: 152, b: 215 },
orange: { r: 243, g: 123, b: 38 },
gold: { r: 255, g: 230, b: 101 }
}
};
Colors.toHex2 = function (decimal) {
var hex = decimal.toString(16);
return (hex.length == 1 ? '0'+hex : hex);
};
Colors.toColorString = function (value) {
var g = Colors,
toHex2 = g.toHex2;
var parts = [ '#', toHex2(value.r), toHex2(value.g), toHex2(value.b) ];
return parts.join('');
};
Colors.load = function () {
var g = Colors,
names = g.names,
values = g.values,
containers = {
original: document.getElementById('original'),
translucent: document.getElementById('translucent'),
layered: document.getElementById('layered'),
averaged: document.getElementById('averaged')
},
averaged = { r: 0, g: 0, b: 0 };
document.body.style.paddingTop = 10*(1+names.length) + 'px';
for (var i = 0; i < names.length; ++i) {
var name = names[i],
value = values[name],
color = g.toColorString(value),
swatch = document.createElement('div'),
proportion = 1 / names.length;
swatch.className = 'swatch';
swatch.style.backgroundColor = color;
containers.original.appendChild(swatch);
swatch = swatch.cloneNode();
swatch.style.opacity = proportion;
containers.translucent.appendChild(swatch);
swatch = swatch.cloneNode();
swatch.style.height = 60 + 10*(names.length-1) + 'px';
swatch.style.top = 10*(1+i-names.length) + 'px';
containers.layered.appendChild(swatch);
averaged.r += proportion * value.r;
averaged.g += proportion * value.g;
averaged.b += proportion * value.b;
}
swatch = document.createElement('div');
swatch.className = 'swatch';
averaged.r = Math.round(averaged.r);
averaged.g = Math.round(averaged.g);
averaged.b = Math.round(averaged.b);
swatch.style.backgroundColor = g.toColorString(averaged);
containers.averaged.appendChild(swatch);
};
window.onload = Colors.load;
body {
font-family: sans-serif;
font-size: 24px;
margin: 0;
padding-left: 20px;
}
.display {
width: 120px;
float: left;
}
.swatch {
width: 100px;
height: 60px;
margin-bottom: 10px;
}
.layered {
position: relative;
height: 60px;
}
.layered .swatch {
position: absolute;
}
<div id="original" class="display"></div>
<div id="translucent" class="display"></div>
<div id="layered" class="display layered"></div>
<div id="averaged" class="display"></div>
In the demonstration above, we let the web browser do the alpha compositing for us. We can also do alpha compositing directly. Layer opacity is equivalent to the alpha channel, so we set the alpha channel of each color to the weight of the color. In other words, if the weight of a color is 25%, we set its alpha channel to 0.25.
Note that the alpha channel ranges from 0 to 1. However, our RGB components range from 0 to 255.
Suppose we are mixing these two colors:
RGB value background with alpha channel alpha.background
RGB value foreground with alpha channel alpha.foreground
We calculate the resulting color's alpha channel alpha.mix like so:
alpha.mix = 1 - (1-alpha.background)*(1-alpha.foreground);
To compute the R component of the RGB value mix, we do this:
mix.r = 255 * (foreground.r/255.0 * alpha.foreground/alpha.mix +
mix.r/255.0 * alpha.background*(1-alpha.foreground)/alpha.mix);
And likewise for the G component mix.g and the B component mix.b.
The code snippet below is an interactive demonstration that compares alpha compositing with the simpler approach of averaging the RGB components in parallel. Run the code and play around with the sliders to see the difference between these two approaches.
var Mixer = {
color: {
names: ['green', 'blue', 'orange', 'gold'],
rgb: {
green: { r: 15, g: 167, b: 73 },
blue: { r: 0, g: 152, b: 215 },
orange: { r: 243, g: 123, b: 38 },
gold: { r: 255, g: 230, b: 101 }
}
},
style: {
swatch: { width: 150, height: 90, margin: { right: 15 } },
slider: { height: 20 },
handle: { width: 20, height: 34 }
}
};
Mixer.toHex2 = function (decimal) {
var hex = decimal.toString(16);
return (hex.length == 1 ? '0'+hex : hex);
};
Mixer.toCSS = function (rgb) {
var g = Mixer,
toHex2 = g.toHex2;
var parts = [ '#', toHex2(rgb.r), toHex2(rgb.g), toHex2(rgb.b) ];
return parts.join('');
};
Mixer.toString = function (rgb) {
return 'rgb(' + [rgb.r, rgb.g, rgb.b].join(', ') + ')';
};
Mixer.makeUnselectable = function (element) {
element.className += ' unselectable';
element.ondragstart = element.onselectstart = function (event) {
event.preventDefault();
};
};
Mixer.makeElement = function (tag, className, innerHTML, unselectable) {
var g = Mixer,
element = document.createElement(tag);
element.className = (className ? className : '');
element.innerHTML = (innerHTML ? innerHTML : '');
if (unselectable) {
g.makeUnselectable(element);
}
return element;
};
Mixer.handleDown = function (event) {
event = event || window.event;
var g = Mixer;
g.mouseX = { depart: event.screenX };
g.activeHandle = this;
window.onmousemove = Mixer.handleMove;
window.onmouseup = Mixer.handleUp;
};
Mixer.handleMove = function (event) {
event = event || window.event;
var g = Mixer,
handle = g.activeHandle,
pos = handle.pos,
handles = g.handles,
num = g.num,
slider = g.slider,
proportion = g.proportion,
segments = g.segments,
handleWidth = g.style.handle.width,
swatches = g.swatches,
canvas = g.canvas,
context = g.context,
mixingFunctions = g.mixingFunctions,
limit = {
min: (pos == 0 ? 0 : handles[pos-1].right),
max: (pos == num-2 ? slider.length.total : handles[pos+1].left) -
handleWidth
},
mouseX = g.mouseX;
mouseX.current = event.screenX;
var left = handle.left + mouseX.current - mouseX.depart;
if (left < limit.min) {
left = limit.min;
}
if (left > limit.max) {
left = limit.max;
}
handle.newLeft = left;
segments[pos] = left - limit.min;
context.fillStyle = swatches[pos].css;
context.fillRect(limit.min, 0, segments[pos], canvas.height);
segments[pos+1] = limit.max - left;
context.fillStyle = swatches[pos+1].css;
context.fillRect(left + handleWidth, 0, segments[pos+1], canvas.height);
handle.style.left = left + 'px';
var segmentSpan = segments[pos] + segments[pos+1],
proportionSpan = proportion[pos] + proportion[pos+1];
if (segmentSpan != 0) {
proportion[pos] = Math.round(segments[pos]/segmentSpan * proportionSpan);
proportion[pos+1] = proportionSpan - proportion[pos];
swatches[pos].percent.innerHTML = proportion[pos] + '%';
swatches[pos+1].percent.innerHTML = proportion[pos+1] + '%';
}
g.mixColors();
};
Mixer.handleUp = function (event) {
var g = Mixer,
handle = g.activeHandle;
window.onmousemove = null;
window.onmouseup = null;
handle.left = handle.newLeft;
handle.right = handle.left + g.style.handle.width;
};
Mixer.makeFunctionName = function (title) {
var parts = ['mix'],
tokens = title.split(' ');
for (var i = 0; i < tokens.length; ++i) {
var token = tokens[i];
parts.push(token[0].toUpperCase() + token.substring(1));
}
return parts.join('');
};
Mixer.mixAlphaCompositing = function (swatch, label) {
return function () {
var g = Mixer,
swatches = g.swatches,
proportion = g.proportion,
num = g.num,
mix = {},
subs = ['r', 'g', 'b'];
for (var i = 0; i < subs.length; ++i) {
var x = subs[i];
mix[x] = swatches[0].rgb[x];
}
var alpha = { back: proportion[0]/100 };
for (var pos = 1; pos < num; ++pos) {
var fore = swatches[pos].rgb;
alpha.fore = proportion[pos]/100,
alpha.mix = 1 - (1-alpha.back)*(1-alpha.fore);
if (alpha.mix >= 1.0e-6) {
for (var i = 0; i < subs.length; ++i) {
var x = subs[i];
mix[x] = 255 * (fore[x]/255 * alpha.fore/alpha.mix +
mix[x]/255 * alpha.back*(1-alpha.fore)/alpha.mix);
}
}
alpha.back = alpha.mix;
}
for (var i = 0; i < subs.length; ++i) {
var x = subs[i];
mix[x] = Math.round(mix[x]);
}
var css = g.toCSS(mix);
label.rgb.innerHTML = g.toString(mix);
label.css.innerHTML = css;
swatch.style.backgroundColor = css;
swatch.style.opacity = alpha.mix;
};
};
Mixer.mixWeightedAverage = function (swatch, label) {
return function () {
var g = Mixer,
swatches = g.swatches,
proportion = g.proportion,
num = g.num,
mix = { r: 0, g: 0, b: 0 },
subs = ['r', 'g', 'b'];
for (var pos = 0; pos < num; ++pos) {
for (var i = 0; i < subs.length; ++i) {
var x = subs[i];
mix[x] += proportion[pos]/100 * swatches[pos].rgb[x];
}
}
for (var i = 0; i < subs.length; ++i) {
var x = subs[i];
mix[x] = Math.round(mix[x]);
}
var css = g.toCSS(mix);
label.rgb.innerHTML = g.toString(mix);
label.css.innerHTML = css;
swatch.style.backgroundColor = css;
};
};
Mixer.mixColors = function () {
var g = Mixer,
mixingFunctions = g.mixingFunctions;
for (var i = 0; i < mixingFunctions.length; ++i) {
mixingFunctions[i]();
}
};
Mixer.load = function () {
var g = Mixer,
style = g.style;
// Make color swatches.
var palette = g.palette = document.getElementById('palette'),
names = g.color.names,
swatches = g.swatches = [],
num = g.num = names.length;
for (var i = 0; i < num; ++i) {
var name = names[i],
rgb = g.color.rgb[name],
css = g.toCSS(rgb),
container = g.makeElement('div', 'swatchContainer', '', true),
percent = g.makeElement('div', 'title', '', true),
swatch = g.makeElement('div', 'swatch', '', true);
swatches[i] = { rgb: rgb, css: css, percent: percent };
container.appendChild(percent);
swatch.style.backgroundColor = css;
swatch.style.width = style.swatch.width + 'px';
swatch.style.height = style.swatch.height + 'px';
swatch.style.marginRight = style.swatch.margin.right + 'px';
container.appendChild(swatch);
container.appendChild(g.makeElement('div', 'label', g.toString(rgb), true));
container.appendChild(g.makeElement('div', 'label', css, true));
palette.appendChild(container);
}
var totalWidth = num*style.swatch.width + (num-1)*style.swatch.margin.right;
// Initialize proportions.
var proportion = g.proportion = new Array(num),
each = Math.floor(100/num);
for (var i = 0; i < num-1; ++i) {
proportion[i] = each;
}
proportion[num-1] = 100 - (num-1)*each;
for (var i = 0; i < num; ++i) {
swatches[i].percent.innerHTML = proportion[i] + '%';
}
// Prepare the blended swatches.
var blend = g.blend = { container: document.getElementById('blend') },
mixers = ['alpha compositing', 'weighted average'],
between = (totalWidth - mixers.length*style.swatch.width) /
(mixers.length + 1);
g.makeUnselectable(blend);
blend.container.style.width = totalWidth + 'px';
blend.container.style.height = style.swatch.height + 'px';
g.mixingFunctions = [];
for (var i = 0; i < mixers.length; ++i) {
var mixer = mixers[i],
container = g.makeElement('div', 'swatchContainer', '', true),
title = g.makeElement('div', 'title', mixer, true),
swatch = g.makeElement('div', 'swatch', '', true),
label = {
rgb: g.makeElement('div', 'label', '', true),
css: g.makeElement('div', 'label', '', true)
};
swatch.style.width = style.swatch.width + 'px';
swatch.style.height = style.swatch.height + 'px';
container.style.left = i*style.swatch.width + (i+1)*between + 'px';
container.appendChild(title);
container.appendChild(swatch);
container.appendChild(label.rgb);
container.appendChild(label.css);
blend.container.appendChild(container);
var functionName = g.makeFunctionName(mixer),
mixingFunction = g[functionName](swatch, label);
g.mixingFunctions.push(mixingFunction);
}
// Assemble the slider widget.
var slider = g.slider = document.getElementById('slider');
slider.length = {
total: totalWidth,
free: totalWidth - (num-1)*style.handle.width
};
var segments = g.segments = new Array(num);
var tail = slider.length.free;
for (var i = 0; i < num-1; ++i) {
var current = Math.round(proportion[i]/100*slider.length.free);
segments[i] = current;
tail -= current;
}
segments[num-1] = tail;
slider.style.width = slider.length.total + 'px';
slider.style.height = style.slider.height + 'px';
var canvas = g.canvas = g.makeElement('canvas'),
context = g.context = canvas.getContext('2d');
g.makeUnselectable(slider);
g.makeUnselectable(canvas);
canvas.width = slider.length.total;
canvas.height = style.slider.height;
slider.appendChild(canvas);
var handles = g.handles = new Array(num-1);
var left = 0;
for (var i = 0; i < num; ++i) {
context.fillStyle = swatches[i].css;
context.fillRect(left, 0, segments[i], canvas.height);
if (i == num-1) {
break;
}
var handle = handles[i] = g.makeElement('div', 'handle', '', true);
handle.pos = i;
handle.style.width = style.handle.width + 'px';
handle.style.height = style.handle.height + 'px';
handle.style.top = (style.slider.height - style.handle.height)/2 + 'px';
handle.left = left + segments[i];
handle.style.left = handle.left + 'px';
handle.right = handle.left + style.handle.width;
left = handle.right;
handle.onmousedown = g.handleDown;
slider.appendChild(handle);
}
g.mixColors();
};
window.onload = Mixer.load;
body {
font-family: sans-serif;
color: #444;
}
.unselectable {
-webkit-user-select: none;
-khtml-user-drag: none;
-khtml-user-select: none;
-moz-user-select: none;
-moz-user-select: -moz-none;
-ms-user-select: none;
user-select: none;
}
#blend {
position: relative;
padding: 10px 0 90px;
}
#blend .swatchContainer {
position: absolute;
}
#blend .swatchContainer .title {
font-size: 17px;
padding-bottom: 5px;
}
#slider {
margin: 20px 0;
position: relative;
}
.handle {
position: absolute;
background: #444;
border-radius: 5px;
cursor: pointer;
}
.swatchContainer {
float: left;
}
.swatchContainer .title {
font-size: 25px;
text-align: center;
}
.swatchContainer .label {
font-size: 17px;
}
<div id="blend"></div>
<div id="slider"></div>
<div id="palette"></div>
No, you cannot. Here is a link to W3 Css Colors definition which states at the top that only blue, red, and green can be used.
Edit: Ok, so let me clarify. Natively, this is not possible, from my understanding. However, there may be things you can do using Less and Sass that can achieve your desired result. Here is some tutorial regarding Less Color functions. Most interestingly is the part about Mixing colors:
.box.mix {
background-color: mix(#blue, #yellow, 50%);
}
You would need to explore this, however, as I have no experience with it.
I wonder if the answer isn't just to 'mix' colors in RGB?
var green = [15, 167, 73];
var blue = [0, 152, 215];
var orange = [243, 123, 38];
var gold = [255, 230, 101];
generateTrueColor(greenRatio, blueRatio, orangeRatio, goldRatio){
for(var i = 0; i < 3, i++){
RGB[i] = greenRatio * green[i] + blueRatio * blue[i] + orangeRatio * orange[i] + goldRatio * gold[i];
}
return RGB;
for(var i = 0; i < 3, i++){
if(RGB[i] > 255) RGB[i] = 255;
}
}
generateTrueColor(1, 0.1, 0.1, 0.1);
I'm not sure dividing by 50 is the right/best thing to do, but this pretty much works:
// Note that the results differ from "true" blue, green, orange, and gold; the colors used to represent these are custom versions of those colors, as found on the True Colors website
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace Sandbox
{
public partial class FormTrueColorsMain : Form
{
// Primary constituents of the "True Colors" hues
const int GREEN_RED = 15;
const int GREEN_GREEN = 167;
const int GREEN_BLUE = 73;
const int BLUE_RED = 0;
const int BLUE_GREEN = 152;
const int BLUE_BLUE = 215;
const int ORANGE_RED = 243;
const int ORANGE_GREEN = 123;
const int ORANGE_BLUE = 38;
const int GOLD_RED = 255;
const int GOLD_GREEN = 230;
const int GOLD_BLUE = 101;
Color tcGreen = Color.FromArgb(15, 167, 73);
Color tcGreenComplement = Color.FromArgb(240, 88, 182);
Color tcBlue = Color.FromArgb(0, 152, 215);
Color tcOrange = Color.FromArgb(243, 123, 38);
Color tcGold = Color.FromArgb(255, 230, 101);
public FormTrueColorsMain()
{
InitializeComponent();
InitializeControls();
}
private void InitializeControls()
{
lblGreen.ForeColor = tcGreen;
lblGreen.BackColor = Color.White; // tcGreenComplement;
lblBlue.ForeColor = tcBlue;
lblBlue.BackColor = Color.White;
lblOrange.ForeColor = tcOrange;
lblOrange.BackColor = Color.Black;
lblGold.ForeColor = tcGold;
lblGold.BackColor = Color.Black;
// For these to work, needed to also comment out "Application.EnableVisualStyles();" in Program.cs (see Crispy's answer at http://stackoverflow.com/questions/778678/how-to-change-the-color-of-progressbar-in-c-sharp-net-3-5)
progressBarGreen.ForeColor = tcGreen;
progressBarGreen.Style = System.Windows.Forms.ProgressBarStyle.Continuous;
progressBarBlue.ForeColor = tcBlue;
progressBarBlue.Style = System.Windows.Forms.ProgressBarStyle.Continuous;
progressBarOrange.ForeColor = tcOrange;
progressBarOrange.Style = System.Windows.Forms.ProgressBarStyle.Continuous;
progressBarGold.ForeColor = tcGold;
progressBarGold.Style = System.Windows.Forms.ProgressBarStyle.Continuous;
}
private void button1_Click(object sender, EventArgs e)
{
// If they have already been set (user clicked the arrows rather than entered the value directly), this is moot but it's
// probably not worthwhile checking to see whether their value is 0, and only calling the methods conditionally in that case.
SetGreenProgressBar();
SetBlueProgressBar();
SetOrangeProgressBar();
SetGoldProgressBar();
int greenVal = (int)numericUpDownGreen.Value;
int blueVal = (int)numericUpDownBlue.Value;
int orangeVal = (int)numericUpDownOrange.Value;
int goldVal = (int)numericUpDownGold.Value;
Color trueColor = GetTrueCombinedColor(greenVal, blueVal, orangeVal, goldVal);
pictureBoxTCCombo.BackColor = trueColor;
}
private Color GetTrueCombinedColor(int greenVal, int blueVal, int orangeVal, int goldVal)
{
// tcBlue has no red, so can disregard blueVal for redTotal
int redTotal = ((greenVal * GREEN_RED) + (orangeVal * ORANGE_RED) + (goldVal * GOLD_RED));
int greenTotal = ((greenVal * GREEN_GREEN) + (blueVal * BLUE_GREEN) + (orangeVal * ORANGE_GREEN) + (goldVal * GOLD_GREEN));
int blueTotal = ((greenVal * GREEN_BLUE) + (blueVal * BLUE_BLUE) + (orangeVal * ORANGE_BLUE) + (goldVal * GOLD_BLUE));
int redWeight = redTotal / 50;
int greenWeight = greenTotal / 50;
int blueWeight = blueTotal / 50;
if (redWeight <= 0) redWeight = 1;
if (greenWeight <= 0) greenWeight = 1;
if (blueWeight <= 0) blueWeight = 1;
if (redWeight >= 256) redWeight = 255;
if (greenWeight >= 256) greenWeight = 255;
if (blueWeight >= 256) blueWeight = 255;
Color trueColorCombo = Color.FromArgb(redWeight, greenWeight, blueWeight);
//Color trueColorCombo = Color.FromArgb(redWeight, greenWeight, blueWeight, 10);
return trueColorCombo;
}
private void numericUpDownGreen_ValueChanged(object sender, EventArgs e)
{
SetGreenProgressBar();
}
private void SetGreenProgressBar()
{
progressBarGreen.Value = (int)numericUpDownGreen.Value;
}
private void numericUpDownBlue_ValueChanged(object sender, EventArgs e)
{
SetBlueProgressBar();
}
private void SetBlueProgressBar()
{
progressBarBlue.Value = (int)numericUpDownBlue.Value;
}
private void numericUpDownOrange_ValueChanged(object sender, EventArgs e)
{
SetOrangeProgressBar();
}
private void SetOrangeProgressBar()
{
progressBarOrange.Value = (int)numericUpDownOrange.Value;
}
private void numericUpDownGold_ValueChanged(object sender, EventArgs e)
{
SetGoldProgressBar();
}
private void SetGoldProgressBar()
{
progressBarGold.Value = (int)numericUpDownGold.Value;
}
}
}
Here's what the util looks like:
Cyndi Lauper, eat your heart out!
I'm trying to put items from a csv file in an hashmap. By adding items I mean categorizing them. The csv is filled with the answers from a question list. So the csv is build up like this:
Person Question
- Do you wear glasses
1 Yes
2 Yes
3 No
4 Sometimes
The next step I would like to do is reading the items and put the answer in the hashmap with the key being the name of the answer and the value with the amount of that certain answer.
The hashmap should look like this with the previous example I gave:
Yes, 2
No, 1
Sometimes, 1
I'm looping right now like this:
for (int j = 0; j < dataPersonList.size(); j++)
{
// looping through the csv
while (t.hasNext ())
{
// looping through the hashmap
Map.Entry me = (Map.Entry)t.next();
if (dataPersonVar.glasses.equals(me.getKey()))
{
// if the item in the csv is the same as the item in the hashmap
hm.put(me.getKey(), me.getValue() =+ 1); // the value gets +1
}
else
{
// a new item is made and gets automatically 1
hm.put(dataPersonVar.glasses,1);
}
}
}
But obviously this doesn't work. I'm a starter with hashmaps but really think the hashmap is the solution for my problem. I'm working in Processing. Does anybody have an idea how to solve this? If I'm not clear enough let me know!
Thanks in advance
Edit:
As requested I hereby post the full code:
import java.util.Iterator;
import java.util.Map;
HashMap hm = new HashMap();
import de.bezier.data.*;
int totalParticipants;
int bgWidth = 1000;
int bgHeight = 1000;
int x;
int eSize = 10;
int opacity = 100;
float xLocation;
float yLocation;
String travelType;
int travelTime;
int border=400;
float dataMinLat=1000;
float dataMaxLat;
float dataMinLon=1000;
float dataMaxLon;
float xLocationMM = (5.17880);
float yLocationMM = (52.22541);
ArrayList dataPersonList = new ArrayList();
ArrayList dataFunctionList = new ArrayList(100);
Point[] pointList = new Point[1000];
float angle;
XlsReader reader;
PImage kaart;
void setup ()
{
textSize(10);
size(bgWidth, bgHeight);
background(0);
noStroke();
smooth();
//kaart = loadImage("map.png");
yLocationMM = 0 - yLocationMM;
reader = new XlsReader( this, "MMdata.xls" ); // assumes file to be in the data folder
totalParticipants = reader.getLastRowNum();
for (int i = 1;i < totalParticipants+1; i++) {
DataPerson dataPerson = new DataPerson();
dataPerson.function = reader.getString(i, 23);
dataPerson.firstName = reader.getString(i, 1);
dataPerson.lastName = reader.getString(i, 2);
dataPerson.glasses = reader.getString(i, 20);
dataPerson.longitude = reader.getFloat(i, 55);
dataPerson.latitude = reader.getFloat(i, 54);
dataPerson.location = reader.getString(i, 8);
dataPerson.ownage = reader.getString(i, 14);
dataPerson.traveltime = reader.getInt(i, 31);
dataPerson.establishment = reader.getString(i, 58);
dataPerson.traveltype = reader.getString(i, 17);
dataPersonList.add(dataPerson);
}
for (int i = 0; i < dataPersonList.size(); i++) {
DataPerson person = (DataPerson) dataPersonList.get(i);
for (int j = 0; j < dataFunctionList.size() + 1; j++) {
DataFunction dataFunction = null;
if (j < dataFunctionList.size())
{
dataFunction = (DataFunction) dataFunctionList.get(j);
}
if (dataFunction != null) {
if (person.function.equals(dataFunction.function)) {
dataFunction.persons.add(person);
dataFunction.amount ++;
break;
}
}
else {
dataFunction = new DataFunction();
dataFunction.function = person.function;
dataFunction.amount = 1;
dataFunction.persons.add(person);
dataFunctionList.add(dataFunction);
break;
}
}
}
for (int i = 0; i < dataPersonList.size(); i++) {
DataPerson dataPersonVar = (DataPerson) dataPersonList.get(i);
if (dataPersonVar.longitude > dataMaxLon) {
dataMaxLon = dataPersonVar.longitude;
}
else if (dataPersonVar.longitude < dataMinLon) {
dataMinLon = dataPersonVar.longitude;
}
if (dataPersonVar.latitude > dataMaxLat) {
dataMaxLat = dataPersonVar.latitude;
}
else if (dataPersonVar.latitude < dataMinLat) {
dataMinLat = dataPersonVar.latitude;
}
}
}
class DataPerson
{
String function;
String firstName;
String lastName;
String glasses;
float longitude;
float latitude;
String location;
String ownage;
int traveltime;
String establishment;
String traveltype;
String fullName()
{
return firstName + " " + lastName;
}
}
class DataFunction
{
String function;
int amount;
ArrayList persons = new ArrayList();
String getPersonNames()
{
String output = "";
for (int i = 0; i < persons.size(); i++) {
DataPerson person = (DataPerson) persons.get(i);
output += person.firstName + "(" + person.glasses + ") ";
}
return output;
}
}
class Point
{
float x;
float y;
}
void draw()
{
background(0);
strokeWeight(2);
x=50;
int xText=80;
int procentGlasses;
noStroke();
pushMatrix();
scale(1.40, 0.89);
//image(kaart, -250, -360);
popMatrix();
for (int i = 0; i < dataPersonList.size(); i++) {
DataPerson dataPersonVar = (DataPerson) dataPersonList.get(i);
if (dataPersonVar != null) {
xLocation = map(dataPersonVar.longitude, dataMinLon, dataMaxLon, border, bgWidth-border);
yLocation = map(dataPersonVar.latitude, dataMinLat, dataMinLat+(dataMaxLon-dataMinLon), border, bgHeight-border);
travelType = (dataPersonVar.traveltype);
noFill();
if (travelType.equals("By car")) {
stroke(0, 0, 255, opacity+100);
}
else if (travelType.equals("By public transport")) {
stroke(255, 0, 0, opacity);
}
else {
stroke(255, opacity);
}
//text(dataPersonVar.firstName, xLocation, yLocation);
noStroke();
strokeWeight(4);
stroke(100, 15);
strokeWeight(2);
}
}
for (int i = 0; i < dataPersonList.size(); i++) {
DataPerson dataPersonVar = (DataPerson) dataPersonList.get(i);
if (dataPersonVar != null) {
xLocation = map(dataPersonVar.longitude, dataMinLon, dataMaxLon, border, bgWidth-200);
yLocation = map(dataPersonVar.latitude, dataMinLat, dataMinLat+(dataMaxLon-dataMinLon), border, bgHeight-200);
noStroke();
fill(255, 200);
ellipse(xLocation, yLocation, eSize, eSize);
//println(dataPersonVar.glasses);
Iterator t = hm.entrySet().iterator(); // Get an iterator
for (int j = 0; j < dataPersonList.size(); j++) {
while (t.hasNext ()) {
Map.Entry me = (Map.Entry)t.next();
println("die in de dataPersonshit is "+dataPersonVar.glasses+". En de andere waarde is "+me.getKey());
if (dataPersonVar.glasses.equals(me.getKey())) {
hm.put(me.getKey(), ((Integer)me.getValue()) + 1);
}
else {
hm.put(dataPersonVar.glasses, 1);
//println("YEAH");
}
}
}
/////////drawing the circle///////////////
angle = ((PI*2)/15*1)/dataPersonList.size()*i;
stroke(255, 100, 50, 50);
noFill();
strokeWeight(3);
pointList[i] = new Point();
pointList[i].x = bgWidth/2+sin(angle)*400; // de punt van x = 400 ( het middelpunt van de cirkel ) + sin((360 graden) / het totaal
pointList[i].y = bgHeight/2+cos(angle)*400;
beginShape();
vertex(xLocation, yLocation);
quadraticVertex((xLocation+pointList[i].x)/2, yLocation, pointList[i].x, pointList[i].y);
endShape();
}
}
}
Unfortunately I can't give you the csv but I hope the code at least helps.
You don't really need to iterate over the map to do what you seem to be trying to do. Here is an example with a similar csv as you have described:
import java.util.Map;
Map<String, Integer> answers = new HashMap<String,Integer>();
//String [] fileInput = loadStrings("question.csv");
String [] fileInput = new String [] {
"1,Yes", "2,No", "3,Yes", "4,Sometimes", "5,Yes", "6,No", "7,No", "8,No"
};
for (int i = 0 ; i < fileInput.length; i++) {
String [] line = split(fileInput[i],",");
String newAnswer = line[1];
if(!answers.containsKey(newAnswer)) answers.put(newAnswer,1);
else answers.put(newAnswer,answers.get(newAnswer)+1);
}
println(answers);