I'm drawing data in a JS canvas. I need to enter the veritcal and horizontal axis values at fix intervals.
I would ask how to create an array of paragraph or text to assign an absolute coordinate and the right axis value to draw them around the canvas.
currently I created and edited line by line:
document.getElementById('percent0').innerHTML =
a.toFixed(5-Math.round(Math.log10(a)));
a = minVal+(maxVal-minVal)*0.25;
document.getElementById('percent25').innerHTML =
a.toFixed(5-Math.round(Math.log10(a)));
a = minVal+(maxVal-minVal)*0.5;
document.getElementById('percent50').innerHTML =
a.toFixed(5-Math.round(Math.log10(a)));
a = minVal+(maxVal-minVal)*0.75;
document.getElementById('percent75').innerHTML =
a.toFixed(5-Math.round(Math.log10(a)));
a = minVal+(maxVal-minVal)*1;
document.getElementById('percent100').innerHTML =
a.toFixed(5-Math.round(Math.log10(a)));
but I would like to use a smart way to do it with array if possible.
thks.
Just add mark values to array and use it where it changes:
const marks = [0, 25, 50, 75, 100};
marks.forEach(mark => {
const a = minVal+(maxVal-minVal)*mark / 100.0;
document.getElementById('percent' + mark).innerHTML =
a.toFixed(5-Math.round(Math.log10(a)));
});
If you want to create those html elements with code too you can simple have something like <div id="marks-container;></div> in your HTML and then add all paragraps with JS too -
const p = document.createElement('p');
p.id = "percent" + mark;
document.querySelector("#marks-container").appendChild(p);
Related
I'm attempting to use opencv.js to align images to a baseline image. I'm following some basic python guidance that i've seen work (example: https://alexanderpacha.com/2018/01/29/aligning-images-an-engineers-solution/)
but i'm getting tripped up with an error that I don't quite understand. The error is "opencv.js:30 Uncaught TypeError: Cannot use 'in' operator to search for 'type' in 1e-10" and it seems to be caused by the "criteria" variable passed to "cv.findTransformECC();" see here.
any guidance as to what I'm doing wrong here?
function Align_img(){
let image_baseline = cv.imread(imgElement_Baseline);
let image = cv.imread('imageChangeup');
let im1_gray = new cv.Mat();
let im2_gray = new cv.Mat();
let im2_aligned = new cv.Mat();
//get size of baseline image
width1 = image_baseline.cols;
height1 = image_baseline.rows;
//resize image to baseline image
let dim1 = new cv.Size(width1, height1);
cv.resize(image, image, dim1, cv.INTER_AREA);
// Convert images to grayscale
cv.cvtColor(image_baseline, im1_gray, cv.COLOR_BGR2GRAY);
cv.cvtColor(image, im2_gray, cv.COLOR_BGR2GRAY);
// Find size of image1
let dsize = new cv.Size(image_baseline.rows, image_baseline.cols);
// Define the motion model
warp_mode = cv.MOTION_HOMOGRAPHY;
// Define 3x3 matrix and initialize the matrix to identity
let warp_matrix = cv.Mat.eye(3, 3, cv.CV_8U);
// Specify the number of iterations.
number_of_iterations = 5000;
// Specify the threshold of the increment in the correlation coefficient between two iterations
termination_eps = 0.0000000001; //1e-10;
// Define termination criteria
criteria = (cv.TERM_CRITERIA_EPS | cv.TERM_CRITERIA_COUNT, number_of_iterations, termination_eps);
//Run the ECC algorithm. The results are stored in warp_matrix.
cv.findTransformECC(im1_gray, im2_gray, warp_matrix, warp_mode, criteria, null, 5);
// Use warpPerspective for Homography
cv.warpPerspective (image, im2_aligned, warp_matrix, dsize, cv.INTER_LINEAR + cv.WARP_INVERSE_MAP);
cv.imshow('imageChangeup', im2_aligned);
im1_gray.delete();
im2_gray.delete();
im2_aligned.delete();
};
UPDATE: 2 things. 1. Found easy fix to error (code below) and 2. looks like a bug in the findTransformECC opencv.js API causing this method not to work. Here is current code.
The API has 2 optional parameters (inputMask and gaussFiltSize) but if you don't include them you get an error ("function findTransformECC called with 5 arguments, expected 7 args!").
The issue is what to use for inputMask - "null" does not work, there doesn't seem to be support for 'cv.noArray()' and I can't find a mask that doesn't lead to a 'uncaught exception' error.
I'll update again once I find a workaround. Let me know if anyone sees a work around.
function Align_img(){
let image_baseline = cv.imread(imgElement_Baseline);
let image = cv.imread('imageChangeup');
let im1_gray = new cv.Mat();
let im2_gray = new cv.Mat();
let im2_aligned = new cv.Mat();
//get size of baseline image
var width1 = image_baseline.cols;
var height1 = image_baseline.rows;
//resize image to baseline image
let dim1 = new cv.Size(width1, height1);
cv.resize(image, image, dim1, cv.INTER_AREA);
// Convert images to grayscale
cv.cvtColor(image_baseline, im1_gray, cv.COLOR_BGR2GRAY);
cv.cvtColor(image, im2_gray, cv.COLOR_BGR2GRAY);
// Find size of image1
let dsize = new cv.Size(image_baseline.rows, image_baseline.cols);
// Define the motion model
const warp_mode = cv.MOTION_HOMOGRAPHY;
// Define 3x3 matrix and initialize the matrix to identity
let warp_matrix = cv.Mat.eye(3, 3, cv.CV_8U);
// Specify the number of iterations.
const number_of_iterations = 5000;
// Specify the threshold of the increment in the correlation coefficient between two iterations
const termination_eps = 0.0000000001; //1e-10;
// Define termination criteria
//const criteria = (cv.TERM_CRITERIA_EPS | cv.TERM_CRITERIA_COUNT, number_of_iterations, termination_eps);
let criteria = new cv.TermCriteria(cv.TERM_CRITERIA_EPS | cv.TERM_CRITERIA_COUNT, number_of_iterations, termination_eps);
//Run the ECC algorithm. The results are stored in warp_matrix.
//let inputMask = new cv.Mat.ones(im1_gray.size(), cv.CV_8U); //uint8
cv.findTransformECC(im1_gray, im2_gray, warp_matrix, warp_mode, criteria, null, 5);
// Use warpPerspective for Homography
cv.warpPerspective (image, im2_aligned, warp_matrix, dsize, cv.INTER_LINEAR + cv.WARP_INVERSE_MAP);
getMatStats(im2_aligned, 1); //0 = baseline (srcMat), 1 = image (srcMat_compare)
cv.imshow('imageChangeup', im2_aligned);
im1_gray.delete();
im2_gray.delete();
im2_aligned.delete();
};
UPDATE 2 I verified code works fine in Python. code below. The issue at hand now is simply, how do you this in Javascript: "inputMask=None"
Python:
# Read the images to be aligned
im1 = cv2.imread(r"C:\temp\tcoin\69.jpg");
im2 = cv2.imread(r"C:\temp\tcoin\pic96_crop.jpg");
#resize image to compare
width1 = int(im1.shape[1])
height1 = int(im1.shape[0])
dim1 = (width1, height1)
im2 = cv2.resize(im2, dim1, interpolation = cv2.INTER_AREA)
# Convert images to grayscale
im1_gray = cv2.cvtColor(im1,cv2.COLOR_BGR2GRAY)
im2_gray = cv2.cvtColor(im2,cv2.COLOR_BGR2GRAY)
# Find size of image1
sz = im1.shape
# Define the motion model
warp_mode = cv2.MOTION_HOMOGRAPHY
# Define 2x3 or 3x3 matrices and initialize the matrix to identity
warp_matrix = np.eye(3, 3, dtype=np.float32)
# Specify the number of iterations.
number_of_iterations = 5000;
# Specify the threshold of the increment
# in the correlation coefficient between two iterations
termination_eps = 1e-10;
# Define termination criteria
criteria = (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, number_of_iterations, termination_eps)
# Run the ECC algorithm. The results are stored in warp_matrix.
(cc, warp_matrix) = cv2.findTransformECC (im1_gray,im2_gray,warp_matrix, warp_mode, criteria, inputMask=None, gaussFiltSize=1)
# Use warpPerspective for Homography
im2_aligned = cv2.warpPerspective (im2, warp_matrix, (sz[1],sz[0]), flags=cv2.INTER_LINEAR + cv2.WARP_INVERSE_MAP)
# Show final results
cv2.imshow("Aligned Image 2", im2_aligned)
cv2.imwrite(r"c:\temp\tcoin\output\pic96_cropB.jpg", im2_aligned)
cv2.waitKey(0)
I have an svg image that I want to duplicate n number of times on the screen. Each time I want to change its position (x and y). For example, I would like to use one svg to create a 3x3 square of the duplicated svg.
How can this be achieved?
I figured it out and what I did was
const duplicateHtml = (element, quantity) => {
const html = new Array(quantity)
.fill('')
.map(() => {
return element.innerHTML;
})
// joing all the elements and returning a string
.join('');
return (element.innerHTML = html);
};
duplicateHtml(document.querySelector('.svg-images'),3);
I took example source from this link.
My data looks like this:
var data = [{ known_technologies : ["prepaid billing", " postpaid billing"],company : "A",YearsOfExp:0},
{ known_technologies : ["prepaid billing", " postpaid billing"],company:"B",YearsOfExp:1}];
My dimensions:
var ndx = crossfilter(data);
var yearDim2 = ndx.dimension(function(d)
{
return [d.known_technologies,d.company];
});
var spendPerYear2 = yearDim2.group();
I got something like below:
But I wanted in below way:
jsfiddle here
How do I make the dimensions. Any suggestions? Thanks in advance.
If you want to render two different sunbursts you need two different elements to grab on your html page. You can control the inner and out rings by changing the order of the dimensions in the array you are returning in the year2 dimension. Create appropriate groups, select both items from the DOM and create your charts as in the jsfiddle. Don't forget to call dc.renderAll() so you actually create the charts.
const ndx = crossfilter(data);
const yearDimX = ndx.dimension(function(d){
return [d.company, d.known_technologies];
});
const yearDimY = ndx.dimension(function(d){
return [d.known_technologies,d.company];
});
const spendPerYearX = yearDimX.group();
const spendPerYearY = yearDimY.group();
I create some lines in my Paper:
var svg = Snap("#svg_container");
var linesContainer = {};
var line = svg.line( 0, 0, 200, 200).attr(...);
linesContainer[someID] = line;
then i clear the Snap / create a new. I want to have the stored object also in my new snap:
svg = Snap("#svg_container");
svg.clear();
//something like:
//svg.append(linesContainer[someID]);
is this possible?
Here script with using SnapSVG.
var linesContainer = []; // not {}
lineContainer[linesContainer.length] = svg.line( 0, 0, 200, 200).attr(...);
// or 2nd way .. u can definitely make objects with value x,y, attrs and store them, but it helps reducing a storage of using memory.
U can put line to svg like that.
svg = Snap("#svg_container");
svg.clear();
for(i=0;i<lineContainer.length;i++)
svg.add(lineContainer[i]);
In raphael, if I want to render the following shape:
I have to do something like:
var paper = Raphael("notepad", 320, 200);
var rect = paper.rect(...);
var line1 = paper.path(...);
var line2 = paper.path(...);
which create three elements: rect, line1, line2.
BUT, I would like to treat the rendered shape as one object in other js code insteand of three. In Raphael, how can I create this shape which returns me just one object not three?
You want to create a set.
Creates array-like object to keep and operate couple of elements at once. Warning: it doesn't create any elements for itself in the page.
var st = paper.set();
st.push(
paper.circle(10, 10, 5),
paper.circle(30, 10, 5)
);
st.attr({fill: "red"});
Your code would look something like this:
var paper = Raphael("notepad", 320, 200),
st = paper.set();
st.push(
paper.rect(...),
paper.path(...),
paper.path(...)
);
// use st elsewhere
Edit
How can I access individual element in the set then?
You can grab references to the objects before you add them to the set:
var paper = Raphael("notepad", 320, 200),
st = paper.set(),
rect1 = paper.rect(...),
path1 = paper.path(...),
path2 = paper.path(...);
st.push(rect1, path1, path2);
I'm not 100% sure, but since the docs say that a set is "array-like," then you should also be able to access elements in the set using array index notation:
var i, elt;
for (i=0; i<st.length; i++)
{
elt = st[i];
// do stuff with elt
}