I'm working newly with a Streamgeometry to draw a simple arrow. Now I need to turn the arrow to a specified angle. But how to rotate this geometry?
Dim pt1 As New Point(X1, Me.Y1) 'left point
Dim pt2 As New Point(_X2, Me.Y2) 'right point
Dim pt3 As New Point(_X2 + (HeadWidth * cost - HeadHeight * sint), Y2 + (HeadWidth * sint + HeadHeight * cost)) 'arrow line down
Dim pt4 As New Point(_X2 + (HeadWidth * cost + HeadHeight * sint), Y2 - (HeadHeight * cost - HeadWidth * sint)) 'arrow line up
context.BeginFigure(pt1, True, False)
context.LineTo(pt2, True, True)
context.LineTo(pt3, True, True)
context.LineTo(pt2, True, True)
context.LineTo(pt4, True, True)
If the rotation is only for presentation (i.e. you don't care that the original geometry data is still an arrow pointing in the original direction) then you can apply a transform to it.
After you've drawn on your context, just apply the transform on the original StreamGeometry object (code in C# but it applies to VB.NET too):
var geo = new StreamGeometry();
using (var ctx = geo.Open())
{
ctx.BeginFigure(new Point(0, 20), false, false);
ctx.LineTo(new Point(100, 20), true, true);
ctx.LineTo(new Point(80, 40), true, true);
ctx.LineTo(new Point(80, 0), true, true);
ctx.LineTo(new Point(100, 20), true, true);
}
geo.Transform = new RotateTransform(45);
var drawing = new GeometryDrawing(Brushes.Transparent, new Pen(Brushes.Black, 1), geo);
image1.Source = new DrawingImage(drawing);
The above code will draw an arrow pointing down/right on an Image control named image1.
Related
I am facing a problem while using encodedImage. When a user logins into the app, the first form after successful login has an image. And the image is causing me issues upon retrieving it.
When the user captures an image in the app, I convert it to a base64 string which I send to the server. The code for that is:
ImageIO img = ImageIO.getImageIO();
ByteArrayOutputStream out = new ByteArrayOutputStream();
img.save(et, out, ImageIO.FORMAT_JPEG, 1);
byte[] ba = out.toByteArray();
String userImage64 = Base64.encodeNoNewline(ba);
et is the captured image. So I store the string userImage64 in the server.
When I retrieve the base64, I decode it and convert it to an EncodedImage. The code is:
String url = new JSONObject(result.getResponseData()).getString("photo");
byte[] b = Base64.decode(url.getBytes());
Image icon = EncodedImage.create(b);
When I am on the simulator, everything flows smoothly. The images display and everything works very well.
My issue is, when I put the app on an android device, it doesn't work. It shows me a toast of successful login and just stops there. So i did some debugging and realized that issue is with the three lines of converting from base64 to image. When I comment out the three lines, everything works very well. Where could I be going wrong?
EDIT
Below is the code I use to capture a photo:
String i = Capture.capturePhoto();
if (i != null) {
try {
final Image newImage = Image.createImage(i);
Image roundedMask = Image.createImage(rich.minScreensize() / 4, rich.minScreensize() / 4, 0xff000000);
Graphics gra = roundedMask.getGraphics();
gra.setColor(0xffffff);
gra.fillArc(0, 0, rich.minScreensize() / 4, rich.minScreensize() / 4, 0, 360);
Object masked = roundedMask.createMask();
cropImage(newImage, rich.minScreensize() / 4, rich.minScreensize() / 4, et -> {
if (editing) {
try {
ImageIO img = ImageIO.getImageIO();
ByteArrayOutputStream out = new ByteArrayOutputStream();
img.save(et, out, ImageIO.FORMAT_JPEG, 1);
byte[] ba = out.toByteArray();
userImage64 = Base64.encodeNoNewline(ba);
et = et.applyMask(masked);
logoimage.setIcon(et);
///removed unnecessary code
logoimage.getComponentForm().revalidate();
} catch (IOException ex) {
}
} else {
et = et.applyMask(masked);
logoimage.setIcon(et);
}
});
} catch (IOException ex) {
Log.p("Error loading captured image from camera", Log.ERROR);
}
}
Inside there is code I use to crop the photo and that is code is:
private void cropImage(Image img, int destWidth, int destHeight, OnComplete<Image> s) {
Form previous = getCurrentForm();
Form cropForm = new Form("", new LayeredLayout());
Label toobarLabel = new Label("New Holder", "Toolbar-HeaderLabel");
cropForm.setTitleComponent(toobarLabel);
Toolbar mainToolbar = new Toolbar();
mainToolbar.setUIID("ToolBar");
cropForm.setToolbar(mainToolbar);
Label moveAndZoom = new Label("Move and zoom the photo to crop it");
moveAndZoom.getUnselectedStyle().setFgColor(0xffffff);
moveAndZoom.getUnselectedStyle().setAlignment(CENTER);
moveAndZoom.setCellRenderer(true);
cropForm.setGlassPane((Graphics g, Rectangle rect) -> {
g.setColor(0x0000ff);
g.setAlpha(150);
Container cropCp = cropForm.getContentPane();
int posY = cropForm.getContentPane().getAbsoluteY();
GeneralPath p = new GeneralPath();
p.setRect(new Rectangle(0, posY, cropCp.getWidth(), cropCp.getHeight()), null);
if (isPortrait()) {
p.arc(0, posY + cropCp.getHeight() / 2 - cropCp.getWidth() / 2,
cropCp.getWidth() - 1, cropCp.getWidth() - 1, 0, Math.PI * 2);
} else {
p.arc(cropCp.getWidth() / 2 - cropCp.getHeight() / 2, posY,
cropCp.getHeight() - 1, cropCp.getHeight() - 1, 0, Math.PI * 2);
}
g.fillShape(p);
g.setAlpha(255);
g.setColor(0xffffff);
moveAndZoom.setX(0);
moveAndZoom.setY(posY);
moveAndZoom.setWidth(cropCp.getWidth());
moveAndZoom.setHeight(moveAndZoom.getPreferredH());
moveAndZoom.paint(g);
});
final ImageViewer viewer = new ImageViewer();
viewer.setImage(img);
cropForm.add(viewer);
cropForm.getToolbar().addMaterialCommandToRightBar("", FontImage.MATERIAL_CROP, e -> {
previous.showBack();
s.completed(viewer.getCroppedImage(0).
fill(destWidth, destHeight));
});
cropForm.getToolbar().addMaterialCommandToLeftBar("", FontImage.MATERIAL_CANCEL, e -> previous.showBack());
cropForm.show();
}
In this example I use Npgsql in development version 3.1.0-alpha6.
I want to specify a PostgisGeometry object as a parameter in a query (NpgsqlDbType.Geometry)
and select the object again.
Queries with types like Point, MultiPoint, LineString, MultiLineString, Polygon and GeometryCollection will be returned correctly. A PostgisMultiPolygon object with only one polygon will be returned correctly too.
However, it does not work with a PostgisMultiPolygon with more than one polygon.
PostgisMultiPolygon geom1 = new PostgisMultiPolygon(new[]
{
new PostgisPolygon(new[]
{
new[]
{
new Coordinate2D(40, 40),
new Coordinate2D(20, 45),
new Coordinate2D(45, 30),
new Coordinate2D(40, 40)
}
})
}) {SRID = 4326};
PostgisMultiPolygon geom2 = new PostgisMultiPolygon(new[]
{
new PostgisPolygon(new[]
{
new[]
{
new Coordinate2D(40, 40),
new Coordinate2D(20, 45),
new Coordinate2D(45, 30),
new Coordinate2D(40, 40)
}
}),
new PostgisPolygon(new[]
{
new[]
{
new Coordinate2D(20, 35),
new Coordinate2D(10, 30),
new Coordinate2D(10, 10),
new Coordinate2D(30, 5),
new Coordinate2D(45, 20),
new Coordinate2D(20, 35)
}
})
}) {SRID = 4326};
using (NpgsqlConnection connection = CreateConnection())
{
NpgsqlCommand command = connection.CreateCommand();
command.Parameters.AddWithValue("p1", NpgsqlDbType.Geometry, geom1);
command.CommandText = "Select :p1";
command.ExecuteScalar();
}
using (NpgsqlConnection connection = CreateConnection())
{
NpgsqlCommand command = connection.CreateCommand();
command.Parameters.AddWithValue("p1", NpgsqlDbType.Geometry, geom2);
command.CommandText = "Select :p1";
command.ExecuteScalar(); //timeout occurs...
}
If increasing the CommandTimeout, the timeout occurs anyway.
Thanks in advance!
The fix for this bug has just been merged: https://github.com/npgsql/npgsql/pull/1025
Im using jfreecharts for my application. I need to remove the x-axis line in the Line chart produced. How can i remove the axis line, Any help would be appreciated.
To remove your axis line and tick marks, refer this code.
final DefaultCategoryDataset dataset = new DefaultCategoryDataset();
dataset.addValue(1.0, "Line", "2009");
dataset.addValue(2.0, "Line", "2010");
dataset.addValue(null, "Line", "2011");
dataset.addValue(3.0, "Line", "2012");
final JFreeChart chart = ChartFactory.createLineChart(
"", // chart title
"", // domain axis label
"", // range axis label
dataset, // data
PlotOrientation.VERTICAL, // orientation
false, // include legend
false, // tooltips
false // urls
);
chart.setBackgroundPaint(Color.WHITE);
final CategoryPlot plot = (CategoryPlot) chart.getPlot();
plot.setBackgroundPaint(Color.WHITE);
plot.setRangeZeroBaselinePaint(Color.RED);
plot.setOutlineVisible(false);
plot.setRangeGridlinePaint(Color.white);
plot.setDomainGridlinePaint(Color.BLUE);
final CategoryAxis categoryAxis = (CategoryAxis) plot.getDomainAxis();
categoryAxis.setAxisLineVisible(false);
categoryAxis.setTickMarksVisible(false);
//categoryAxis.setVisible(false);
final NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis();
//rangeAxis.setAxisLineVisible(false);
rangeAxis.setVisible(false);
rangeAxis.setLabelPaint(Color.BLUE);
rangeAxis.setRange(0, 3);
final LineAndShapeRenderer renderer = (LineAndShapeRenderer) plot.getRenderer();
//renderer.setItemLabelsVisible(false); //Deprecated.
renderer.setBaseShapesVisible(true);
renderer.setBaseShapesFilled(true);
renderer.setSeriesStroke(0, new BasicStroke(2.0f));
Shape circle = new Ellipse2D.Double(-3, -3, 6, 6);
renderer.setSeriesShape(0, circle);
plot.getRenderer().setSeriesPaint(0, Color.BLUE);
try {
ChartUtilities.saveChartAsPNG(new File("E:\\jfreeLinechart.png"), chart, 211, 90);
System.out.println("=====chart=====");
} catch (Exception e) {
e.printStackTrace();
}
Also refer this link
I have bitmapdata object converted to bytearray:
var bytes:ByteArray = bitmapDataA.getPixels(bitmapDataA.rect);
and I save it as .jpg file for later:
writeStream.writeBytes(bytes, 0, bytes.bytesAvailable);
Now, when I want to retrieve the data:
var file:File = File.documentsDirectory.resolvePath("data/"+photoNameVec[loadCounter]);
var fileStream:FileStream = new FileStream();
fileStream.open(file, FileMode.READ);
var fileContent:ByteArray = new ByteArray;
fileStream.readBytes(fileContent);
fileStream.close();
var bmpData:BitmapData = new BitmapData(XXX, YYY);
bmpData.setPixels(bmpData.rect, fileContent);
addChild(new Bitmap(bmpData));
But I need to get exact XXX and YYY to show the graphics correctly. How can I do this?
EDIT:
As there was no way to determine bitmapdata width and height based on bytearray, I decided to transform all pictures I take to 1024px x 768px:
var bitmapDataA:BitmapData = new BitmapData(mpLoaderInfo.width, mpLoaderInfo.height);
var matrix:Matrix = new Matrix();
matrix.scale( 1024 / mpLoaderInfo.width, 768 / mpLoaderInfo.height);
var bitmapDataB:BitmapData = new BitmapData(1024,768);
bitmapDataB.draw(mpLoaderInfo.content, matrix, null, null, new Rectangle(0,0,1024,768), true);
Still waiting for tips on getting Width x Height from bytearray created by getPixels method of bitmapdata.
You can use a Loader class to load the image then you can access it's width/height and BitmapData
var file:File = File.documentsDirectory.resolvePath("data/"+photoNameVec[loadCounter]);
var myImage:BitmapData;
var loader:Loader = new Loader();
var urlReq:URLRequest = new URLRequest(file.url);
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loaded);
loader.load(urlReq);
function loaded(e:Event):void
{
var bmp:Bitmap = e.target.content as Bitmap;
myImage = bmp.bitmapData;
trace(myImage.width, myImage.height);
}
And here is with loadBytes
var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.INIT, loaded);
loader.loadBytes(yourByteArray);
function loaded(e:Event):void
{
var bmp:Bitmap = e.target.content as Bitmap;
myImage = bmp.bitmapData;
trace(myImage.width, myImage.height);
}
I guess that's the most suiting solution :)
Simply expand the the bytearray with extra values from which I shall gather width and height.
http://www.ghostwire.com/blog/archives/as3-serializing-bitmaps-storing-bitmapdata-as-raw-binarybytearray/
Ps.: Creating and reading uncompressed files is way faster than making png/jpg
The byte array created by getPixels does not contain any information on the height or width of the bitmap, it's simply an "unsigned integer (a 32-bit unmultiplied pixel value) for each pixel".
So you'll need to either write it as an image format (PNG/JPG) which will require encoding (hence time), or simply add the width and height to your byte array before writing to file.
Eg in your stream writer:
writeStream.writeInt( bitmapDataA.width );
writeStream.writeInt( bitmapDataA.height );
writeStream.writeBytes(bytes, 0, bytes.bytesAvailable);
Then when you are loading:
var file:File = File.documentsDirectory.resolvePath("data/"+photoNameVec[loadCounter]);
var fileStream:FileStream = new FileStream();
fileStream.open(file, FileMode.READ);
var w:int = fileStream.readInt();
var h:int = fileStream.readInt();
var fileContent:ByteArray = new ByteArray;
fileStream.readBytes(fileContent);
fileStream.close();
var bmpData:BitmapData = new BitmapData( w , h);
bmpData.setPixels(bmpData.rect, fileContent);
addChild(new Bitmap(bmpData));
I have a new problem.
I already done my widget but now i want 5 rating widget's for 5 categories in my database.
I have this column in my database (named places.categ):
places.categ
a
b
c
d
a
e
....
I have 21 markers in my Google Maps and each one of them as a category. (a,b,c,d or e).
How can i associate 5 rating widgets to those 21 markers by category? All i could do was this:
db.define_table('product',
Field('A', 'integer',requires=IS_IN_SET(range(1,6))),
Field('B', 'integer',requires=IS_IN_SET(range(1,6))),
Field('C', 'integer',requires=IS_IN_SET(range(1,6))),
Field('D', 'integer',requires=IS_IN_SET(range(1,6))),
Field('E', 'integer',requires=IS_IN_SET(range(1,6))))
I have this code in my models/db.py and this one in my controllers/default.py:
from plugin_rating_widget import RatingWidget
# Inject the widgets
db.product.A.widget = RatingWidget()
db.product.B.widget = RatingWidget()
db.product.C.widget = RatingWidget()
db.product.D.widget = RatingWidget()
db.product.E.widget = RatingWidget()
# form2 = SQLFORM.factory(
# Field('Rating','integer',widget=SQLFORM.widgets.RatingWidget))
# if form2.process().accepted:
# print form2.vars.search
form2 = SQLFORM(db.product)
if form2.accepts(request.vars, session):
session.flash = 'submitted %s' % form2.vars
redirect(URL('index'))
I have 5 rating widget but they are not associated to my database and they are vertical (in 5 lines) and not in 1 line, like i wanted too.
TIA.
P.S.: I have the plugin rating widget uploaded.
I solved in another way. I get colors to each category with this code:
var amarelo = new google.maps.MarkerImage(
"http://labs.google.com/ridefinder/images/mm_20_yellow.png",
new google.maps.Size(12, 20),
new google.maps.Point(0, 0),
new google.maps.Point(6, 20));
var vermelho = new google.maps.MarkerImage(
"http://labs.google.com/ridefinder/images/mm_20_red.png",
new google.maps.Size(12, 20),
new google.maps.Point(0, 0),
new google.maps.Point(6, 20));
var verde = new google.maps.MarkerImage(
"http://labs.google.com/ridefinder/images/mm_20_green.png",
new google.maps.Size(12, 20),
new google.maps.Point(0, 0),
new google.maps.Point(6, 20));
var azul = new google.maps.MarkerImage(
"http://labs.google.com/ridefinder/images/mm_20_blue.png",
new google.maps.Size(12, 20),
new google.maps.Point(0, 0),
new google.maps.Point(6, 20));
var branco = new google.maps.MarkerImage(
"http://labs.google.com/ridefinder/images/mm_20_white.png",
new google.maps.Size(12, 20),
new google.maps.Point(0, 0),
new google.maps.Point(6, 20));
var sombra = new google.maps.MarkerImage(
"http://labs.google.com/ridefinder/images/mm_20_shadow.png",
new google.maps.Size(22, 20),
new google.maps.Point(0, 0),
new google.maps.Point(6, 20));
I awarded each category in one of this colors (example):
if (placescoordjs[i][4]== 'a')
{
marker = new google.maps.Marker({
position: new google.maps.LatLng(placescoordjs[i][1],placescoordjs[i][2]),
icon: amarelo, shadow: sombra,
map: map,
title: placescoordjs[i][3]
});
google.maps.event.addListener(marker, 'click', (function(marker, i) {
return function() {
infowindow.setContent(placescoordjs[i][0]);
infowindow.open(map, marker);
}
})(marker, i));
}
I have more 3 "else if" and the final else with the final color to my last category.
Thanks anyway. ;)