osgText with getBound() - openscenegraph

Is it possible to do a getBound() on osgText without setting its position before that i.e.
osg::ref_ptr<osgText::Text> label = new osgText::Text;
geode->addDrawable( label.get() );
label->setText("Event:
dist = label->getBound().xMax();
and somewhere later after deciding on the position i would do this
label->setPosition(pos);
The problem i am facing right now is that getBound() seems to return diff values with GL and GLES builds.

Since you haven't set the bounding volume OSG will return the default BoundingBox parameters (xmax, xmin, etc). The default BoundingBox will depend on your GL build.
Ideally getBound() will return the bounds of nodes once you set them.

Related

is the area of a contour comprising the holes that are inside or not?

As in the question, I computed the contours of each object in an image, using the findContours() function and specifing the RETR_CCOMP hierarchy.
If I compute the area of a parent contour, using the function contourArea(), is opencv considering the whole area comprising all the holes or is it automatically removing the childs contours areas?
I'm asking this in order to be able to remove the area of the holes, after having retrieved the areas of the objects and the holes, if any hole exists.
This is part of the (working) code:
[...]
_, contours0, hierarchy = cv.findContours(thresholded.copy(), cv.RETR_CCOMP, cv.CHAIN_APPROX_SIMPLE)
contours = [cv.approxPolyDP(cnt, 3, True) for cnt in contours0]
for cntIndex in range(0, len(hierarchy[0])):
#if the current contour has no parent
if(hierarchy[0, cntIndex][3]==-1):
#then, it is a parent contour and
#compute its bounding box
boundingBox = cv.contourArea(cnt)
[...]
#otherwise, if it has a parent it must be a child
else:
#which means we found a GAP
gap = contours[cntIndex]
boundingBox = cv.contourArea(cnt)
[...]
Of course I'm storing the gaps and the objects areas in two variables which, for now, are subtracted in order to get the exact surface covered by the object. Is this the right approach? I think it is, but I need to be 100% sure and I wasn't able to find this piece of information.

Flash CC Canvas and GSAP: How to set registration point of movieclip on stage

How would I go about changing the registration point of a movieclip labeled "tablet" placed on the stage (root) dynamically?
For example: I have the following:
var tablet = this.tablet; //movieclip labeled "tablet" on stage
function resetTablet(){
tablet.regX = tablet.width/2; //move registration point to center
tablet.regY = tablet.height/2;
}
However when I call it using GSAP:
var tl = new TimelineLite();
tl.to(tablet, 1, {alpha:1, onComplete:resetTablet})
.to(tablet, 3, {alpha:0, scaleX:1.5, scaleY:1.5})
the registration point is still set to the upper left corner rather than the center.
What am I doing wrong here? Thanks!
Registration points affect change both the transformation point, but also the position. If you set a displayobject that is 100x100 pixels to regX=50;regY=50, then it will draw from that point, moving the content 50px to the top and left. If you make that change you should also translate the clip to x=50;y=50.
An issue with you example is that there is no width or height on EaselJS content (explained here). You can get the bounds of anything generated by Flash CC using the nominalBounds property, which Flash exports as a property on every object. If you have multiple frames, you can turn on "multi-frame bounds" in the publish settings, and a frameBounds property is added to the objects as well.
Note that nominalBounds and frameBounds are not used by the getBounds method.
Here is how you might be able to approach it.
var bounds = tablet.nominalBounds;
tablet.regX = bounds.width/2;
tablet.regY = bounds.height/2;
// Optional if your actual registration point was [0,0] before:
tablet.x += tablet.regX;
tablet.y += tablet.regX;
Hope that helps.

Set the rotation of an object at its axis three js

I try to set the rotation of an object at it's own axis using:
object.rotateOnAxis(new THREE.Vector3(1,0,0) , Math.PI)
in the render function, but the object is rotating in every rendering. Is there a way to set the rotation at it's own axis like when using:
object.rotation.x = Math.PI
or
object.rotation.set(Math.PI,0,0)
to set the rotation at the world axis?
Just remove the following code from the render method.
object.rotateOnAxis(new THREE.Vector3(1,0,0) , Math.PI)
You could put it to the declaration of object. Surely, you could also set the rotation there (in render) but that would reduce the performance needlessly.
Simply put it outside the render function.
EDIT: You can simply use
object.rotation.x += rotationSpeed;
in the render method to let it rotate.
If the rotation must take place at the render function that means that the model is changing rotation at every render. Simply find the rotation difference and apply it to the model using the code mentioned:
object.rotateOnAxis(new THREE.Vector3(1,0,0) , Math.PI);
Store the old rotation and the new rotation at variables and apply the difference:
var old_rotation = value1;
var new_rotation = value2;
var Drotation = value1-value2;
if the difference is negative or positive it shows the direction of the rotation so just apply:
object.rotateOnAxis(new THREE.Vector3(1,0,0) , Drotation);
UPDATE:
The simplest way i found is:
object.rotateX(angle);
object.rotateY(angle);
object.rotateZ(angle);
this rotates the object around its axes :D

D3js: finding path's bounding box (without getBBox() )?

The following code works on Chromium :
var node = window.d3.selectAll('#L1 > *:nth-child(2)');
var bbox = node.node().getBBox();
console.log(bbox) // {height: 44, width: 44, y: -13, x: 144}
but not with nodejs + jsdom:
"TypeError: Object [ PATH ] has no method 'getBBox' "
M. Bostock pointed out that JSDOM doesn't support getBBox()
What D3js replacement to use to get the bounding box of #L1 > *:nth-child(2) ?
Past efforts lead me there : getBBox() based fiddle
Path's bounding box
Digging straight into the element's path data d="..." should work. An svg line is basically a set of x,y points. Assuming absolute coordinates without translation nor big bezier curves, which is the case of my D3js-generated svg lines, I'am finding in this data the min and max values for both x and y.
To do so, I get the d="..." svg line or multilines code. For simplicity sake, I rudely removes possible relative jumps such h30 or v20 since I never saw any in my D3js output, then clean out letters (aka svg commands : M,L,H,V,C,S,Q,T,A,Z), simplify the spaces and line jumps, then split by the remaining spaces. I get a clean arrays of coordinates.
Important to note, my selector directly target a single non-translated path.
var getBBox = function(selector){
var xmin, xmax, ymin, ymax,p;
// clean up path
var t = d3.select(selector).attr("d"); // get svg line's code
console.log(t)
t = t.replace(/[a-z].*/g," ") // remove relative coords, could rather tag it for later processing to absolute!
.replace(/[\sA-Z]+/gi," ").trim().split(" "); // remove letters and simplify spaces.
console.log(t)
for(var i in t){ // set valid initial values
if(t[i].length>1){
p = t[i].split(",");
xmin = xmax = p[0]; ymin = ymax = p[1]; }
}
for(var i in t){ // update xmin,xmax,ymin,ymax
p = t[i].split(",");
if(!p[1]){ p[0]=xmin; p[1] = ymin;} // ignore relative jumps such h20 v-10
xmin = Math.min(xmin, p[0]);
xmax = Math.max(xmax, p[0]);
ymin = Math.min(ymin, p[1]);
ymax = Math.max(ymax, p[1]);
} return [[xmin,ymax],[xmax,ymin]]; // [[left, bottom], [right, top]] as for https://github.com/mbostock/d3/wiki/Geo-Paths#bounds
}
var bb = getBBox("path");
JSfiddle DEMO
Groups bounding boxes
For groups of multiple paths, you may want to traverse the svg DOM to loop upon each single path of the group in order to update xmin, ymin, xmax, ymax.
Translated elements
To handle translated elements, adapt further.
Alternatives
Other better approaches may exist. Remember to check if getBBox() and getBoundingClientRect() are available in your context, since they are native and very convenient.
The reason why getBBox/getBoundingClientRect/getClientRect does not work in NodeJS+JSDOM is that calculating these values of an SVG (or HTML) element involves massive amounts of computation.
First, all CSS code in <style> elements must be parsed (which is already not trivial). Then the CSS selectors, cascading and inheritance rules must be applied to know what size, position or line width an element has. And even after you know all style property values, you need to do some non-trivial maths to calculate the bounding boxes: definition of different SVG transform functions, compositions of these, bounding boxes of SVG primitives and Bezier curves. Browsers support all of these (they have to, in order to draw the element), but JSDOM is simply not meant for all of these.
But fortunately, canvg is a JavaScript implementation of most of SVG, which uses a <canvas> element to draw the image. It does support most of the above, and although it does not have an interface for giving you those data, fortunately it has very nice (and MIT licensed) code, so hopefully you can copy and reuse parts of it. As of now, the code is written in a single file, and it has CSS parsing, applying cascading rules, path data parsing, definitions of SVG transforms, applying transformations, and bezier curve bounding box calculation. That is, almost everything you need to calculate bounding boxes :) It does not, however, support CSS selectors, but it can reuse another library. But unfortunately, as far as I can tell, canvg is not ready for running in NodeJS, you probably need some tweaks.
There is, however canvgc, an SVG to JS compiler, which contains an older version of canvg, and it is capable of running in NodeJS. So it is easier to start with that.

Raphael - Transform after Serialization

I am using Raphael to draw some paths. Each path has an associated rectangle [container] the size and position of the bounding box. I am using the container for dragging both shapes.
In the move callback, I update the both positions so they both move together.
This all works great until I serialize. I am only serializing the path, then creating the container on the fly after deserialization.
Immediately after converting to json and back, things look fine. I can print out the current transform of the path and it looks correct. Doing any transform on the path after this results in the path being reset and moved to 0,0.
Here is a fiddle that shows the problem.
If you move the rect, you can see both objects move together.
If you click 'Save/Load', things look fine, and the path prints the same.
If you now drag, the path gets reset to 0,0. Printing shows the transform has been reset from 0,0.
I am trying to find out how to make the path move as it did before serialization. Is something getting lost in the process? Or is there an internal state that needs to be updated?
Raphael.JSON serialises data stored in the elements. It does not preserve temporary data stored in the paper object so something does indeed get lost in the process when calling R.clear(). For example drag events bound to elements are not preserved.
However the main issue here is with your drag function, notice how dragging the square a second time applies the transformation from the top left of the paper. I suggest using Raphael.FreeTransform (which you already included in the Fiddle) to handle this.
I wrote both Raphael.JSON and Raphael.FreeTransform plugins and have struggled with the same issues. I'm currently working on an application that lets you save save and restore the state of the paper (similar to what you're doing) and it works fine. If you need any help feel free to open an issue on Github.
You need to capture the initial transform offsets of your elements when the drag starts and use those as the basis for your drag-move transforms. Consider the following:
var start_x, start_y;
cont.drag(function(x, y, e)
{
p.transform('t' + ( start_x + x ) + ',' + ( start_y + y ) );
cont.transform('t' + ( start_x + x ) + ',' + ( start_y + y ) );
},
function( x, y )
{
var start_bbox = p.getBBox();
start_x = start_bbox.x;
start_y = start_bbox.y;
console.log("Drag start at %s,%s", start_x, start_y );
} );
I've staged this in a fiddle located here.
Unfortunately, there is still an issue with the path -- it's offset is being incremented by the difference between it's bounding box y value and the y axis (a difference of 12, to be precise) each time drag is used. I'm not sure where that's coming from exactly.

Resources