How to draw a loop shape in WPF? - c#

I'm looking in on how to draw a looping shape in WPF from codebehind.
I know I can draw ellipses and draw a line, but I can't find anywhere how to modify them to get this looping shape.
Perhaps I'm not using the correct word for this type of drawing... but also found some words such as clothoids but not sure if this is exactly what I'm looking for...
Any tips are welcome. Thank you !

It's a little clumsy but you can create Geometry objects and then Path objects from SVG data.
The Path can then be hosted in any container.
//Define SVG data
string pathData = "M 4.4285714e-6,196.64791 C 71.557031,196.64791 202.13304,-0.49493571 99.047621,-0.49493571 c -103.0854176,0 -4.93638,197.14284571 99.047619,197.14284571 103.984,0 197.9832,-197.14284571 99.04762,-197.14284571 -98.93558,0 3.94706,197.14284571 99.04762,197.14284571 95.10056,0 199.7498,-197.14284571 99.04761,-197.14284571 -100.70219,0 4.52998,197.14284571 99.04762,197.14284571";
//Create converter
var converter = TypeDescriptor.GetConverter(typeof(Geometry));
//Create Path
var p = new Path() {
Data = (Geometry)converter.ConvertFrom(pathData),
Stroke = new SolidColorBrush(Colors.Red),
StrokeThickness = 4
};

Related

How to render image of a country on a globe using sharpmap

I have a list of region borders inside SQL database and i am using sharpmap to render thumbnail images for every country i need. It works really well.
But I would like to go one step further and add a small globe around it and position country on it's place in globe, but I do not know where to start.
Here's the code i'm using so far to render country thumbs. Any ideas?
var map = new Map(new Size(command.Width, command.Height));
map.BackColor = Color.Transparent;
var countryGeometry = GeometryFromWKT.Parse(command.CountryLevelWkt);
IProvider countryProvider = new GeometryFeatureProvider(countryGeometry);
var countryLayer = new VectorLayer("country", countryProvider);
var borderColor = System.Drawing.ColorTranslator.FromHtml(command.BorderColor);
countryLayer.Style.EnableOutline = true;
countryLayer.Style.Outline = new Pen(borderColor);
countryLayer.Style.Outline.Width = command.BorderWidth;
countryLayer.Style.Fill = Brushes.Transparent;
var transformationFactory = new CoordinateTransformationFactory();
countryLayer.CoordinateTransformation = transformationFactory.CreateFromCoordinateSystems(
GeographicCoordinateSystem.WGS84,
ProjectedCoordinateSystem.WebMercator);
map.Layers.Add(countryLayer);
var bottomLeft = new Coordinate(command.Extents.BottomLeft.Longitude, command.Extents.BottomLeft.Latitude);
var topRight = new Coordinate(command.Extents.TopRight.Longitude, command.Extents.TopRight.Latitude);
// transformations
var bottomLeftLongLat = countryLayer.CoordinateTransformation.MathTransform.Transform(bottomLeft);
var topRightLongLat = countryLayer.CoordinateTransformation.MathTransform.Transform(topRight);
map.ZoomToBox(new Envelope(bottomLeftLongLat, topRightLongLat));
var img = map.GetMap();
return img;
Start by drawing all countries on a new map, each on its own layer.
Draw the country in which you're interested on its own layer.
Set map center to the Envelope.Center of the layer from Step 2. Eg, if drawing Australia, the map will move to the left.
Render map as image. Draw image on a drawing sufrace (System.Drawing.Graphics).
Re-center the map, to cover the empty space. Eg, if drawing Australia, move map almost all the way to the right. You will need to work out these offsets programmatically.
Render map from step 5 as image. Add image to the same drawing sufrace (see step 4).
Repeat steps 5-6 covering empty space below/above the render made at step 3.
Here is an example:
Note that:
Australia is in the center
There is a gap between map layers near the mouse pointer (gap in screenshot is intentional to demonstrate the logic)
Some countries are very large (eg Russia) and obtaining Envelope.Center will not work very well - consider centering based on the largest polygon only
Here's a sample Windows Forms project. In the sample, I used maps from http://thematicmapping.org/downloads/world_borders.php.

How to render InkStroke on Canvas using BezierSegment in UWP C#

I am porting an application from javascript to UWP c# and I am struggling with the new InkCanvas. If you are familiar with the new InkCanvas in UWP, I would truly appreciate your help.
This is the code I wrote that takes renders an InkStroke onto a Canvas.
public static void Bezier(Canvas canvas, InkStroke stroke)
{
var segments = stroke.GetRenderingSegments();
PathFigure pthFigure = new PathFigure() { StartPoint = new Point(segments[0].Position.X, segments[0].Position.Y)};
for (int i = 1; i < segments.Count; i++)
{
var segment = segments[i];
var bezier = new BezierSegment();
bezier.Point1 = new Point(segment.BezierControlPoint1.X, segment.BezierControlPoint1.Y);
bezier.Point2 = new Point(segment.BezierControlPoint2.X, segment.BezierControlPoint2.Y);
bezier.Point3 = new Point(segment.Position.X, segment.Position.Y);
pthFigure.Segments.Add(bezier);
}
PathGeometry pthGeometry = new PathGeometry();
pthGeometry.Figures.Add(pthFigure);
Path path = new Path();
//path.Stroke = new SolidColorBrush(stroke.DrawingAttributes.Color);
//path.StrokeThickness = stroke.DrawingAttributes.Size.Height;
path.Stroke = new SolidColorBrush(Colors.Red);
path.StrokeThickness = 1;
path.Data = pthGeometry;
canvas.Children.Add(path);
}
Unfortunately, the control points seem to be messed up, and I do not understand why.
You can see below an image of what I get running this code.
The black stroke is the one originally rendered in the InkCanvas, and the red stroke is the one rendered on the Canvas from the code above.
The black stroke is the one originally rendered in the InkCanvas, and the red stroke is the one rendered on the Canvas from the code above
Anyone has any idea of what I am doing wrong?
I found the problem! I was setting drawingAttributes.FitToCurve = false and this caused the control points to be zero. I assumed this setting was only affecting the rendering, but now it makes sense because I was calling GetRenderingSegments. I was able to draw the shape by using GetInkPoints and then draw a polyline.

Barcode i25 using ItextSharp

i am using BarcodeInter25 class to make barcode. I am able to make it but its just blur how can it become more sharp ??
also its background white colour is not completely white
My Code:
BarcodeInter25 code25 = new BarcodeInter25();
Rectangle r = new iTextSharp.text.Rectangle(38, 152);
code25.ChecksumText = false;
code25.Code = "some digits";
code25.BarHeight = 2
System.Drawing.Image i = code25.CreateDrawingImage(System.Drawing.Color.Black, System.Drawing.Color.White);
MemoryStream ms = new MemoryStream();
i.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
Image img = Image.GetInstance(ms.ToArray());
ms.Dispose();
Looking at your code, it should be obvious why the barcode is blurry. You convert it to a System.Drawing.Image (making it a raster image) and then you convert it to an iTextSharp.text.Image (but by then the image is already blurry).
The correct way to achieve what you want, is to create an iTextSharp.text.Image straight from the barcode (do not pass through System.Drawing.Image). This can be done like this:
BarcodeInter25 code25 = new BarcodeInter25();
Rectangle r = new iTextSharp.text.Rectangle(38, 152);
code25.ChecksumText = false;
code25.Code = "some digits";
code25.BarHeight = 2;
PdfContentByte cb = writer.DirectContent;
Image img = code25.CreateImageWithBarcode(cb, null, null);
Now the Image object won't be a raster image (with pixels that make the lines blurry), but it will be a true vector image (no pixels, but instructions such as moveTo(), lineTo() and stroke()). Vector data has the advantage that it is resolution independent: you can zoom in and zoom out as much as you want, it will always be sharp.
This is explained in Chapter 10 of my book where you'll find the Barcodes example. In that chapter, you'll also discover the setFont() (or in iTextSharp the Font property). I quote from the API documentation:
public void setFont(BaseFont font)
Sets the text font.
Parameters:
font - the text font. Set to null to suppress any text
So if you don't want to see any text, you can add the following line to the above code snippet:
code25.Font = null;
You should avoid re-sizing by any means. The output is most likely pixel-perfect but when you scale it up/down a bilinear filter will smooth it rendering it blurry.
I had the same exact problem by embedding a QRC code in a PDF and solved it by avoiding a resize.
If you really need a different size apply it programmatically in code by using the correct interpolation algorithm.

Emgucv drawn items

I am making a project using Emgucv library, he problem is as follows,
I Capture image
detect feature
extract it
draw it
After that i copy the drawn items in a blank image, now I want find contours inside that new image, but the result is always bull, Why is That?
Thanks in advance
Additional information would be good.
But for you to be able to find the contours, the new image must be converted into a binary image like the ff: (assuming newImage is of type Image)
Image<Gray,byte> binaryImage = newImage.ThresholdBinary(new Gray(1), new Gray(255));
To detect contours and write to resultImage:
for (var contour = binaryImage.FindContours(
CHAIN_APPROX_METHOD.CV_CHAIN_APPROX_SIMPLE,
RETR_TYPE.CV_RETR_CCOMP);
contour != null;
contour = contour.HNext)
{
resultImage.Draw(contour, new Gray(255), -1);
}

Connecting two shapes together, Silverlight 2

I'm looking to connect or glue together two shapes or objects with a Line. These shapes will be generated dynamically, meaning I'll be calling a Web service on the backend to determine how many objects/shapes need to be created. Once this is determined, I'll need to have the objects/shapes connected together.
The method signature may look like this (similar to Visio's drawing capabilities):
GlueTogether(objButton1, objButton2);
I may need to get the position of each Rectangle shape or Button to determine where the starting Line point is. Then determine the second shape/objects position to draw the line.
Any help or suggestions would be great!
Use a Path or a Line below the shapes in stacking order or z index
Use instance.TransformToVisual() to get the transform of each shape
Use the transform to transform the centerpoint of each shape
Draw a line between the two centerpoints.
var transform1 = shape1.TransformToVisual(shape1.Parent as UIElement);
var transform2 = shape2.TransformToVisual(shape2.Parent as UIElement);
var lineGeometry = new LineGeometry()
{
StartPoint = transform1.Transform(new Point(shape1.ActualWidth / 2, shape1.ActualHeight / 2.0)),
EndPoint = transform2.Transform(new Point(shape2.ActualWidth / 2.0, shape2.ActualHeight / 2.0))
};
var path = new Path()
{
Data = lineGeometry
};
I am trying much the same, but instead of the line going from one centre to the other I want the lines to stop at the edge of the two shapes.
In particular I have arrows at the end of the lines, and the arrows need to stop at the bounds of the shapes instead of going inside/behind the shape to its centre.
My shape is a usercontrol with a grid and rectangle, and some labels and other stuff.
I can't find any methods that provide me with a geometry for the edge of the shape (which is a rounded rectangle).
I figured out a solution that uses the bounding box and intersection points to connect my elements by lines at their approximate edges, and it works well for me using arrow ended lines.
See Connecting two WPF canvas elements by a line, without using anchors?
Check this out: http://www.graphspe.com/Main.aspx#/Solution/graphviz-xaml-renderer
All you have to do is printf to a string and you get your Silverlight[2|3] diagram.
Ceyhun
In addition... Instead of connecting to the center point of your objects, I've modified the same code from Michael S. to:
var lineGeometry = new LineGeometry()
{
StartPoint = transform1.Transform(new Point(1 , b1.ActualHeight / 2.0)),
EndPoint = transform2.Transform(new Point(b2.ActualWidth , b2.ActualHeight / 2.0))
};
This will connect at the outer portions of each object.
I am using the above code to draw two buttons, I want a line between those two buttons, but all i get are two buttons that look like tiny circles and no line.
code:
Button b1 = new Button();
Button b2 = new Button();
canvas1.Children.Add(b1);
canvas1.Children.Add(b2);
Canvas.SetLeft(b1, 300);
var transform1 = b1.TransformToVisual(b1.Parent as UIElement);
var transform2 = b2.TransformToVisual(b2.Parent as UIElement);
var lineGeometry = new LineGeometry()
{
StartPoint = transform1.Transform(new Point(1, b1.ActualHeight / 2.0)),
EndPoint = transform2.Transform(new Point(b2.ActualWidth, b2.ActualHeight / 2.0))
};
var path = new Path()
{
Data = lineGeometry
};
canvas1.Children.Add(path);

Categories