I'm working on simple genetics program involving theoretical flowers. For color assignment I'm using a simplified Punnett Square created thusly,
var momDom = mommaFlower.ColorOne;
var momRec = mommaFlower.ColorTwo;
var dadDom = papaFlower.ColorOne;
var dadRec = papaFlower.ColorTwo;
var punnet = [
[0,0],
[0,0],
];
punnet[0][0] = [momDom, dadDom];
punnet[0][1] = [momDom, dadRec];
punnet[1][0] = [momRec, dadDom];
punnet[1][1] = [momRec, dadRec];
return punnet[Math.floor(Math.random() * 2)][Math.floor(Math.random() * 2)];
so there is a relatively equal chance of any of the four color combinations for the child.
My trouble lies in translating this to Java, namely the destructuring assignment. What I have so far is
//getDomColor() = {255, 187, 187, 1.0}
float[][][][] punnet = {
{
{m.getDomColor(), f.getDomColor()},
{m.getDomColor(), f.getRecColor()}
},{
{m.getRecColor(), f.getDomColor()},
{m.getRecColor(), f.getRecColor()}
}
};
where the return on getDomColor, and getRecColor is a float array of rgb values. I had hoped it would be just as simple as JS's way, but I've since found out that Java does not have destructuring assignment. My question is, what would be the best way to translate my JS Punnett Square into Java, considering what I have so far.
Related
I found an interesting demo of how to find the largest rectangle in an irregular shaped polygon here using D3plus.
I'm trying to recreate this for a polygon I'm working on but currently the code is not working. It seems to runs endlessly. The code I'm using is as follows:
d3.csv("data/polyPoints.csv", function(error, polyPoints) {
if (error) return console.error(error);
// coerce string values to numbers
polyPoints.forEach(function(d) {
d3.keys(d).forEach(function(k) {
d[k] = +d[k]
})
});
// settings for geom.largestRect
var rectOptions = {
angle: 0,
maxAspectRatio: 5,
nTries: 1
};
console.log(rectOptions);
console.log(polyPoints);
var lRect = d3plus.geom.largestRect(polyPoints, rectOptions);
console.log(lRect);
});
I suspect my polygon is not in the correct format.
Update
I'm making progress. My original polygon object was taken from a csv and created an array of arrays of key value pairs (e.g. {"x": 0 "y": 1},{"x": 2, "y": 1}....)
I converted this to an array of arrays (e.g. [[1,0],[2,0]....])
Now the code is running but the output is defining rectangles that cross the boundary of the original polygon.
For anyone working with this. The largestRect docs are https://d3plus.org/docs/#largestRect and can be run with the following code.
const d3p = require('d3plus');
const polygon = [[x,y],[x,y],[x,y]...]
const rectOptions = {
maxAspectRatio: 5,
nTries: 20
};
let lRect = d3p.largestRect(rdp, rectOptions);
The algorithm used is an approximation and random points inside the polygon are chosen to do calculations from. Because of this the edges of the box won't always be touching the edge but should be "close enough".
The options.tolerance value might affect this as well but I haven't played around with it much. This is a pretty old question but hopefully it helps someone.
Im trying to create a convex hull with opencv.js based on an array with points, does anyone know a way to do this correctly and efficient? An array would look like this:
[
[5,5],
[10,10],
[15,15]
...
]
-> where the first value would be the x and the second the y value, but it wouldn't be a problem to change this format to something more suitable.
Thnx for the help :)
As far I could experiment OpenCV stores contour/hull data in Mat format with type CV_32SC2: essentially a flat list of 32bit short integers in [x1,y1,x2,y2,x3,y3,...] order.
Note the two channels/planes part of 32SC2: one channel for all the x values and another for all the y values
You can manually create such a Mat, access it's data32S property and fill in each value:
let testHull = cv.Mat.ones(4, 1, cv.CV_32SC2);
testHull.data32S[0] = 100;
testHull.data32S[1] = 100;
testHull.data32S[2] = 200;
testHull.data32S[3] = 100;
testHull.data32S[4] = 200;
testHull.data32S[5] = 200;
testHull.data32S[6] = 100;
testHull.data32S[7] = 200;
However OpenCV.js comes with a handy method to convert a flat array of values to such a Mat:
let testHull = cv.matFromArray(4, 1, cv.CV_32SC2, [100,100,200,100,200,200,100,200])
If your array is nested, you can simply use JS Array's flat() method to flatten it from a 2D array([[x1,y1]...]) to a 1D array ([x1,y1,...]).
So you don't have to worry about the Mat type and all that you can wrap it all into a nice function, for example:
function nestedPointsArrayToMat(points){
return cv.matFromArray(points.length, 1, cv.CV_32SC2, points.flat());
}
Here's a quick demo:
function onOpenCvReady(){
cv.then(test);
}
function nestedPointsArrayToMat(points){
return cv.matFromArray(points.length, 1, cv.CV_32SC2, points.flat());
}
function test(cv){
console.log("cv loaded");
// make a Mat to draw into
let mainMat = cv.Mat.zeros(30, 30, cv.CV_8UC3);
// make a fake hull
let points = [
[ 5, 5],
[25, 5],
[25,25],
[ 5,25]
]
let hull = nestedPointsArrayToMat(points);
console.log("hull data", hull.data32S);
// make a fake hulls vector
let hulls = new cv.MatVector();
// add the recently created hull
hulls.push_back(hull);
// test drawing it
cv.drawContours(mainMat, hulls, 0, [192,64,0,0], -1, 8);
// output to canvas
cv.imshow('canvasOutput', mainMat);
}
<script async src="https://docs.opencv.org/4.4.0/opencv.js" onload="onOpenCvReady();" type="text/javascript"></script>
<canvas id="canvasOutput" width="30" height="30"></canvas>
Note that the above is a rough example, there's no data validation or any other fancier checks, but hopefully it illustrates the idea so it can be extended robustly as required.
Lets say that your points represent a contour:
var contours = new cv.MatVector();
for (var i = 0; i < points.size(); ++i) {
contours.push_back(new cv.Mat(points[i][0], points[i][1])
}
Now following this tutorial from opencv website:
// approximates each contour to convex hull
for (var i = 0; i < contours.size(); ++i) {
var tmp = new cv.Mat();
var cnt = contours.get(i);
// You can try more different parameters
cv.convexHull(cnt, tmp, false, true);
hull.push_back(tmp);
cnt.delete(); tmp.delete();
}
I'm using a JS Library called Javascript Clipper for polygon operation. As stated from the manual, the coordinate format of an input path is like the follows,
var paths = [[{X:30,Y:30},{X:130,Y:30},{X:130,Y:130},{X:30,Y:130}],
[{X:60,Y:60},{X:60,Y:100},{X:100,Y:100},{X:100,Y:60}]];
My question is, how to convert a regular JS array, say
var x = [40, 100, 1, 5, 25, 10] and var y= [22, 32, 11, 45, 75, 19] to the required format shown above? The actual case is, these coordinate points will not be typed manually, but obtained from another function, the output of which is not in the format required by the Javascript Clipper Library.
Something like this:
function makePath(xVals, yVals) {
var pathArray = [];
xVals.forEach(function(xVal, index) {
var yVal = yVals[index];
var coordObj = {xVal, yVal};
pathArray.push(coordObj);
})
return pathArray;
}
You can pass it your arrays, x and y, as makePath(x,y) to get the combined array out.
My method assumes that the lengths of the arrays x and y are the same.
I am Currently Trying to work with JavaScript in a cleaner object orientated way, So Please excuse me if I'm doing this entirely incorrectly I am using this previous questions answer as a general reference, but Here's my 'test' code:
//Create some sample objects to play with.
var testJSON = {
"rectangle": [
{ "id":3 , "x":5, "y":10, "width":10, "height":50
}
]
};
//Create Rectangle Constructor
var rectangle = {
init: function( i, x, y, width, height ) {
this.id = i,
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.fields = []
},
move: function( x, y ) {
this.x += x;
this.y += y;
}
};
//Create test array to hold all the objects
var test = [];
//Create a new rectangle object
var myRectangle = Object.create( rectangle );
myRectangle.init( 1, 0, 0, 2, 4 );
myRectangle.move( 3, 5 );
//put rectangle object in array associated with id
test[myRectangle.id] = myRectangle;
//Create a new rectangle object with the same variable name as it will all be in an array anyway.
var myRectangle = Object.create( rectangle );
myRectangle.init( 2, 0, 0, 2, 4 );
myRectangle.move( 0, 0 );
//put rectangle object in array associated with id
test[myRectangle.id] = myRectangle;
//put JSON result in
test[testJSON.rectangle[0].id] = testJSON.rectangle[0];
//No Longer need this variable, is it worth getting rid of.. i dont know
myRectangle =null;
//Try and use methods created in the constructor.
test[2].move(4,8);
console.log(test);
Okay, Now the actual questions, The Application I am trying to create, has both json data and it will have users that create data, so for example: the application will generate a bunch of 'rectangles' and then the user can also create rectangles.
So the first question would be, 'Is this the correct approach' and then secondly how would i get the json data to also have the method defined in the rectangle constructor (move)?
Any Help Greatly Appreciated.
This an extension of what #Marc B and #Ray Toal mentioned...
You have created javascript functions - which is not at all that bad - but not JSON. To create graphics, you could use the canvas tag as, in effect, a "drawing div" and use the object's x and y positions to constantly update them - if you were considering doing 2d animation. If so, I would recommend CreateJs as a starting block before hard-coding JAVASCRIPT animations. Again, you're code is just fine, but having users create this data - if you were considering a server application would involve using real JSON or perhaps Node.js - but for now I'd focus on single player aspect and setting up you're objects on a graphical 'interface' like <canvas>
Is there a recommended way to extend classes in Paper.js? In particular, I am interested in extending Path
Pardon if my terminology is incorrect, but I am essentailly asking the same question about paper that is being asked about three here
Based on your comment to the initial version of my answer, you are looking for the 'extend' function (oops, that was exactly what you meant) to do subclassing. In an email to the paper.js mailing list, Jürg Lehni (one of the creators) said:
As for subclassing, that's not something that is supported at the
moment. It might work, it might not, it might work in most cases, but
not in very rare cases that are hard to pinpoint, it might need only a
couple of changes to make it work well, but those might be in many
different places.
For example, each Item subclass has a _type property which is a string
representing its type. Sometimes we check that instead of using
instanceof, because it's faster, and so far, for example for Path we
just assumed there would be no subclassing.
A complication is that there are no paper.Path.Rectangle objects. There are paths, and there are rectangles, but when you call new paper.Path.Rectangle() it creates a new Path using initialization code (createRectangle) that creates a rectangular shape.
So we would need to extend paper.Path. Unfortunately, when you call new paper.Path.Rectangle it calls createPath, which always returns a Path (not your extension). It may be possible to do something like:
var SuperRectangle = paper.Path.extend({
otherFunc: function() {
console.log('dat');
}
});
...and with correctly substituting/overriding for createRectangle or createPath get a subclass to work. Unfortunately, I have not been able to manage it.
My first working recommendation is to make a factory and add your functions to the objects in that factory (jsbin here):
var createSuperRectangle = function(arguments){
var superRect = new paper.Path.Rectangle(arguments);
superRect.otherFunc = function(){
console.log('dat');
}
return superRect;
}
var aRect = new Rectangle(20, 30, 10, 15);
var aPath = createSuperRectangle({
rectangle: aRect,
strokeColor: 'black'
});
aPath.otherFunc();
Similarly, you can use the factory to just change the prototype for your SuperRectangles, having added your functions to that prototype object (and making its prototype the one from paper.Path.__proto__) (jsbin here):
var superRectProto = function(){};
var tempRect = new paper.Path.Rectangle();
tempRect.remove();
superRectProto.__proto__ = tempRect.__proto__;
superRectProto.otherFunc = function(){
console.log('dat');
}
delete tempRect;
var createSuperRectangle = function(arguments){
var superRect = new paper.Path.Rectangle(arguments);
superRect.__proto__ = superRectProto;
return superRect;
}
var aRect = new Rectangle(20, 30, 10, 15);
var aPath = createSuperRectangle({
rectangle: aRect,
strokeColor: 'black'
});
aPath.otherFunc();
Alternatively, you can make an object that encapsulates the Path (jsbin here):
var SuperRectangle = function(arguments){
this.theRect = new paper.Path.Rectangle(arguments);
this.otherFunc = function(){
console.log('dat');
}
}
var aRect = new Rectangle(20, 30, 10, 15);
var aPath = new SuperRectangle({
rectangle: aRect,
strokeColor: 'black'
});
aPath.otherFunc();
aPath.theRect.strokeWidth = 5;
Unfortunately, then to access the path you have to use the theRect variable.
Initial incorrect answer follows:
I don't think you mean "extending classes". In Javascript you can extend objects so that they have more functions, so extending the Path "class" would mean all Path objects have the same new functions. Javascript object extension is further described here.
If I'm wrong, and you do want to extend Path, then you can use:
paper.Path.inject({
yourFunctionName: function(anyArgumentsHere) {
// your function here
}
});
However, I think you are actually talking about creating new objects that mostly behave like Path objects but have different functionality from each other. If that is the case, then you may want to look at this answer about Javascript using prototypical inheritance. For example, here I create two Rectangle objects that behave differently when I ask them to doSomething (jsbin here):
var rect1 = new Path.Rectangle({
point: [0, 10],
size: [100, 100],
strokeColor: 'black'
});
rect1.doSomething = function() {
this.fillColor = new Color('red');
};
var rect2 = new Path.Rectangle({
point: [150, 10],
size: [100, 100],
strokeColor: 'black'
});
rect2.doSomething = function() {
this.strokeWidth *= 10;
};
rect1.doSomething();
rect2.doSomething();
A couple of things.
1) You can wrap the original paperjs object but this is very much a hack
paperjs playground
function SuperSquare() {
this.square = new Path.Rectangle({
size:50,
fillColor:'red',
onFrame:function(base) {
var w2 = paper.view.element.width / 2;
this.position.x = Math.sin(base.time) * w2 + w2;
}
});
}
SuperSquare.prototype.setFillColor = function(str) {
this.square.fillColor = str;
}
var ss = new SuperSquare();
ss.setFillColor('blue');
2) I may clone & create a paper 2017 which operates off of es6 so that you can use the extend keyword.
3) I wrote an application called Flavas but it never gained a following so I just kind of left it. That being said, I have been playing with it lately; upgrading it to es6. With it you can do what you're talking about.
class Square extends com.flanvas.display.DisplayObject {
constructor(size) {
this.graphics.moveTo(this.x, this.y);
this.graphics.lineTo(this.x + size, this.y);
this.graphics.lineTo(this.x + size, this.y + size);
this.graphics.lineTo(this.x, this.y + size);
}
someMethod(param) {
trace("do something else", param);
}
);
I wrote all this kind of quick so feel free to hit me up with Q's.