I am using the 2D Autodesk Forge Viewer, and I'm looking for a way to determine the X,Y coordinate of a block reference object from AutoCAD.
I have the dbID for the geometry element, and. I can get some information through NOP_VIEWER.getProperties() and NOP_VIEWER.getDimensions(), but neither of those have the X,Y coordinate.
With help from Xiaodong below, I was able to devise the following solution to get the X,Y coordinate of an object using its dbId
const geoList = NOP_VIEWER.model.getGeometryList().geoms;
const readers = [];
for (const geom of geoList) {
if (geom) {
readers.push(new Autodesk.Viewing.Private.VertexBufferReader(geom, NOP_VIEWER.impl.use2dInstancing));
}
}
const findObjectLocation = (objectId) => {
for (const reader of readers) {
let result;
reader.enumGeomsForObject(objectId, {
onLineSegment: (x, y) => {
result = { x, y };
},
});
if (result) {
return result;
}
}
throw new Error(`Unable to find requested object`);
};
As I remember, it is true the position data is not available with block entity. I will check with engineer team if there is any comment about the native position data of block. One alterative is to use Forge Design Automation of AutoCAD to extract the data yourself, while it would require additional more code.
After Forge translates the source DWG, the entities are converted to primitives. By API, it is feasible to get geometry info of the primitives, such as start point of line, center of circle. The two blogs tell in details:
https://forge.autodesk.com/blog/working-2d-and-3d-scenes-and-geometry-forge-viewer
https://forge.autodesk.com/blog/working-2d-and-3d-scenes-and-geometry-forge-viewer
Essentially, it uses the callback function:
VertexBufferReader.prototype.enumGeomsForObject = function(dbId, callback)
The callback object needs these optional functions:
• onLineSegment(x0, y0, x1, y1, viewport_id)
• onCircularArc(centerX, centerY, startAngle, endAngle, radius, viewport_id)
• onEllipticalArccenterX, centerY, startAngle, endAngle, major, minor, tilt, viewport_id)
• onTriangleVertex(x, y, viewport_id)
.
When i remove a tile with the coords (example: X: 15, Y: 9) with
TiledMapTileLayer tiledMapTileLayer = (TiledMapTileLayer)map.getLayers().get(0);
tiledMapTileLayer.setCell(15, 9, null);
I notice that actually the wrong tile is removed from the map. Instead tile with the coords X:15 Y: 6 is being removed. What am i doing wrong?
I believe this would be due to libgdx inverting the map to match better with their coordinate system. If your map is 16 tiles high, trying to remove tile at Y: 9 will result in removal of tile at Y: 16 - 9 - 1 = 6.
If you want to copy a Y coordinate from Tiled and put it in your code, you'll in general need to apply the following conversion to turn it into the same location in libgdx:
int y = tileLayer.getHeight() - 1 - [Y coordinate from Tiled];
Is there a method similar to ClientToWorld, that can give me the X,Y world coords if I provide it with X,Y screen coords?
I know that ClientToWorld gives me a Z coord of where it interacts with the model, but I am happy to have no Z coord as it will not raycast to a point on the model.
How about Viewer3dImpl.clientToViewport?
let coords = viewer.impl.clientToViewport(client.x, client.y); //c.Vector3 {x: -0.9696521095484826, y: 0.9200779727095516, z: 1 (always 1)}
let finalCoords = coords.unproject(viewer.impl.camera) //c.Vector3 {x: -26.379134321221724, y: 5.162777223710702, z: 1.3846547842336627}
See unofficial doc (not authoritative & subject to change w/o notice) for this method here
I'm currently playing with Kinetic.JS. I have drawn a rather crude UFO-like shape in two parts, a hull (red) and a disc (grey).
Demo - JSBin
Question: how come when I later arrange the shape ordering so the hull is above the disc, the disc bizarrely goes from grey to the hull's red?
Uncomment the moveToTop() line at the bottom of my JSBin to see what I mean. Here's the pertinent (condensed) code.
//ship hull
var hull = new Kinetic.Shape({
drawFunc: function(ctx) {
ctx.arc(game_dims.w / 2, game_dims.h * 0.6, game_dims.h * 0.45, 0, Math.PI, true);
this.fill(ctx);
},
fill: 'red'
});
//ship disc
var disc = new Kinetic.Circle({
x: game_dims.w / 2,
y: game_dims.h * 0.6,
radius: {x: game_dims.w * 0.45, y: 30},
fill: '#888'
});
//draw
layer.add(hull);
layer.add(disc);
stage.add(layer);
//post-production
hull.moveToTop(); // <-- weirdness - changes disc colour!?
layer.draw();
I am aware I could draw the two shapes in reverse order to get the desired order, but that is not what I want with this question - I'm interested in rearrangement of order after drawing.
Thanks in advance
Your draw function of the hull needs to tell the context it's drawing a new path:
function(ctx) {
ctx.beginPath();
ctx.arc(...);
this.fill(ctx);
}
By adding the beginPath() command you are telling the context that you are not in fact adding to the previous path, but drawing a new one instead. This is also what makes this.fill() fill the previous shape with red, because in your example the context is still referring to the disc when it attempts to fill it
This question already has answers here:
What's the best way to set a single pixel in an HTML5 canvas?
(14 answers)
Closed 7 years ago.
Drawing a line on the HTML5 canvas is quite straightforward using the context.moveTo() and context.lineTo() functions.
I'm not quite sure if it's possible to draw a dot i.e. color a single pixel. The lineTo function wont draw a single pixel line (obviously).
Is there a method to do this?
For performance reasons, don't draw a circle if you can avoid it. Just draw a rectangle with a width and height of one:
ctx.fillRect(10,10,1,1); // fill in the pixel at (10,10)
If you are planning to draw a lot of pixel, it's a lot more efficient to use the image data of the canvas to do pixel drawing.
var canvas = document.getElementById("myCanvas");
var canvasWidth = canvas.width;
var canvasHeight = canvas.height;
var ctx = canvas.getContext("2d");
var canvasData = ctx.getImageData(0, 0, canvasWidth, canvasHeight);
// That's how you define the value of a pixel
function drawPixel (x, y, r, g, b, a) {
var index = (x + y * canvasWidth) * 4;
canvasData.data[index + 0] = r;
canvasData.data[index + 1] = g;
canvasData.data[index + 2] = b;
canvasData.data[index + 3] = a;
}
// That's how you update the canvas, so that your
// modification are taken in consideration
function updateCanvas() {
ctx.putImageData(canvasData, 0, 0);
}
Then, you can use it in this way :
drawPixel(1, 1, 255, 0, 0, 255);
drawPixel(1, 2, 255, 0, 0, 255);
drawPixel(1, 3, 255, 0, 0, 255);
updateCanvas();
For more information, you can take a look at this Mozilla blog post : http://hacks.mozilla.org/2009/06/pushing-pixels-with-canvas/
It seems strange, but nonetheless HTML5 supports drawing lines, circles, rectangles and many other basic shapes, it does not have anything suitable for drawing the basic point. The only way to do so is to simulate a point with whatever you have.
So basically there are 3 possible solutions:
draw point as a line
draw point as a polygon
draw point as a circle
Each of them has their drawbacks.
Line
function point(x, y, canvas){
canvas.beginPath();
canvas.moveTo(x, y);
canvas.lineTo(x+1, y+1);
canvas.stroke();
}
Keep in mind that we are drawing to South-East direction, and if this is the edge, there can be a problem. But you can also draw in any other direction.
Rectangle
function point(x, y, canvas){
canvas.strokeRect(x,y,1,1);
}
or in a faster way using fillRect because render engine will just fill one pixel.
function point(x, y, canvas){
canvas.fillRect(x,y,1,1);
}
Circle
One of the problems with circles is that it is harder for an engine to render them
function point(x, y, canvas){
canvas.beginPath();
canvas.arc(x, y, 1, 0, 2 * Math.PI, true);
canvas.stroke();
}
the same idea as with rectangle you can achieve with fill.
function point(x, y, canvas){
canvas.beginPath();
canvas.arc(x, y, 1, 0, 2 * Math.PI, true);
canvas.fill();
}
Problems with all these solutions:
it is hard to keep track of all the points you are going to draw.
when you zoom in, it looks ugly
If you are wondering, what is the best way to draw a point, I would go with filled rectangle. You can see my jsperf here with comparison tests
In my Firefox this trick works:
function SetPixel(canvas, x, y)
{
canvas.beginPath();
canvas.moveTo(x, y);
canvas.lineTo(x+0.4, y+0.4);
canvas.stroke();
}
Small offset is not visible on screen, but forces rendering engine to actually draw a point.
The above claim that "If you are planning to draw a lot of pixel, it's a lot more efficient to use the image data of the canvas to do pixel drawing" seems to be quite wrong - at least with Chrome 31.0.1650.57 m or depending on your definition of "lot of pixel". I would have preferred to comment directly to the respective post - but unfortunately I don't have enough stackoverflow points yet:
I think that I am drawing "a lot of pixels" and therefore I first followed the respective advice for good measure I later changed my implementation to a simple ctx.fillRect(..) for each drawn point, see http://www.wothke.ch/webgl_orbittrap/Orbittrap.htm
Interestingly it turns out the silly ctx.fillRect() implementation in my example is actually at least twice as fast as the ImageData based double buffering approach.
At least for my scenario it seems that the built-in ctx.getImageData/ctx.putImageData is in fact unbelievably SLOW. (It would be interesting to know the percentage of pixels that need to be touched before an ImageData based approach might take the lead..)
Conclusion: If you need to optimize performance you have to profile YOUR code and act on YOUR findings..
This should do the job
//get a reference to the canvas
var ctx = $('#canvas')[0].getContext("2d");
//draw a dot
ctx.beginPath();
ctx.arc(20, 20, 10, 0, Math.PI*2, true);
ctx.closePath();
ctx.fill();