Flex : Print a Chart? - actionscript-3

I wish to print a chart.
I do as follow :
var printJob : PrintJob = new PrintJob();
if ( printJob.start() == false )
return;
var printOptions : PrintJobOptions = new PrintJobOptions( true );
printJob.addPage( lineChart, null, printOptions );
printJob.send();
but as a result i am receiving only 1 page which containing only some part of the chart.
How to scale the whole chart on 1 page, and how to print all of the chart pages when it is not scaled ?

Alive PDF or Pure PDF or FxPDF is one of the best solutions to create cutom printings.
http://alivepdf.bytearray.org/
http://code.google.com/p/purepdf/

You only get one page because you add only one page:
printJob.addPage( lineChart, null, printOptions );
Your chart clip must fit on a page, A4 dimension in pixels should fit in width:559 x height:842.
You can check the dimensions of your chart clip, when it is bigger then the A4 you can scale it accordingly (don't forget print margins). To scale a movielclip you can use scaleX or scaleY, but changing the width or height of the container works better for me, because pixel values are easier then calculating the scale.
You can also create a print template clip, so instead of printing the chart clip immediately you place the charts on a new clip, that way you have more control over the page you are printing. It will also be easier to add more pages to the printjob.

Related

How can I make it so Edit2D lines do not resize when viewer is zoomed in and out?

Long story short: I want to set Edit2D polyline tool's line width to 6" based on calibration sizing and have it stay that size in the viewer no matter the camera zoom.
I'm using the edit2d library to allow drawing. I need to be able to set the line width for the polyline tool and have it stay at that width similar to how markups stay a set size when drawn. The default functionality of the edit2d polyline tool is for the line to be resized on camera changes and so it grows and shrinks depending on zoom.
I tried setting edit2DTools.polylineTool.style.isScreenSpace = false; which works, however, trying to set the specific size is difficult as it ends up being a decimal less then 1 and I can't find a correlation from the calibration, page size, etc. to allow me to dynamically set the size the same on different models.
I also found this in the Edit2D Snapper's code, but I can't figure out what's happening here to replicate it on the polyline tool. It seems to be doing what I want to do.
Any help or ideas at all would be greatly appreciated!
This code seems to be working for me:
async function setLineWidth(viewer) {
let mt = await viewer.loadExtension("Autodesk.Measure");
if (!mt.sharedMeasureConfig.calibrationFactor) {
console.log("Has not been calibrated yet");
return;
}
let edit2d = viewer.getExtension('Autodesk.Edit2D');
let pt1 = {x:0, y:0, z:0}, pt2 = {x:6, y:0, z:0};
viewer.model.pageToModel(pt1, pt2, 0 /*viewport id*/, true /*reverse*/);
let style = edit2d.defaultTools.polylineTool.style;
style.lineWidth = (pt2.x - pt1.x) / mt.calibration.scaleFactor;
}
Here is a video showing it in action: https://youtu.be/DIaKugvQdm4
As you can see first the lineWidth of the polylineTool is not what you want, but after setting what 6" should be in the drawing, I can set it to the same width and all is fine.
Here is a zip file with the html including the JavaScript code and the test PDFs I used: https://github.com/adamenagy/Container/blob/master/Edit2dTest.zip

Building an web based image annotation tool - saving annotations to localStorage

I am building a web application for annotating images. The work flow is as follows:
Select a project - using : action = list all sub-projects
Click on a sub-project : action = fetch all the images within-sub project
Display the images as a horizontal scrollable thumbnail gallery
Onclick image thumbnail from the gallery, display the larger image for annotation.
I am using canvas to display larger image. I have used another canvas as a layer to the first one, and I am able to draw rectangles using mouse over regions of interest. I am saving it locally. However, when I move on to the next image, the rectangle also gets carried to the next image.
My question is, instead of using just one layer, do I have to dynamically create as many canvas layers as I have in the annotation dataset. I am not sure because in each sub project I have around 8000-9000 images. Though I wont be annotating on all of them, still creating as many canvases as layers doesn't really sound good for me.
The following is the code:
HTML Canvas
<div class="body"> <!-- Canvas to display images begins -->
<canvas id="iriscanvas" width=700px height=700px style="position:absolute;margin:50px 0 0 0;z-index:1"></canvas>
<canvas id="regncanvas" onclick="draw(this, event)" width=700px height=700px style="position:absolute;margin:50px 0 0 0;z-index:2"></canvas>
</div> <!-- Canvas to display images ends -->
Step 4 given above: OnClick display thumbnail
function clickedImage(clicked_id) {
var clickedImg = document.getElementById(clicked_id).src;
var clickedImg = clickedImg.replace(/^.*[\\\/]/, '');
localStorage.setItem("clickedImg", clickedImg);
var canvas = document.getElementById("iriscanvas");
var ctx = canvas.getContext("2d");
var thumbNails = document.getElementById("loaded_img_panel");
var pic = new Image();
pic.onload = function() {
ctx.drawImage(pic, 0,0)
}
thumbNails.addEventListener('click', function(event) {
pic.src = event.target.src;
});
}
Draw rectangles on second layer of canvas
window.onload=function(){
c=document.getElementById("regncanvas");
if (c) initCanvas(c);
};
function initCanvas(canvas){
// Load last canvas
loadLastCanvas(canvas);
}
function draw(canvas, event){
// Draw at random place
ctx=c.getContext("2d");
ctx.fillStyle="#ff0000";
ctx.beginPath();
ctx.fillRect (250*Math.random()+1, 220*Math.random()+1, 40, 30);
ctx.closePath();
ctx.fill();
// Save canvas
saveCanvas(canvas);
}
function saveCanvas(c){
localStorage['lastImgURI']=c.toDataURL("image/png");
}
function loadLastCanvas(c){
if (!localStorage['lastImgURI']) return;
img = new Image();
img.onload = function() {
ctx=c.getContext("2d");
ctx.drawImage(img, 0, 0, img.width, img.height);
};
img.src= localStorage['lastImgURI'];
}
Can someone guide me please?
The following is a screen grab of my application:
I have developed OCLAVI which is an image annotation tool with loads of features. It's still in beta but just after 3 weeks of release, it is gaining attraction quickly.
I have few advises for you.
HTML Canvas follow draw and forget strategy and every time redrawing the image is not a good idea. Be it 10 images or 10k, you should have one canvas for drawing the image and one canvas for drawing the shapes. Image canvas need be touched only when the image changes. Different shapes can share the same canvas.
You should integrate a data storage. Local storage is clearly not a good option to store this amount of data (especially if you have a team member who also would be annotating on the same image dataset.)
Isolate the code to a separate-separate file according to the shape. It will be very handy when you will think of adding support for Circle, Polygon, Cuboidal, Point interactions. Trust me following OOPs concepts will relive you from a lot of pain.
In terms of complexity
zooming with coordinates is easy
move with coordinates is of medium level difficulty
but you need to think with pen and paper to implement move on a zoomed image canvas (P.S. take care of the canvas flickering when the image moves
). How much the image can move in each direction also need to be calculated.
Take care of the image to canvas dimension ratio because at the end you need to have the coordinates scaled down to image level.
If your canvas size vs image size ratio is 1:1 then your job is simplified.
But this won't happen always because some images might be very small or very large to directly fit in window screen and you need to scale up and down accordingly.
The complexity increases if you like to use percentage width and height for canvas and your other team member annotating the image has a different screen size. So he drawing something will look something else on your screen.

How to make the points overlap in visjs timeline?

I am trying to create a time line using http://visjs.org/timeline_examples.html
I want the time line to have fixed height (which I can set using height attribute in options). But As I zoom in/out the timeline, It is displaying the points one below another. This feature is affecting the height of the graph.
Can anyone help me how to make the points overlap?! so that I can have the height of the groups constant?
Actual behavior
In the options for your timeline you can specify stack: false e.g.
var options = {
stack: false
};
var timeline = new vis.Timeline(container, dataset, options);
This will cause the time line items to overlap rather than stack up on top of each other. You can see this in action here:
http://visjs.org/examples/timeline/other/groupsPerformance.html

scaling object to match field of view

I am overlaying some clickable hotspots on top of a proprietary panorama viewer application in flash (as3), and I need to make sure that the hotspots scale according to the changing field of view as the user zooms in / zooms out, but I'm not sure what formula to use.
I set a maximum and minimum field of view of 90 and 25, respectively. I've been given some suggestions of how to calculate the scale of the icons:
from the maker of the panorama software:
Scale => 1/tan(FoV)
This doesn't seem to work for me. And:
scalar += (ZOOM_SCALE_UPPER - ZOOM_SCALE_LOWER) * ( ZOOM_LIMIT_OUT - tempFOV )/( ZOOM_LIMIT_OUT-ZOOM_LIMIT_IN) ;
hotspot.scaleX = hotspot.scaleY = scalar;
Gets me close, but at some point the hotspot stops scaling even though the panorama continues to scale. I thought I could just do something like:
diffFOV = previousFOV - currentFOV.
hotspot.scale = currentScale*(1-diffFov)
But that's not quite right either. Everything gets way too big or too small.
Any ideas?
You may be over thinking it.
//assume we change the scale
var NEW_SCALE:Number = currentScale*(1-(previousFOV-currentFOV));
//1. change the scale of the parent containing both the view and the hotspots
viewSprite.scale = NEW_SCALE;
//this way the hotspot and the panorama will scale together
//2. if they are not in the same parent... then set them both to the same view
hotspot.scale = panorama.scale;
Only thing you may have to do after is reposition if they are not registered on their center point.

Tell Flying Saucer or BIRT to scale the html to fit on a single pdf page

My application generates HTML reports. The users want the report to fit a single PDF page - doesn't matter how much zoom you need for it.
Currently they render the page in Internet Explorer 8, and manually define a custom zoom level at the Print Preview window, then they print the page to PDF. I need to perform this operation automatically. How to achieve this?
The reports are actually created by BIRT, so BIRT-based solution is fine, too. Using the BIRT zoom options scale the document to fit height, but it doesn't fit width (because it first renders the HTML then apply the zoom).
Now I'm trying to use Flying Saucer to convert to PDF the BIRT-generated HTML.
I've saw similar questions related to abcPDF (.NET) and CF8 (se below) but I need a Java-based solution, and I wasn't able to use the same techniques with Flying Saucer or BIRT.
Tell abcPdf to scale the html to fit on a single pdf page
scale PDF to single page
We have added a pull request to Flying Saucer project for a patch to allow "itextrenderer fitting to page width".
The idea of the proposed patch is that we will make the page as wide as necessary (to avoid truncation) and then you can use PDF reader to fit to page when printing.
That's the solution I found, based on Flying Saucer / iText:
// A4 paper size = 297x210 mm
int PAGE_WIDTH = 2100;
int PAGE_LENGTH = 2970;
float MARGIN = 19.05f; // 0.75 inch
int width = PAGE_WIDTH;
// Java2DRenderer.NO_HEIGHT = -1 (it's private)
// if used the required height is computed
Java2DRenderer renderer = new Java2DRenderer(dom, width, -1);
BufferedImage img = renderer.getImage();
// Adjusts width based on required height
int height = img.getHeight();
width = (int) Math.round(height * PAGE_WIDTH / PAGE_LENGTH);
// Render same document again, now with the right dimensions
renderer = new Java2DRenderer(dom, width, height);
img = renderer.getImage();
com.lowagie.text.Document pdf = new com.lowagie.text.Document(PageSize.A4);
pdf.setMargins(MARGIN,MARGIN,MARGIN,MARGIN);
PdfWriter.getInstance(pdf, new FileOutputStream(args[0]+".pdf"));
pdf.open();
com.lowagie.text.Image pdfImage = com.lowagie.text.Image.getInstance(img,Color.WHITE);
Rectangle ps = pdf.getPageSize();
pdfImage.scaleAbsolute(
ps.getWidth()-pdf.leftMargin()-pdf.rightMargin(),
ps.getHeight()-pdf.topMargin()-pdf.bottomMargin()
);
pdf.add(pdfImage);
pdf.close();
First, I have not used Flying Saucer.
However, perhaps others may be reading your question and need a different solution.
If you are using the Java BIRT Engine and setting the render options yourself, you can apply:
[PAGE_OVERFLOW = FIT_TO_PAGE_SIZE]