How To Draw A Path In Blender
The Android Canvas API provides drawing operations for standard primitive shapes like lines or rectangles, only it'due south more often than not easier to utilise more flexible Path primitives for drawing complex shapes. In this blog post, nosotros'll demonstrate how to utilise the path API in exactly this mode. This is just a basic case, but it could be interesting if y'all want to build your ain custom views that crave irregular filled shapes with borders.
What Is Path?
The Path class represents a compound geometric path that tin exist drawn to Canvas. A path can include multiple directly lines, quadratic or cubic curves, or simple geometric shapes like arcs, circles, and rectangles. It can be drawn via Canvas#drawPath() in custom views, in drawables, or to bitmaps (if the canvas was backed by 1). A path tin can likewise be fatigued either filled or stroked, depending on the style of the paint used for cartoon.
Drawing Unproblematic Shapes
Before we get to the example of cartoon complex shapes, let's start with uncomplicated ones. You lot can easily describe simple shapes with borders by get-go drawing a shape filled with a border colour. And so describe a shape with a smaller border width and filled with a fill color on top of the get-go shape. Equally an example, here'south how to draw a rounded rectangle with a border.
The most straightforward arroyo to drawing rounded rectangles with filled borders is to employ Canvas#drawRoundRect:
// Ready paints beforehand to prevent allocations when drawing. val borderPaint = Paint() borderPaint.setStyle(Pigment.Mode.Fill up) borderPaint.setColor(borderColor) borderPaint.setAntiAlias(true) borderPaint.setDither(true) val fillPaint = Pigment() fillPaint.setStyle(Paint.Way.Make full) fillPaint.setColor(fillColor) fillPaint.setAntiAlias(truthful) fillPaint.setDither(truthful) ... // Draw a rounded rectangle with a dark color that will serve equally the edge. sheet.drawRoundRect(rect, cornerRadius, cornerRadius, borderPaint) // And so depict a smaller rounded rectangle with a lighter color that will serve as the background. rect.inset(borderWidth, borderWidth) if (rect.width() > 0 && rect.height() > 0) { sheet.drawRoundRect(rect, cornerRadius, cornerRadius, fillPaint) }
// Set paints beforehand to prevent allocations when drawing. final Paint borderPaint = new Pigment(); borderPaint.setStyle(Paint.Fashion.FILL); borderPaint.setColor(borderColor); borderPaint.setAntiAlias(true); borderPaint.setDither(true); terminal Paint fillPaint = new Paint(); fillPaint.setStyle(Pigment.Style.Fill up); fillPaint.setColor(fillColor); fillPaint.setAntiAlias(truthful); fillPaint.setDither(true); ... // Draw a rounded rectangle with a night colour that will serve as the border. canvas.drawRoundRect(rect, cornerRadius, cornerRadius, borderPaint); // Then draw a smaller rounded rectangle with a lighter color that will serve as the background. rect.inset(borderWidth, borderWidth); if (rect.width() > 0 && rect.acme() > 0) { canvas.drawRoundRect(rect, cornerRadius, cornerRadius, fillPaint); }
Drawing with Paths
Now we'll testify how to achieve the same thing by using paths with rounded rectangle information. Start, we'll describe the path make full:
// Prepare fill path. val fillPath = Path() fillPath.addRoundRect(rect, cornerRadius, cornerRadius, Path.Management.CW) ... // Draw path to canvas. sail.drawPath(fillPath, fillPaint)
// Set make full path. Path fillPath = new Path(); fillPath.addRoundRect(rect, cornerRadius, cornerRadius, Path.Direction.CW); ... // Draw path to sheet. canvas.drawPath(fillPath, fillPaint);
Adjacent, we'll describe the path outline on elevation:
We combine two rounded rectangle paths here. The starting time 1 represents the outer rounder rectangle, and the second one represents its inner path. We then gear up path'southward fill type to FillType#EVEN_ODD. This tells Canvas drawing routines that nosotros want to make full within of our path with the paint's color:
// Prepare the border path. val borderPath = Path() // Add together the outer rounded rectangle. borderPath.addRoundRect(rect, cornerRadius, cornerRadius, Path.Direction.CW) // Add the inner rounded rectangle. val innerRect = RectF(rect) innerRect.inset(borderWidth, borderWidth) if (innerRect.width() > 0 && innerRect.height() > 0) { borderPath.addRoundRect(innerRect, cornerRadius, cornerRadius, Path.Direction.CW) } // Using the EVEN_ODD fill up type will outcome in a filled space between the two rounded rectangles we created. borderPath.setFillType(Path.FillType.EVEN_ODD) ... // Depict the path to canvas. sail.drawPath(borderPath, borderPaint)
// Prepare the border path. Path borderPath = new Path(); // Add together the outer rounded rectangle. borderPath.addRoundRect(rect, cornerRadius, cornerRadius, Path.Direction.CW); // Add together the inner rounded rectangle. final RectF innerRect = new RectF(rect); innerRect.inset(borderWidth, borderWidth); if (innerRect.width() > 0 && innerRect.tiptop() > 0) { borderPath.addRoundRect(innerRect, cornerRadius, cornerRadius, Path.Direction.CW); } // Using the EVEN_ODD fill type will upshot in a filled space between the 2 rounded rectangles we created. borderPath.setFillType(Path.FillType.EVEN_ODD); ... // Describe the path to canvas. canvass.drawPath(borderPath, borderPaint);
Note: You should e'er prepare path and paint objects beforehand to preclude excessive allocations while drawing.
Drawing Complex Shapes
Using the rectangle drawing commands of Canvass was much simpler than using paths, merely I included this example for illustrative purposes. Nosotros'll at present extend the concept to cartoon more complex filled paths with borders.
In this case, nosotros'll use the following path data:
val vectorPath = Path() vectorPath.moveTo(half-dozen.5f, 79.99f) vectorPath.lineTo(37.21f, 50.5f) vectorPath.lineTo(6.5f, 19.79f) vectorPath.lineTo(18.79f, vii.5f) vectorPath.lineTo(49.5f, 38.21f) vectorPath.lineTo(80.21f, 7.5f) vectorPath.lineTo(92.5f, nineteen.79f) vectorPath.lineTo(61.79f, 50.5f) vectorPath.lineTo(92.5f, 79.99f) vectorPath.lineTo(fourscore.21f, 93.5f) vectorPath.lineTo(49.5f, 62.79f) vectorPath.lineTo(18.79f, 93.5f) vectorPath.close()
Path vectorPath = new Path(); vectorPath.moveTo(six.5f, 79.99f); vectorPath.lineTo(37.21f, l.5f); vectorPath.lineTo(six.5f, nineteen.79f); vectorPath.lineTo(18.79f, 7.5f); vectorPath.lineTo(49.5f, 38.21f); vectorPath.lineTo(fourscore.21f, 7.5f); vectorPath.lineTo(92.5f, 19.79f); vectorPath.lineTo(61.79f, 50.5f); vectorPath.lineTo(92.5f, 79.99f); vectorPath.lineTo(fourscore.21f, 93.5f); vectorPath.lineTo(49.5f, 62.79f); vectorPath.lineTo(18.79f, 93.5f); vectorPath.close();
This data is in a [0, 0, 100, 100] coordinate space. We'll transform the data to fit the required bounds:
val width = premises.width() val height = premises.tiptop() // Calculate a transformation scale between [0, 0, 100, 100] and [0, 0, width, height]. val scaleX = width / 100.0f val scaleY = summit / 100.0f // Create the transformation matrix. val drawMatrix = Matrix() drawMatrix.setScale(scaleX, scaleY) // Now transform the vector path. vectorPath.transform(drawMatrix)
int width = bounds.width(); int height = bounds.height(); // Calculate a transformation scale between [0, 0, 100, 100] and [0, 0, width, height]. bladder scaleX = width / 100.0f; float scaleY = elevation / 100.0f; // Create the transformation matrix. concluding Matrix drawMatrix = new Matrix(); drawMatrix.setScale(scaleX, scaleY); // Now transform the vector path. vectorPath.transform(drawMatrix);
Next, nosotros'll demand to create proper paints for drawing the filled path and path outline:
val fillPaint = Paint() fillPaint.mode = Paint.Fashion.FILL fillPaint.color = fillColor fillPaint.isAntiAlias = true fillPaint.isDither = true val borderPaint = Pigment() borderPaint.style = Paint.Mode.STROKE borderPaint.strokeWidth = borderWidth borderPaint.color = borderColor borderPaint.isAntiAlias = true borderPaint.isDither = truthful
Paint fillPaint = new Paint(); fillPaint.setStyle(Paint.Fashion.Fill); fillPaint.setColor(fillColor); fillPaint.setAntiAlias(truthful); fillPaint.setDither(true); Paint borderPaint = new Paint(); borderPaint.setStyle(Paint.Manner.STROKE); borderPaint.setStrokeWidth(borderWidth); borderPaint.setColor(borderColor); borderPaint.setAntiAlias(truthful); borderPaint.setDither(true);
Finally, we can describe the final path:
// First draw the make full path. canvas.drawPath(fillPath, fillPaint) // Then overlap this with the border path. canvas.drawPath(borderPath, borderPaint)
// First draw the fill path. canvas.drawPath(fillPath, fillPaint); // Then overlap this with the edge path. canvas.drawPath(borderPath, borderPaint);
Conclusion
We've shown how to use paths on Android to describe complex shapes programatically. As y'all can see, the Path class exposes a flexible way of drawing complex geometric shapes. Hopefully this article will be useful for yous when working on custom views or drawables that require complex shape drawing.
Source: https://pspdfkit.com/blog/2018/using-paths-to-draw-shapes-with-borders/
Posted by: furrwassaimmat.blogspot.com

0 Response to "How To Draw A Path In Blender"
Post a Comment