I have a big issue, but I don't know how to solve it.
I have a json file, which contains elements and their positions in a grid.
All elements possible have childrens, and the childrens are re-indexed from zero (0,0).
I need to convert relative positions to 'absolute' position.
An example json file:
{
label: 'item 1',
position: {x: 0, y: 0},
childrens: [
{
label: 'item 1 children 1'
position: {x: 1, y: 0}
},
{
label: 'item 1 children 2',
position: {x: 2, y: 0}
}
]
},
{
label: 'item 2',
position: {x: 1, y: 0},
childrens: [
{
label: 'item 2 children 1',
position : {x: 0, y: 2}
}
]
}
Keep an absolute offset.
Start with offset (0,0) for the root node. Then when you reach a child compute the absolute coordinates for the top-left corner and call the recursive function with the computed coordinates as the new absolute offset.
For regular items add the absolute offset to the item coordinates to get the absolute coordinates.
In your example, you start with offset (0,0). Then you reach the child rectangle. You compute that the top-left corner should be at position (2,0) and send that as the offset into the recursive call. When you reach the first block inside the child you compute the absolute coordinates as child relative coordinates: (0,0) + absolute coordinate: (2,0) to get (2,0).
Related
I rotate a node (with a green image sprite for easy viewing) containing child nodes (called Dot, with red color, collider2D and rigidbody2D). I change the Rotation property and all Dots also change. I want to do so in code, however only the blue part rotates.
I rotated both ways:
tween(new Vec3(0, 0, 0))
.to(3, new Vec3(0, 0, 360), {
easing: "cubicIn",
onUpdate(target?: any) {
wheelDot.eulerAngles = target;
},
})
.start();
and
tween(this.wheelDot)
.to(
3,
{
angle: this.wheelDot.angle + 360,
},
{
easing: "cubicIn",
}
)
.start();
Both of the above codes just rotate the green part and the red dots stay in place.
Edit: I found out if I dropped RigidBody2D, the red dots moved. How can I still use RigidBody2D and still rotate?
I have an application using the Forge Viewer displaying converted ACAD dwg files. The short description is that I need to take specific polylines out of the dwg file source and use the Edit2D extension to draw them as polygons over the background. I have this working, but arcs are causing some issues right now. This doesn't have to be perfect but it should be decently the same shape. In most cases it is just drawing a line from the start to the end of the arc (and I understand why, see code below) but in other cases it's significantly segmenting the arc and I'm not sure why.
I start by finding the id's of the polylines based on their layer and then getting the fragment ids (this is working fine). Then I get the vertexes for the polyline like this:
export function getVertexesById(
viewer: Autodesk.Viewing.GuiViewer3D,
frags: Autodesk.Viewing.Private.FragmentList,
fragIds: number[],
dbId: number
): Point[] {
// We need to also get the center points of arcs as lines seem to be drawn to them in the callbacks for some
// reason. Center points should later be removed from the point array, so we don't get strange spikes on our shapes.
const polyPoints: Point[] = [];
const centers: Point[] = [];
fragIds.forEach((fid) => {
const mesh = frags.getVizmesh(fid);
const vbr = new Autodesk.Viewing.Private.VertexBufferReader(
mesh.geometry,
viewer.impl.use2dInstancing
);
vbr.enumGeomsForObject(dbId, {
onLineSegment(
x1: number,
y1: number,
x2: number,
y2: number,
_vpId: number
) {
checkAddPoint(polyPoints, { x: x1, y: y1, z: 0 });
checkAddPoint(polyPoints, { x: x2, y: y2, z: 0 });
},
onCircularArc: function (cx, cy, start, end, radius, _vpId) {
centers.push({ x: cx, y: cy, z: 0 });
},
onEllipticalArc: function (
cx,
cy,
start,
end,
major,
minor,
tilt,
_vpId
) {
centers.push({ x: cx, y: cy, z: 0 });
},
onOneTriangle: function (x1, y1, x2, y2, x3, y3, _vpId) {
checkAddPoint(polyPoints, { x: x1, y: y1, z: 0 });
checkAddPoint(polyPoints, { x: x2, y: y2, z: 0 });
checkAddPoint(polyPoints, { x: x3, y: y3, z: 0 });
},
onTexQuad: function (cx, cy, width, height, rotation, _vpId) {
centers.push({ x: cx, y: cy, z: 0 });
},
});
});
centers.forEach((c) => {
checkRemovePoint(polyPoints, { x: c.x, y: c.y, z: 0 });
});
return polyPoints;
}
The functions checkAddPoint and checkRemovePoint are just helper functions that make sure we don't duplicate points and take into account rounding (so we don't get two points that are say 0,0,0 and 0,0.00001,0.
I then use those points to draw with the Edit2D extension. So what I would expect here is that it creates a series of points that would draw along all the straight lines of the polyline and when it gets to an arc it just draws from one endpoint to the other. That is mostly what I see.
Here is an example file as it looks in ACAD:
Notice there are a handful of breaks in the arc around the outside of the room. What I get when I do the above process is this:
Notice all along the top I get what I would expect. However, along the bottom in 2 places I get a huge number of segments all along the line.
I looked back at the ACAD file and exploded the polyline and looked at it as much as I know how and I can't find anything different about those two segments vs. the other that would indicate why it acts differently.
What would be really awesome is if there is an easy way to just segment along an arc say every x units and have it return that but I'm not expecting that here, I just want to know why it is treating these differently.
Any help is greatly appreciated.
Edit
I should also mention that I have logged the creation routine and the only things in this that are ever hit are the onLineSegment and onCircularArc. As you see, the circular arc one only checks to make sure we don't have the center point in the list, so all of these extra points are for some reason being read in the line segment section.
I am trying to understand the Google Slides API Rotate function.
3000000 is the Object width and Height.
If we wanted to rotate Rectangle 35 degrees Counter clockwise,
Trying to understand example parameters in documentation, and how to rotate https://developers.google.com/slides/samples/transform
What is -0.5 below and 0.3? How are they derived?
Additionally, what is -2000000 and -550000?
Last curious if there any shorthand method of doing this? Three requests for 15 lines, just to rotate a rectangle?
{
"requests": [
{
"updatePageElementTransform": {
"objectId": pageElementId,
"applyMode": "RELATIVE",
"transform": {
"scaleX": 1,
"scaleY": 1,
"translateX": -2000000 - 0.5 * 0.3 * 3000000,
"translateY": -550000 - 0.5 * 0.12 * 3000000,
"unit": "EMU"
}
}
},
{
"updatePageElementTransform": {
"objectId": pageElementId,
"applyMode": "RELATIVE",
"transform": {
"scaleX": cos(35 * (pi/180)),
"scaleY": cos(35 * (pi/180)),
"shearX": sin(35 * (pi/180)),
"shearY": -sin(35 * (pi/180)),
"unit": "EMU"
}
}
},
{
"updatePageElementTransform": {
"objectId": pageElementId,
"applyMode": "RELATIVE",
"transform": {
"scaleX": 1,
"scaleY": 1,
"translateX": 2000000 + 0.5 * 0.3 * 3000000,
"translateY": 550000 + 0.5 * 0.12 * 3000000,
"unit": "EMU"
}
}
}
]
}
By the way, just opened feature request for shorthand rotate, will try to figure it out for now https://issuetracker.google.com/u/2/issues/183986639
Answer:
When completing transformations on shapes in Slides, all operations are done from the frame of reference of the origin of the page. This point is the top-left point of the page.
More Information:
At the top of the page on Transform Operations, it states that the examples on the page assume the existence of a defined arrow shape:
For these examples, assume that there exists an example arrow shape page element with the following size and transform data (which can be found with a presentations.pages.get request):
{
"objectId": pageElementId,
"size": {
"width": {
"magnitude": 3000000,
"unit": "EMU"
},
"height": {
"magnitude": 3000000,
"unit": "EMU"
}
},
"transform": {
"scaleX": 0.3,
"scaleY": 0.12,
"shearX": 0,
"shearY": 0,
"translateX": 2000000,
"translateY": 550000,
"unit": "EMU"
},
"shape": {
"shapeType": "RIGHT_ARROW"
}
}
So to answer your first two questions:
The 0.3 is taken from the sclaing factor of the arrow.
The -2000000 and -550000 are used to translate the shape to the origin of the page
The -0.5 is used to halve the translation distance (as we are doing the rotation from the shape's centre rather than its vertex)
Also, from the documentation on Sizing and Positioning Page Elements (emphasis my own):
Rotation transforms rotate a page element around a point, using the scaling and shear parameters. The basic rotation transform matrix has the following form, where the angle of rotation (in radians) is measured from the X-axis, moving counterclockwise:
As with scaling, you can use this matrix form directly as a RELATIVE transform to rotate an element, but this causes the element to be rotated about the origin of the page. To rotate the element about its center or a different point, shift to that reference frame.
So simple answer: yes you can do it in one request, but you will have to do the calculations for shifting to the element's reference frame yourself and send that request to the API instead.
References:
Transform Operations - Example arrow shape | Slides API | Google Developers
Sizing and Positioning Page Elements
Element references frames
I created a Cesium label, using the following code:
var label: Cesium.LabelGraphics = new Cesium.LabelGraphics({
text : lab,
verticalOrigin: Cesium.VerticalOrigin.TOP,
horizontalOrigin: Cesium.HorizontalOrigin.RIGHT,
font: '15px Helvetica',
fillColor: Cesium.Color.WHITE,
outlineWidth: 2,
style: Cesium.LabelStyle.FILL,
pixelOffset: new Cesium.Cartesian2(20, 20)
});
But it is blurred...
I would like to have a clearer label. Is this image you can see inside the red rectangle the real label. In the blue rectangle is the label with a zoom In. In the green rectangle is how I would like it to be.
Is there some way to make the label clearer?
Thanks!
In Bllboard.js or Cesium.js change
gl_Position = czm_viewportOrthographic * vec4(positionWC.xy,-positionWC.z, 1.0);
to
gl_Position = czm_viewportOrthographic * vec4(floor(positionWC.xy + 0.5), -positionWC.z, 1.0);
It will makethe billboards snap to a pixel, instead of get blurred.
also disable the FXAA (antialias) in your viewer initialization
viewer.scene.fxaa = false
it will make the billboards and labels much more crispy !
Before
.
After
A trick I sometimes use is to combine a larger font size with a scale setting on the label to scale the large font down using WebGL. This is a slightly different scaling than simply picking a smaller font size, because WebGL's texture scaling system comes into play to scale the rasterized font images. This works because Cesium labels are not anchored to an integer pixel position, they can be placed at coordinates with sub-pixel precision. So, the extra resolution in the label texture comes in handy as the label moves around. Of course this method costs a little bit more texture memory, but is usually worth it to get the cleaner edges.
Here's an example, showing the difference between normal (no scaling), double (0.5 scaling), and triple (roughly, 0.3 scaling).
var viewer = new Cesium.Viewer('cesiumContainer', {
navigationHelpButton: false, animation: false, timeline: false
});
viewer.entities.add({
position : Cesium.Cartesian3.fromDegrees(-75.1641667, 39.9522222),
label : {
text : 'Label == || normal',
verticalOrigin: Cesium.VerticalOrigin.TOP,
horizontalOrigin: Cesium.HorizontalOrigin.RIGHT,
font: '15px Helvetica', // NOTE: Standard size, no scaling here.
fillColor: Cesium.Color.WHITE,
outlineWidth: 2,
style: Cesium.LabelStyle.FILL,
pixelOffset: new Cesium.Cartesian2(20, -10)
}
});
viewer.entities.add({
position : Cesium.Cartesian3.fromDegrees(-75.1641667, 39.9522222),
label : {
text : 'Label == || double',
verticalOrigin: Cesium.VerticalOrigin.TOP,
horizontalOrigin: Cesium.HorizontalOrigin.RIGHT,
font: '31px Helvetica',
fillColor: Cesium.Color.WHITE,
outlineWidth: 2,
style: Cesium.LabelStyle.FILL,
pixelOffset: new Cesium.Cartesian2(20, 20),
scale: 0.5
}
});
viewer.entities.add({
position : Cesium.Cartesian3.fromDegrees(-75.1641667, 39.9522222),
label : {
text : 'Label == || triple',
verticalOrigin: Cesium.VerticalOrigin.TOP,
horizontalOrigin: Cesium.HorizontalOrigin.RIGHT,
font: '57px Helvetica', // NOTE: Large font size here
fillColor: Cesium.Color.WHITE,
outlineWidth: 2,
style: Cesium.LabelStyle.FILL,
pixelOffset: new Cesium.Cartesian2(20, 50),
scale: 0.3 // NOTE: Large font images scaled down via WebGL texturing.
}
});
html, body, #cesiumContainer {
width: 100%; height: 100%; margin: 0; padding: 0; overflow: hidden;
}
<link href="http://cesiumjs.org/Cesium/Build/Cesium/Widgets/widgets.css"
rel="stylesheet"/>
<script src="http://cesiumjs.org/Cesium/Build/Cesium/Cesium.js"></script>
<div id="cesiumContainer"></div>
I have a problem with the HTML5 Canvas. I use jCanvas to add layers to an canvas but I have a problem with the sizes.
I have 2 rectangles a green one and a red one.
Now I want the red box touch the green left top corner.
Using the coordinate system I start green at coordinates 200, 200
then red has to start at 0,0 and the width and height has to be 200 and 200.
But that doesn't work
Check this example
Why doesnt this work??
When I use 100x100 dimensions it does work
All depends on the origin of your layer. By default it is the center of the layer.
So to have the results you expect there are two solutions (exemples with layer 100*100) :
First in your case you have to calculate correct position from top left canvas origin to the middle of your object :
$('canvas')
.addLayer({
type: 'rectangle',
name: 'redBox',
fillStyle: '#c33',
x: 50, y: 50,//canvas origin to center (100/2)
width: 100, height: 100
})
.addLayer({
type: 'rectangle',
name: 'greenBox',
fillStyle: '#585',
x: 150, y: 150,//canvas origin to center (100 of red layer + 100/2)
width: 100, height: 100
})
.drawLayers();
Or you can set origin to top left corner by disable fromCenter property:
$('canvas')
.addLayer({
type: 'rectangle',
name: 'redBox',
fillStyle: '#c33',
fromCenter: false,
x: 0, y: 0,
width: 100, height: 100
})
.addLayer({
type: 'rectangle',
name: 'greenBox',
fillStyle: '#585',
fromCenter: false,
x: 100, y: 100,
width: 100, height: 100
})
.drawLayers();
Hope this help