Author’s Microblog:@GcsSloop

【 Related articles in this series 】

After the basic operation of Path and the Bezier curve of Path in the first two articles, this article will finally move on to the end of Path. After this article, most of the methods related to Path are covered, but there are still some interesting ways of playing Path, which will come in the future. Well, there will be the liberation of the peoples

Path Common methods table

Methods added later than API21(android version 5.0) have been removed from this table for compatibility. I can’t help but make fun of the fact that some of the overloading methods that seem easy to write wait until API21 to be added. The baby was devastated.

role Relevant methods note
The starting point of mobile moveTo Moves the starting position of the next operation
Set the end point setLastPoint Resets the position of the last point in the current path. If called before drawing, it has the same effect as moveTo
Connecting line lineTo Add a line to the Path between a point and the current point
A closed path close Connect the first point to the last point to form a closed region
Add content addRect, addRoundRect, addOval, addCircle, addPath, addArc, arcTo Add (rectangle, rounded rectangle, ellipse, circle, Path, arc) to current Path (note addArc and arcTo difference)
Whether is empty isEmpty Check whether Path is empty
Rectangle or not isRect Check whether path is a rectangle
Replace the path set Replace everything in the current path with the new path
Migration path offset Offsets previous operations on the current path (does not affect subsequent operations)
Bessel curve quadTo, cubicTo Are the methods of quadratic and cubic Bezier curves respectively
RXxx method rMoveTo, rLineTo, rQuadTo, rCubicTo The method without R is based on the origin coordinate system (offset), while the rXxx method is based on the current point coordinate system (offset).
Fill mode setFillType, getFillType, isInverseFillType, toggleInverseFillType Set, get, judge and toggle fill modes
Prompt method incReserve Indicates how many points Path has left to join(This approach seems to allow Path to optimize the storage structure)
Boolean operation (API19) op Boolean operation on two paths (take intersection, union, etc.)
Calculate the boundary computeBounds Compute the Path boundary
Reset the path reset, rewind Clear the contents of Path

Reset does not retain internal data structures, but retains FillType.

Rewind retains the internal data structure, but not the FillType
Matrix operations transform Matrix transformation

Second, Path method detailed explanation

RXxx method

This type of method looks very similar to the previous methods, but with an extra r in front of it. What is the difference between this rXxx and the previous methods?

The rXxx method uses relative position (based on the displacement of the current point), whereas the previous method used absolute position (based on the coordinates of the current coordinate system).

Here’s an example:

Path path = new Path(); Path. The moveTo (100100); Path. The lineTo (100200); canvas.drawPath(path,mDeafultPaint);

In this example, first move the point to coordinate (100,100), and then connect the points between (100,100) and (100,200). It is very simple, draw a vertical line, so let’s look at the next example:

Path path = new Path(); Path. The moveTo (100100); Path. RLineTo (100200); canvas.drawPath(path,mDeafultPaint);

In this example, replacing lineTo with rLineTo shows that the vertical line on the screen is now slanted. That’s because what we end up connecting is the line segment between 100,100 and 200, 300.

Before using rLineTo, the position of the current point is at (100,100); after using rLineTo(100,200), the position of the next point is obtained by adding the offset to the current point, i.e. (100+100, 100+200), so the final result is shown as above.

PS: rLineTo is only used as an example here. As long as you understand the difference between “absolute coordinates” and “relative coordinates”, other methods can be used for analogy.

Fill mode

As we learned in the previous article, Paint has three different styles: “Stroke”, “Fill” and “Stroke and fill”. Here we are looking at how different fill modes can affect the rendering effect of Paint when the latter two styles are used.

If we want to fill the inside of a shape with color, we need to figure out which part is the outside and which part is the inside. Machines are not as smart as we are. How do machines judge the inside and the outside?

There are generally two ways for the machine to judge the inside and outside of the graph:

PS: All graphs here are closed graphs, excluding the case that graphs are not closed.

methods Decision condition explain
Odd-even rule An odd number means inside the graph, an even number means outside the graph If a ray is drawn from any position p, p is the interior point of the graph if the number of edges intersecting the ray is odd, otherwise it is the exterior point.
Non-zero wrapping number rule If the number of circles is 0, it is inside the graph, and non-zero means it is outside the graph First turn the edges of the graph into vectors. Initialize the number of circles to zero. Let’s take another ray from any position P. As you move in the ray direction from point P, count the edges that pass through the ray in each direction. Each time an edge of the figure passes through the ray from right to left, the number of circles increases by 1, and from left to right, the number of circles decreases by 1. After processing all the related edges of the graph, p is the inner point if the number of circles is non-zero, otherwise, p is the outer point.

Let’s take a look at how both methods work.

Even-odd Rule

This one is relatively simple and easy to understand, with a simple example to illustrate.

There is a quadrilateral in the figure above, and we choose three points to determine whether these points are inside the figure.

P1: a ray is emitted from P1, and it is found that the number of intersecting edges of the graph with this ray is 0, even, so P1 point is outside the graph. P2: emits a ray from P2. It is found that the graph intersects the ray with an odd number of edges, so P2 is inside the graph. P3: a ray is emitted from P3, and it is found that the number of intersecting edges of the graph with this ray is 2, even, so P3 point is outside the graph.

Non-zero Winding Number Rule

The non-zero circle number rule is a bit more difficult to understand.

As we learned in the basic Operations of Path in the previous article, when adding graphs to Path, we need to specify whether to add graphs clockwise or counterclockwise. In addition, whether we use lineTo, quadTo, cubicTo or other wiring methods, they are all connected from one point to another point, in other words, Any line segment in the Path is directional, which is the basis for using the non-zero wrap number rule.

Again, we use a simple example to illustrate the use of the non-zero wrapping rule:

PS: Pay attention to the directionality of the line segment in the graph!

P1: a ray is emitted from point P1 and moves along the line of rays without intersecting the edge. The number of circles is 0, so P1 is outside the graph. P2: EMITS a ray from point P2, moving in the direction of the ray, intersecting the left side of the graph point, which passes through the ray from left to right. The number of orbits is -1, and finally the number of orbits is -1, so P2 is inside the graph. P3: emits a ray from point P3, moving in the direction of the ray. At the first intersection, the bottom edge passes through the ray from right to left with the number of orbits +1. At the second intersection, the right side passes through the ray from left to right with the number of orbits -1 and the final number of orbits 0, so P3 is outside the graph.

Generally, the judgment results of the two methods are the same, but there are also cases where the judgment results of the two methods are different, such as the following case:

Note the direction of the graph line segment, not detailed explanation, use the above method to judge.

Self intersecting figure

Self-intersecting graph definition: a polygon has other common points in the plane besides its vertices.

Simply mention the self-intersecting graph, understand the concept, the following is a simple self-intersecting graph:

Fill mode in Android

There are four fill modes in Android, which are an enumeration wrapped in Path.

model Introduction to the
EVEN_ODD Odd-even rule
INVERSE_EVEN_ODD Anti-even rule
WINDING Non-zero wrapping number rule
INVERSE_WINDING Anti-non-zero wrapping number rule

We can see that there are four patterns up here, divided into two pairs, for example, the “odd-even rule” and the “anti-odd-even rule” are a pair, what is the relationship between them?

Inverse and mean “opposite”, indicating that the Inverse parity rule is exactly the opposite of the parity rule. For example, for a rectangle, the inside of the rectangle will be filled with the parity rule, while the outside will be filled with the Inverse parity rule, which will be shown in the code below.

Android methods related to fill mode

These are all methods in Path.

methods role
setFillType Setting the Fill Rule
getFillType Gets the current fill rule
isInverseFillType Check whether it is INVERSE
toggleInverseFillType Toggle fill rules (i.e., toggle between old rules and reverse rules)

Example demonstration:

This demo is intended to help you understand some of the difficult and confusing problems in the fill mode. For some of the simpler problems, you can verify them by yourself.

Parity rules and anti-parity rules
mDeafultPaint.setStyle(Paint.Style.FILL); // Set canvas mode to fill canvas.translate(mViewWidth / 2, mViewHeight / 2); // Move canvas (coordinate system) Path Path = new Path(); // create Path // path.setfillType (path.filltype. EVEN_ODD); // Set the Path filling mode to the parity rule path.setFillType(path.filltype. INVERSE_WINDING); Path.addrect (-200,-200,200,200, path.direction.cw); // Add a rectangle to Path

The following two pictures are drawn under the condition of odd-even rule and anti-odd-even rule respectively, and it can be seen that the filling areas are just opposite:

PS: White is the background color and black is the fill color.

The influence of the direction of graph edge on the regular filling result of non-zero odd-even circle number

We have previously discussed the role of clockwise and counterclockwise in adding graphics to Path, which, in addition to the convenience notes we discussed last time, is another important role covered in this article: “as a basis for the rule of non-zero circle numbers.”

We have had a rough understanding of how the direction of the graphic edge affects the filling effect. Let’s verify it here:

mDeafultPaint.setStyle(Paint.Style.FILL); // Set the brush mode to fill canvas.translate(mViewWidth / 2, mViewHeight / 2); // Move canvas (seat) Path Path = new Path(); // path.addRect(-200, -200, 200, 200, path.direction.cw); path.addRect(-200, -200, 200, 200, Path.Direction.CCW); // Add the big square path.addrect (-400, -400, 400, 400, path.direction.ccw); path.setFillType(Path.FillType.WINDING); // Set Path to a non-zero loop rule, canvas.drawPath(Path, mDeafultPaint); / / draw the Path

Boolean operation (API19)

Boolean operation is very similar to the set operation we learned in middle school. As long as we know the set operation is medium intersection, union, difference and so on, it is easy to understand the Boolean operation.

Boolean operation is the operation between two paths. The main function is to synthesize some relatively complex or difficult to get directly from some simple graphs by some rules.

For example, the Yin and Yang fish in Tai Chi may need six Bezier curves if it is made with Bezier curves, but here we can use four paths to get it through Boolean operation, and it is relatively easier to understand.

    canvas.translate(mViewWidth / 2, mViewHeight / 2);

    Path path1 = new Path();
    Path path2 = new Path();
    Path path3 = new Path();
    Path path4 = new Path();

    path1.addCircle(0, 0, 200, Path.Direction.CW);
    path2.addRect(0, -200, 200, 200, Path.Direction.CW);
    path3.addCircle(0, -100, 100, Path.Direction.CW);
    path4.addCircle(0, 100, 100, Path.Direction.CCW);


    path1.op(path2, Path.Op.DIFFERENCE);
    path1.op(path3, Path.Op.UNION);
    path1.op(path4, Path.Op.DIFFERENCE);

    canvas.drawPath(path1, mDeafultPaint);

After demonstrating the power of Boolean operations, let’s take a look at the core of Boolean operations: Boolean logic.

Boolean operations on Path have five kinds of logic, as follows:

Logical name analogy instructions Schematic diagram
DIFFERENCE Difference set What’s left after subtracting Path2 from Path1
REVERSE_DIFFERENCE Difference set What’s left after subtracting Path1 from Path2
INTERSECT intersection The part of Path1 that intersects Path2
UNION And set Contains all Path1 and Path2
XOR Exclusive or Contains Path1 and Path2 but does not include the sections where they intersect

Boolean operation method

Through the previous theoretical knowledge foundation, I believe that we have a basic understanding and understanding of Boolean operation, we use the code to demonstrate Boolean operation:

Boolean operations in Path have two methods

    boolean op (Path path, Path.Op op)
    boolean op (Path path1, Path path2, Path.Op op)

The return values in the two methods are used to determine the success of the Boolean operation as follows:

// Perform Boolean operations on path1 and path2, specified by the second argument, and store the results to path1. path1.op(path2, Path.Op.DIFFERENCE); // Perform Boolean operations on path1 and path2, specified by the third argument, and store the results to path3. path3.op(path1, path2, Path.Op.DIFFERENCE)Copy the code

Example Boolean operations

Code:

int x = 80; int r = 100; Canvas. Translate (250, 0); Path path1 = new Path(); Path path2 = new Path(); Path pathOpResult = new Path(); path1.addCircle(-x, 0, r, Path.Direction.CW); path2.addCircle(x, 0, r, Path.Direction.CW); pathOpResult.op(path1,path2, Path.Op.DIFFERENCE); canvas.translate(0, 200); Canvas. DrawText (" DIFFERENCE ", 240, 0, mDeafultPaint); canvas.drawPath(pathOpResult,mDeafultPaint); pathOpResult.op(path1,path2, Path.Op.REVERSE_DIFFERENCE); canvas.translate(0, 300); Canvas. DrawText (" REVERSE_DIFFERENCE ", 240, 0, mDeafultPaint); canvas.drawPath(pathOpResult,mDeafultPaint); pathOpResult.op(path1,path2, Path.Op.INTERSECT); canvas.translate(0, 300); Canvas. DrawText (" intersects ", 240, 0, mDeafultPaint); canvas.drawPath(pathOpResult,mDeafultPaint); pathOpResult.op(path1,path2, Path.Op.UNION); canvas.translate(0, 300); Canvas. DrawText (" UNION ", 240, 0, mDeafultPaint); canvas.drawPath(pathOpResult,mDeafultPaint); pathOpResult.op(path1,path2, Path.Op.XOR); canvas.translate(0, 300); Canvas. DrawText (" XOR ", 240, 0, mDeafultPaint); canvas.drawPath(pathOpResult,mDeafultPaint);

Calculate the boundary

This method is used to calculate the space occupied by the Path and its location.

    void computeBounds (RectF bounds, boolean exact)

It takes two arguments:

parameter role
bounds The measurements will go into this rectangle
exact Whether the measurement is accurate, this parameter has been abandoned, generally write true.

For more information about exact, see Google’s official submission record Path.computeBounds()

Example of computed boundary

A simple example of calculating path boundaries.

Code:

/ / move canvas, mViewWidth and mViewHeight canvas in onSizeChanged method. Translate (mViewWidth / 2, mViewHeight / 2); RectF rect1 = new RectF(); Path Path = new Path(); // Create Path and add some content path.lineto (100,-50); Path. The lineTo (50, 100); path.close(); Path. AddCircle (- 100,0,100 path. Direction. The CW); path.computeBounds(rect1,true); // Measure Path canvas. DrawPath (Path,mDeafultPaint); // Draw Path mdeafultpaint.setstyle (paint.style.stroke); mDeafultPaint.setColor(Color.RED); canvas.drawRect(rect1,mDeafultPaint); // Draw boundaries

Reset the path

There are two methods to reset a Path: reset and rewind.

methods Whether to retain FillType Whether to retain the original data structure
reset is no
rewind no is

When should you choose between these two methods?

Select the weight: FillType > Data structure

Because “FillType” affects the display effect, and “data structure” affects the reconstruction speed.

conclusion

This is the end of the common Path method, I hope to help you to deepen the understanding of the use of Path, so that you can use Path to have fun. ( ̄▽ ̄)

(,,, ₃,,,)

PS: Due to my limited level, there may be misunderstandings or inaccuracies in some places. If you have any questions, please submit Issues for feedback.

About Me

Author’s Microblog:@GcsSloop

The resources

Googlecodoc.com puteBounds() path.reset vs. path.rewind