I want to do a perfectly simple thing. I want to draw two quadrilateral polygons, which have the top and bottom lines as parallel diagonals. I also want to draw these polygons stacked on top of each other.
However, after I draw the two polygons, there is a tiny but visible gap between them. It looks like this:
Here's the code that I use (I'm with Silverlight, which means WriteableBitmap):
var bmp = new System.Windows.Media.Imaging.WriteableBitmap((int)this.displayImage.Width, (int)this.displayImage.Height);
var polygon = new System.Windows.Shapes.Polygon()
{
StrokeThickness = 0,
Fill = new System.Windows.Media.SolidColorBrush(System.Windows.Media.Colors.Black),
Points = new System.Windows.Media.PointCollection()
{
new System.Windows.Point(10, 10),
new System.Windows.Point(100, 40),
new System.Windows.Point(100, 130),
new System.Windows.Point(10, 100)
}
};
var polygon2 = new System.Windows.Shapes.Polygon()
{
StrokeThickness = 0,
Fill = new System.Windows.Media.SolidColorBrush(System.Windows.Media.Colors.Black),
Points = new System.Windows.Media.PointCollection()
{
new System.Windows.Point(10, 100),
new System.Windows.Point(100, 130),
new System.Windows.Point(100, 220),
new System.Windows.Point(10, 190)
}
};
bmp.Render(polygon, null);
bmp.Invalidate();
bmp.Render(polygon2, null);
bmp.Invalidate();
displayImage.Source = bmp;
Here displayImage is an Image control on the main grid.
What do I do to get rid of this gap?
P.S. If possible, I'd like solutions that do not use the WriteableBitmapEx library, as I don't want to drag an entire library into my project for such a small task. Also, if possible, I'd like to leave the polygons' size and coordinates the same.
Related
I'm playing with this library because it seems quite useful for app developing that involves locations.
Q1: I was able to implement this in code-behind but I'm not able to transfer this to MVVM architecture. How can I do it?
Q2: if you see my code you can notice that I'm trying to use markers but for some reason I am only able to use marker.Shape (rectangle, ellipse, wtv). I want to use the standard ones from the GoogleMaps. Gmarkergoogle doesn't seems to exists anymore in GMap API. How can I do it? There is some other library to use? Need a little help over here as well.
OverviewView CODE
public partial class OverviewView : UserControl
{
public OverviewView()
{
InitializeComponent();
// Initialize map:
myMap.MapProvider = GoogleMapProvider.Instance;
GMaps.Instance.Mode = AccessMode.ServerOnly; // get tiles from server only
PointLatLng point = new PointLatLng(42.742826, -77.030212);
PointLatLng point1 = new PointLatLng(41.742826, -77.030212);
//Not use proxy
//Center map on a point
//GMapMarker marker = new GMapMarker(point);
var marker = new GMapMarker(point);
var marker1 = new GMapMarker(point1);
marker.Shape = new Rectangle
{
Width = 1,
Height = 100,
Stroke = Brushes.Black,
StrokeThickness = 1.5
};
marker1.Shape = new Rectangle
{
Width = 1,
Height = 100,
Stroke = Brushes.Black,
StrokeThickness = 1.5
};
myMap.Markers.Add(marker);
myMap.Markers.Add(marker1);
myMap.ZoomAndCenterMarkers(5);
myMap.Position = point;
/* GMapOverlay markersOverlay = new GMapOverlay("markers");
GMarkerGoogle marker = new GMarkerGoogle(new PointLatLng(-25.966688, 32.580528),
GMarkerGoogleType.green);
markersOverlay.Markers.Add(marker);
gmap.Overlays.Add(markersOverlay);*/
}
}
Best regards and thanks in advance for the time,
Antoine
I would like to now how to detect collision with lists of rectangles.
Rectanlge Player;
List<Rectangle> BlockHitBox = new List<Rectangle>();
I don't know the proper syntax for.
BlockHitBox.Intersect<>();
The code should detect if the rectangle hit boxes collide with the player hit box.
My goal is to make a room from small rectangles that the player cant pass through them so i need to detect more then one collision at a time ( for corners)
You can use the IntersectsWith method of the Rectangle object like so:
var commonSize = new Size(100, 100);
var player = new Rectangle(new Point(0,0), commonSize);
var blockHitBox = new List<Rectangle>
{
new Rectangle(new Point(0, 100), commonSize), // This one will not collide
new Rectangle(new Point(100, 0), commonSize), // This one will not collide
new Rectangle(new Point(0, 99), commonSize) // This one will collide
};
bool collision = blockHitBox.Any(item => item.IntersectsWith(player));
I have 4 float points (positions in 2D) and I want to draw and fill a polygon (with vertices at those 4 positions) in 2D.
How can I do that with sharpdx?
I have found how to draw and fill a polygon. I have used drawGeometry and fillGeometry methods of RenderTarget object.
I wont mention how to initialize the directx
PathGeometry geo1;
GeometrySink sink1;
FactoryD2D factory = new FactoryD2D();
var dpi = factory.DesktopDpi;
RenderTarget renderTarget;
renderTarget = new RenderTarget(factory, backBuffer, new RenderTargetProperties()
{
DpiX = dpi.Width,
DpiY = dpi.Height,
MinLevel = SharpDX.Direct2D1.FeatureLevel.Level_DEFAULT,
PixelFormat = new SharpDX.Direct2D1.PixelFormat(Format.Unknown, AlphaMode.Ignore),
Type = RenderTargetType.Hardware,
Usage = RenderTargetUsage.None
});
// and after all initialization
pta[0] = new SharpDX.Vector2(pts[4].X, pts[4].Y);
pta[1] = new SharpDX.Vector2(pts[5].X, pts[5].Y);
pta[2] = new SharpDX.Vector2(pts[6].X, pts[6].Y);
pta[3] = new SharpDX.Vector2(pts[7].X, pts[7].Y);
geo1 = new PathGeometry(factory);
sink1 = geo1.Open();
sink1.BeginFigure(pta[0], new FigureBegin());
sink1.AddLines(new SharpDX.Vector2[] { pta[1], pta[2], pta[3] });
sink1.EndFigure(new FigureEnd());
sink1.Close();
Color penColor = Color.Black;
SolidColorBrush penBrush = new SolidColorBrush(g, new SharpDX.Color(penColor.R, penColor.G, penColor.B));
Color color = AddColor(pt, zmin, zmax);
SolidColorBrush aBrush = new SolidColorBrush(g, new SharpDX.Color(color.R, color.G, color.B));
renderTarget.DrawGeometry(geo1, penBrush);
renderTarget.FillGeometry(geo1, aBrush);
geo1.Dispose();
sink1.Dispose();
You can add other geos and sinks in order to add more shapes on to it
Hope this help to somebody who is lost and trying to find an answer desperately like me
I have a bit of code that takes a number of Points and creates multiple LineSegments to build up a Path.
System.Windows.Shapes.Path pathSegment = new System.Windows.Shapes.Path();
PathFigure pathFig = new PathFigure();
PathGeometry pathGeo = new PathGeometry();
pathFig.StartPoint = new Point(pointData[0].X, pointData[0].Y);
for (int loop = 1; loop < pointData.Count; loop++)
{
LineSegment ls = new LineSegment();
ls.Point = new Point(pointData[loop].X, pointData[loop].Y);
pathFig.Segments.Add(ls);
}
pathGeo.Figures.Add(pathFig);
pathSegment.Data = pathGeo;
pathSegment.Stroke = brush;
pathSegment.StrokeThickness = 22;
This creates my line with a width of 22px (roughly). Now if you look at the actual Data for this you can only see the LineSegement elements, which essentially gives you an output like this, where the real line is in black and the actual displayed line is in grey (excuse the dodgy mspaint sketch):
Now I want to perform a StrokeContains on the Geometry to see if a specified Point is within the entire pathSegment above (grey area). What it actually does though is check against the LineSegments (the black line).
Is there a better way to build up the Path? or is there a way of converting the pathSegment, including the StrokeWidth to a new Path?
It should work if you use the proper Pen Thickness in the StrokeContains call:
Point point = ...
Pen pen = new Pen { Thickness = pathSegment.StrokeThickness };
bool contains = pathSegment.Data.StrokeContains(pen, point);
Alternatively you could simply do a hit test on the Path:
bool contains = pathSegment.InputHitTest(point) != null;
I was trying to create a brush that draws a geometry. Everything worked fine until I tried to add Dashing to the shape.
I found that when I create the geometry using Geometry.Parse, the dashed line appears correctly, but when I create it directly using StreamGeometryContext, nothing gets rendered.
This is the code I'm using:
private void RenderGeometryAndSetAsBackground()
{
Point startPoint = new Point(3505961.52400725, 3281436.57325874);
Point[] points = new Point[] {
new Point(3503831.75515445,3278705.9649394),
new Point(3503905.74802898,3278449.37713916),
new Point(3507242.57331039,3276518.41148474),
new Point(3507700.6914325,3276536.23547958),
new Point(3510146.73449577,3277964.12812859),
new Point(3509498.96473447,3278678.60178448),
new Point(3507412.1889951,3277215.64022219),
new Point(3504326.22698001,3278682.85514017),
new Point(3506053.34789057,3281390.66371786)};
string geom = "M3505961.52400725,3281436.57325874L3503831.75515445,3278705.9649394 3503905.74802898,3278449.37713916 3507242.57331039,3276518.41148474 3507700.6914325,3276536.23547958 3510146.73449577,3277964.12812859 3509498.96473447,3278678.60178448 3507412.1889951,3277215.64022219 3504326.22698001,3278682.85514017 3506053.34789057,3281390.66371786";
//Geometry geometry = StreamGeometry.Parse(geom);
StreamGeometry geometry = new StreamGeometry();
using (StreamGeometryContext sgc = geometry.Open())
{
sgc.BeginFigure(startPoint, false, true);
foreach (Point p in points)
{
sgc.LineTo(p, true, true);
}
}
Pen pen = new Pen(Brushes.Yellow, 3);
pen.DashStyle = new DashStyle(new double[] { 30, 30 }, 0);
//GeometryDrawing gd = new GeometryDrawing(null, pen, path.RenderedGeometry);
GeometryDrawing gd = new GeometryDrawing(null, pen, geometry);
DrawingBrush drawingBrush = new DrawingBrush(gd);
DrawingBrush tile = drawingBrush.Clone();
tile.Viewbox = new Rect(0.5, 0, 0.25, 0.25);
RenderTargetBitmap rtb = new RenderTargetBitmap(256, 256, 96, 96, PixelFormats.Pbgra32);
var drawingVisual = new DrawingVisual();
using (DrawingContext context = drawingVisual.RenderOpen())
{
context.DrawRectangle(tile, null, new Rect(0, 0, 256, 256));
}
rtb.Render(drawingVisual);
ImageBrush bgBrush = new ImageBrush(rtb);
Background = bgBrush;
}
When done that way, nothing is getting drawn. If I don't use dashing (or set the dashing to null) it works fine. It also works if I use the StreamGeometry.Parse(geom) and keeps the dashing.
Trying to call sgc.Close() didn't help. Currently my only workaround is to call:
geometry = Geometry.Parse(geometry.ToString());
which is not very nice...
What am I missing?
That's a pretty fascinating bug you got there, I can confirm it. Some ILSpy digging revealed the cause: the implicit BeginFigure call that is generated by Geometry.Parse sets the isFilled parameter to true, whereas you set it to false in your explicit StreamGeometryContext call. Change the second parameter in sgc.BeginFigure from false to true, and the dashed lines will render.
The WPF path markup syntax does not allow specifying whether any individual figure should be filled or not, so I suppose that's why the parser defaults to filling them all, just to be sure. But I can't see any good reason why dashed lines would require filled figures, that has to be a WPF bug.