Skip to content

Instantly share code, notes, and snippets.

@rajsuvariya
Created February 11, 2021 07:56
Show Gist options
  • Save rajsuvariya/6b99ba4575b74f525ec7dd7948d01af4 to your computer and use it in GitHub Desktop.
Save rajsuvariya/6b99ba4575b74f525ec7dd7948d01af4 to your computer and use it in GitHub Desktop.
A trepezoid view which provides curv functionality when dragged from top middle position
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Point;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.Region;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
public class TrepezoidView extends View implements View.OnTouchListener {
private Paint paintRect, paintCircle;
public int LEFT;
public int TOP;
public int RIGHT;
public int BOTTOM;
Point CIRCLE_TOP_LEFT;
Point CIRCLE_TOP_RIGHT;
Point CIRCLE_BOTTOM_LEFT;
Point CIRCLE_BOTTOM_RIGHT;
private int lastX, lastY;
private int dragX, dragY;
private int curveX = -1, curveY = -1;
Bitmap image;
Matrix matrix2;
boolean isTouchCirclePoints = true;
private boolean isInEdit = true;
Paint mPaint;
int displayWidth;
private Rect dst_curve = new Rect();
private Rect dst_resize_left = new Rect();
private Rect dst_resize_right = new Rect();
private Rect dst_resize_bottom = new Rect();
private Rect dst_corner_top_left = new Rect();
private Rect dst_corner_top_right = new Rect();
private Rect dst_corner_bottom_left = new Rect();
private Rect dst_corner_bottom_right = new Rect();
private boolean isBeingDragged = true;
private PorterDuffXfermode porterDuffXfermode;
private final int CIRCLE_RADIUS = 20;
private int TOUCH_CIRCLE_RADIUS = 60;
private Bitmap curveBitmap;
private Bitmap resizeHorizontalBitmap;
private Bitmap resizeVerticalBitmap;
private Bitmap cornerBitmap;
public TrepezoidView(Context context) {
super(context);
// TODO Auto-generated constructor stub
init();
}
public TrepezoidView(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
init();
}
public TrepezoidView(Context context, AttributeSet attrs,
int defStyle) {
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
init();
}
private void init() {
this.setOnTouchListener(this);
paintRect = new Paint();
paintRect.setColor(0xffff0000);
paintRect.setAntiAlias(true);
paintRect.setDither(true);
paintRect.setStyle(Paint.Style.STROKE);
paintRect.setStrokeJoin(Paint.Join.BEVEL);
paintRect.setStrokeCap(Paint.Cap.BUTT);
paintRect.setStrokeWidth(3);
paintRect = new Paint();
paintRect.setColor(0xffff0000);
paintRect.setAntiAlias(true);
paintRect.setDither(true);
paintRect.setStyle(Paint.Style.STROKE);
paintRect.setStrokeJoin(Paint.Join.BEVEL);
paintRect.setStrokeCap(Paint.Cap.BUTT);
paintRect.setStrokeWidth(10);
paintCircle = new Paint();
paintCircle.setColor(0xff0000ff);
paintCircle.setAntiAlias(true);
paintCircle.setDither(true);
paintCircle.setStyle(Paint.Style.FILL_AND_STROKE);
paintCircle.setStrokeJoin(Paint.Join.BEVEL);
paintCircle.setStrokeCap(Paint.Cap.BUTT);
mPaint = new Paint();
LEFT = 0;
TOP = 0;
RIGHT = 440;
BOTTOM = 520;
CIRCLE_TOP_LEFT = new Point(LEFT, TOP);
CIRCLE_TOP_RIGHT = new Point(RIGHT, TOP);
CIRCLE_BOTTOM_LEFT = new Point(LEFT, BOTTOM);
CIRCLE_BOTTOM_RIGHT = new Point(RIGHT, BOTTOM);
curveBitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_curve);
resizeHorizontalBitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_double_arrow);
resizeVerticalBitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_double_arrow_verticle);
cornerBitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_corner);
matrix2 = new Matrix();
}
public void setImageRes(int resId) {
image = BitmapFactory.decodeResource(getResources(), resId);
invalidate();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
displayWidth = getContext().getResources().getDisplayMetrics().widthPixels;
}
@Override
protected void onDraw(Canvas canvas) {
setLayerType(View.LAYER_TYPE_SOFTWARE, null);
// Free Transform bitmap
int bw = image.getWidth();
int bh = image.getHeight();
float[] pts = {
// source
0, 0,
0, bh,
bw, bh,
bw, 0,
// destination
0, 0,
0, 0,
0, 0,
0, 0};
pts[8] = CIRCLE_TOP_LEFT.x;
pts[9] = CIRCLE_TOP_LEFT.y;
pts[10] = CIRCLE_BOTTOM_LEFT.x;
pts[11] = CIRCLE_BOTTOM_LEFT.y;
pts[12] = CIRCLE_BOTTOM_RIGHT.x;
pts[13] = CIRCLE_BOTTOM_RIGHT.y;
pts[14] = CIRCLE_TOP_RIGHT.x;
pts[15] = CIRCLE_TOP_RIGHT.y;
matrix2.setPolyToPoly(pts, 0, pts, 8, 4);
isTouchCirclePoints = false;
canvas.drawBitmap(image, matrix2, null);
porterDuffXfermode = new PorterDuffXfermode(PorterDuff.Mode.SRC_OUT);
mPaint.setXfermode(porterDuffXfermode);
mPaint.setColor(Color.TRANSPARENT);
Path oval = new Path();
oval.setFillType(Path.FillType.INVERSE_EVEN_ODD);
int left = CIRCLE_TOP_LEFT.x;
int top = CIRCLE_TOP_LEFT.y;
int right = CIRCLE_TOP_RIGHT.x;
int bottom = (top + (curveY - CIRCLE_TOP_LEFT.y));
oval.addOval(left, top, right, bottom, Path.Direction.CW);
Region region = new Region();
region.setPath(oval, new Region(0, 0, displayWidth, top + (curveY - CIRCLE_TOP_LEFT.y) / 2));
canvas.drawPath(region.getBoundaryPath(), mPaint);
dst_curve.left = (int) ((CIRCLE_TOP_LEFT.x + CIRCLE_TOP_RIGHT.x) / 2f - TOUCH_CIRCLE_RADIUS);
dst_curve.right = (int) ((CIRCLE_TOP_LEFT.x + CIRCLE_TOP_RIGHT.x) / 2f + TOUCH_CIRCLE_RADIUS);
dst_curve.top = (int) ((CIRCLE_TOP_LEFT.y + CIRCLE_TOP_RIGHT.y) / 2f - TOUCH_CIRCLE_RADIUS);
dst_curve.bottom = (int) ((CIRCLE_TOP_LEFT.y + CIRCLE_TOP_RIGHT.y) / 2f + TOUCH_CIRCLE_RADIUS);
dst_resize_left.left = (int) ((CIRCLE_TOP_LEFT.x + CIRCLE_BOTTOM_LEFT.x) / 2f - TOUCH_CIRCLE_RADIUS);
dst_resize_left.right = (int) ((CIRCLE_TOP_LEFT.x + CIRCLE_BOTTOM_LEFT.x) / 2f + TOUCH_CIRCLE_RADIUS);
dst_resize_left.top = (int) ((CIRCLE_TOP_LEFT.y + CIRCLE_BOTTOM_LEFT.y) / 2f - TOUCH_CIRCLE_RADIUS);
dst_resize_left.bottom = (int) ((CIRCLE_TOP_LEFT.y + CIRCLE_BOTTOM_LEFT.y) / 2f + TOUCH_CIRCLE_RADIUS);
dst_resize_right.left = (int) ((CIRCLE_TOP_RIGHT.x + CIRCLE_BOTTOM_RIGHT.x) / 2f - TOUCH_CIRCLE_RADIUS);
dst_resize_right.right = (int) ((CIRCLE_TOP_RIGHT.x + CIRCLE_BOTTOM_RIGHT.x) / 2f + TOUCH_CIRCLE_RADIUS);
dst_resize_right.top = (int) ((CIRCLE_TOP_RIGHT.y + CIRCLE_BOTTOM_RIGHT.y) / 2f - TOUCH_CIRCLE_RADIUS);
dst_resize_right.bottom = (int) ((CIRCLE_TOP_RIGHT.y + CIRCLE_BOTTOM_RIGHT.y) / 2f + TOUCH_CIRCLE_RADIUS);
dst_resize_bottom.left = (int) ((CIRCLE_BOTTOM_LEFT.x + CIRCLE_BOTTOM_RIGHT.x) / 2f - TOUCH_CIRCLE_RADIUS);
dst_resize_bottom.right = (int) ((CIRCLE_BOTTOM_LEFT.x + CIRCLE_BOTTOM_RIGHT.x) / 2f + TOUCH_CIRCLE_RADIUS);
dst_resize_bottom.top = (int) ((CIRCLE_BOTTOM_LEFT.y + CIRCLE_BOTTOM_RIGHT.y) / 2f - TOUCH_CIRCLE_RADIUS);
dst_resize_bottom.bottom = (int) ((CIRCLE_BOTTOM_LEFT.y + CIRCLE_BOTTOM_RIGHT.y) / 2f + TOUCH_CIRCLE_RADIUS);
dst_corner_top_left.left = CIRCLE_TOP_LEFT.x - TOUCH_CIRCLE_RADIUS;
dst_corner_top_left.right = CIRCLE_TOP_LEFT.x + TOUCH_CIRCLE_RADIUS;
dst_corner_top_left.top = CIRCLE_TOP_LEFT.y - TOUCH_CIRCLE_RADIUS;
dst_corner_top_left.bottom = CIRCLE_TOP_LEFT.y + TOUCH_CIRCLE_RADIUS;
dst_corner_top_right.left = CIRCLE_TOP_RIGHT.x - TOUCH_CIRCLE_RADIUS;
dst_corner_top_right.right = CIRCLE_TOP_RIGHT.x + TOUCH_CIRCLE_RADIUS;
dst_corner_top_right.top = CIRCLE_TOP_RIGHT.y - TOUCH_CIRCLE_RADIUS;
dst_corner_top_right.bottom = CIRCLE_TOP_RIGHT.y + TOUCH_CIRCLE_RADIUS;
dst_corner_bottom_left.left = CIRCLE_BOTTOM_LEFT.x - TOUCH_CIRCLE_RADIUS;
dst_corner_bottom_left.right = CIRCLE_BOTTOM_LEFT.x + TOUCH_CIRCLE_RADIUS;
dst_corner_bottom_left.top = CIRCLE_BOTTOM_LEFT.y - TOUCH_CIRCLE_RADIUS;
dst_corner_bottom_left.bottom = CIRCLE_BOTTOM_LEFT.y + TOUCH_CIRCLE_RADIUS;
dst_corner_bottom_right.left = CIRCLE_BOTTOM_RIGHT.x - TOUCH_CIRCLE_RADIUS;
dst_corner_bottom_right.right = CIRCLE_BOTTOM_RIGHT.x + TOUCH_CIRCLE_RADIUS;
dst_corner_bottom_right.top = CIRCLE_BOTTOM_RIGHT.y - TOUCH_CIRCLE_RADIUS;
dst_corner_bottom_right.bottom = CIRCLE_BOTTOM_RIGHT.y + TOUCH_CIRCLE_RADIUS;
if (isInEdit) {
// line left
canvas.drawLine(CIRCLE_TOP_LEFT.x, CIRCLE_TOP_LEFT.y, CIRCLE_BOTTOM_LEFT.x, CIRCLE_BOTTOM_LEFT.y, paintRect);
// line top
canvas.drawLine(CIRCLE_TOP_LEFT.x, CIRCLE_TOP_LEFT.y, CIRCLE_TOP_RIGHT.x, CIRCLE_TOP_RIGHT.y, paintRect);
// line right
canvas.drawLine(CIRCLE_TOP_RIGHT.x, CIRCLE_TOP_RIGHT.y, CIRCLE_BOTTOM_RIGHT.x, CIRCLE_BOTTOM_RIGHT.y, paintRect);
// line bottom
canvas.drawLine(CIRCLE_BOTTOM_LEFT.x, CIRCLE_BOTTOM_LEFT.y, CIRCLE_BOTTOM_RIGHT.x, CIRCLE_BOTTOM_RIGHT.y, paintRect);
// circle top left
canvas.drawBitmap(cornerBitmap, null, dst_corner_top_left, null);
// circle top right
canvas.drawBitmap(cornerBitmap, null, dst_corner_top_right, null);
// circle bottom left
canvas.drawBitmap(cornerBitmap, null, dst_corner_bottom_left, null);
// circle bottom right
canvas.drawBitmap(cornerBitmap, null, dst_corner_bottom_right, null);
// horizontal stretch left
canvas.drawBitmap(resizeHorizontalBitmap, null, dst_resize_left, null);
// horizontal stretch right
canvas.drawBitmap(resizeHorizontalBitmap, null, dst_resize_right, null);
// curve top
canvas.drawBitmap(curveBitmap, null, dst_curve, null);
// vertical stretch bottom
canvas.drawBitmap(resizeVerticalBitmap, null, dst_resize_bottom, null);
}
super.onDraw(canvas);
}
@Override
public boolean onTouch(View view, MotionEvent event) {
boolean handled = true;
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
if (isInCircle(event, CIRCLE_TOP_LEFT, TOUCH_CIRCLE_RADIUS) ||
isInCircle(event, CIRCLE_TOP_RIGHT, TOUCH_CIRCLE_RADIUS) ||
isInCircle(event, CIRCLE_BOTTOM_LEFT, TOUCH_CIRCLE_RADIUS) ||
isInCircle(event, CIRCLE_BOTTOM_RIGHT, TOUCH_CIRCLE_RADIUS) ||
inCircle(event.getX(), event.getY(), (CIRCLE_TOP_LEFT.x + CIRCLE_BOTTOM_LEFT.x) / 2f, (CIRCLE_TOP_LEFT.y + CIRCLE_BOTTOM_LEFT.y) / 2f, TOUCH_CIRCLE_RADIUS) ||
inCircle(event.getX(), event.getY(), (CIRCLE_TOP_RIGHT.x + CIRCLE_BOTTOM_RIGHT.x) / 2f, (CIRCLE_TOP_RIGHT.y + CIRCLE_BOTTOM_RIGHT.y) / 2f, TOUCH_CIRCLE_RADIUS) ||
inCircle(event.getX(), event.getY(), (CIRCLE_BOTTOM_LEFT.x + CIRCLE_BOTTOM_RIGHT.x) / 2f, (CIRCLE_BOTTOM_LEFT.y + CIRCLE_BOTTOM_RIGHT.y) / 2f, TOUCH_CIRCLE_RADIUS)) {
isBeingDragged = false;
} else if (inCircle(event.getX(), event.getY(), (CIRCLE_TOP_LEFT.x + CIRCLE_TOP_RIGHT.x) / 2f, (CIRCLE_TOP_LEFT.y + CIRCLE_TOP_RIGHT.y) / 2f, TOUCH_CIRCLE_RADIUS)) {
if (curveX == -1) {
curveX = (int) event.getX();
}
if (curveY == -1) {
curveY = (int) event.getY();
}
isBeingDragged = false;
} else if (isInBitmap(event)) {
dragX = (int) event.getX();
dragY = (int) event.getY();
isBeingDragged = true;
} else {
handled = false;
}
break;
case MotionEvent.ACTION_MOVE:
lastX = (int) event.getX();
lastY = (int) event.getY();
if (inCircle(lastX, lastY, CIRCLE_TOP_LEFT.x, CIRCLE_TOP_LEFT.y, TOUCH_CIRCLE_RADIUS)) {
isTouchCirclePoints = true;
CIRCLE_TOP_LEFT.set(lastX, lastY);
} else if (inCircle(lastX, lastY, CIRCLE_TOP_RIGHT.x, CIRCLE_TOP_RIGHT.y, TOUCH_CIRCLE_RADIUS)) {
isTouchCirclePoints = true;
CIRCLE_TOP_RIGHT.set(lastX, lastY);
} else if (inCircle(lastX, lastY, CIRCLE_BOTTOM_LEFT.x, CIRCLE_BOTTOM_LEFT.y, TOUCH_CIRCLE_RADIUS)) {
isTouchCirclePoints = true;
CIRCLE_BOTTOM_LEFT.set(lastX, lastY);
} else if (inCircle(lastX, lastY, CIRCLE_BOTTOM_RIGHT.x, CIRCLE_BOTTOM_RIGHT.y, TOUCH_CIRCLE_RADIUS)) {
isTouchCirclePoints = true;
CIRCLE_BOTTOM_RIGHT.set(lastX, lastY);
} else if (inCircle(lastX, lastY, (CIRCLE_TOP_LEFT.x + CIRCLE_BOTTOM_LEFT.x) / 2f, (CIRCLE_TOP_LEFT.y + CIRCLE_BOTTOM_LEFT.y) / 2f, TOUCH_CIRCLE_RADIUS)) {
isTouchCirclePoints = true;
int diff = (int) (lastX - (CIRCLE_TOP_LEFT.x + CIRCLE_BOTTOM_LEFT.x) / 2f);
CIRCLE_TOP_LEFT.set(CIRCLE_TOP_LEFT.x + diff, CIRCLE_TOP_LEFT.y);
CIRCLE_BOTTOM_LEFT.set(CIRCLE_BOTTOM_LEFT.x + diff, CIRCLE_BOTTOM_LEFT.y);
} else if (inCircle(lastX, lastY, (CIRCLE_TOP_RIGHT.x + CIRCLE_BOTTOM_RIGHT.x) / 2f, (CIRCLE_TOP_RIGHT.y + CIRCLE_BOTTOM_RIGHT.y) / 2f, TOUCH_CIRCLE_RADIUS)) {
isTouchCirclePoints = true;
int diff = (int) (lastX - (CIRCLE_TOP_RIGHT.x + CIRCLE_BOTTOM_RIGHT.x) / 2f);
CIRCLE_TOP_RIGHT.set(CIRCLE_TOP_RIGHT.x + diff, CIRCLE_TOP_RIGHT.y);
CIRCLE_BOTTOM_RIGHT.set(CIRCLE_BOTTOM_RIGHT.x + diff, CIRCLE_BOTTOM_RIGHT.y);
} else if (inCircle(lastX, lastY, (CIRCLE_TOP_LEFT.x + CIRCLE_TOP_RIGHT.x) / 2f, (CIRCLE_TOP_LEFT.y + CIRCLE_TOP_RIGHT.y) / 2f, TOUCH_CIRCLE_RADIUS)) {
isTouchCirclePoints = true;
int diff = (int) (lastY - (CIRCLE_TOP_LEFT.y + CIRCLE_TOP_RIGHT.y) / 2f);
CIRCLE_TOP_RIGHT.set(CIRCLE_TOP_RIGHT.x, CIRCLE_TOP_RIGHT.y + diff);
CIRCLE_TOP_LEFT.set(CIRCLE_TOP_LEFT.x, CIRCLE_TOP_LEFT.y + diff);
} else if (inCircle(lastX, lastY, (CIRCLE_BOTTOM_LEFT.x + CIRCLE_BOTTOM_RIGHT.x) / 2f, (CIRCLE_BOTTOM_LEFT.y + CIRCLE_BOTTOM_RIGHT.y) / 2f, TOUCH_CIRCLE_RADIUS)) {
isTouchCirclePoints = true;
int diff = (int) (lastY - (CIRCLE_BOTTOM_LEFT.y + CIRCLE_BOTTOM_RIGHT.y) / 2f);
CIRCLE_BOTTOM_RIGHT.set(CIRCLE_BOTTOM_RIGHT.x, CIRCLE_BOTTOM_RIGHT.y + diff);
CIRCLE_BOTTOM_LEFT.set(CIRCLE_BOTTOM_LEFT.x, CIRCLE_BOTTOM_LEFT.y + diff);
} else if (isBeingDragged) {
int dragXDist = (int) (event.getX() - dragX);
int dragYDist = (int) (event.getY() - dragY);
dragX = (int) event.getX();
dragY = (int) event.getY();
curveX += dragXDist;
curveY += dragYDist;
CIRCLE_TOP_LEFT.x += dragXDist;
CIRCLE_TOP_LEFT.y += dragYDist;
CIRCLE_TOP_RIGHT.x += dragXDist;
CIRCLE_TOP_RIGHT.y += dragYDist;
CIRCLE_BOTTOM_LEFT.x += dragXDist;
CIRCLE_BOTTOM_LEFT.y += dragYDist;
CIRCLE_BOTTOM_RIGHT.x += dragXDist;
CIRCLE_BOTTOM_RIGHT.y += dragYDist;
}
invalidate();
break;
}
return handled && isInEdit;
}
public void setInEdit(boolean isInEdit) {
this.isInEdit = isInEdit;
invalidate();
}
private boolean isInCircle(MotionEvent event, Point circle, float circleRadius) {
return inCircle(event.getX(), event.getY(), circle.x, circle.y, circleRadius);
}
private boolean inCircle(float x, float y, float circleCenterX, float circleCenterY, float circleRadius) {
double dx = Math.pow(x - circleCenterX, 2);
double dy = Math.pow(y - circleCenterY, 2);
if ((dx + dy) < Math.pow(circleRadius, 2)) {
return true;
} else {
return false;
}
}
private boolean isInBitmap(MotionEvent event) {
Point[] points = {CIRCLE_TOP_LEFT, CIRCLE_TOP_RIGHT, CIRCLE_BOTTOM_RIGHT, CIRCLE_BOTTOM_LEFT};
return isInside(points, 4, new Point((int) event.getX(), (int) event.getY()));
}
// Define Infinite (Using INT_MAX
// caused overflow problems)
static int INF = 10000;
// Given three colinear points p, q, r,
// the function checks if point q lies
// on line segment 'pr'
static boolean onSegment(Point p, Point q, Point r) {
if (q.x <= Math.max(p.x, r.x) &&
q.x >= Math.min(p.x, r.x) &&
q.y <= Math.max(p.y, r.y) &&
q.y >= Math.min(p.y, r.y)) {
return true;
}
return false;
}
// To find orientation of ordered triplet (p, q, r).
// The function returns following values
// 0 --> p, q and r are colinear
// 1 --> Clockwise
// 2 --> Counterclockwise
static int orientation(Point p, Point q, Point r) {
int val = (q.y - p.y) * (r.x - q.x)
- (q.x - p.x) * (r.y - q.y);
if (val == 0) {
return 0; // colinear
}
return (val > 0) ? 1 : 2; // clock or counterclock wise
}
// The function that returns true if
// line segment 'p1q1' and 'p2q2' intersect.
static boolean doIntersect(Point p1, Point q1,
Point p2, Point q2) {
// Find the four orientations needed for
// general and special cases
int o1 = orientation(p1, q1, p2);
int o2 = orientation(p1, q1, q2);
int o3 = orientation(p2, q2, p1);
int o4 = orientation(p2, q2, q1);
// General case
if (o1 != o2 && o3 != o4) {
return true;
}
// Special Cases
// p1, q1 and p2 are colinear and
// p2 lies on segment p1q1
if (o1 == 0 && onSegment(p1, p2, q1)) {
return true;
}
// p1, q1 and p2 are colinear and
// q2 lies on segment p1q1
if (o2 == 0 && onSegment(p1, q2, q1)) {
return true;
}
// p2, q2 and p1 are colinear and
// p1 lies on segment p2q2
if (o3 == 0 && onSegment(p2, p1, q2)) {
return true;
}
// p2, q2 and q1 are colinear and
// q1 lies on segment p2q2
if (o4 == 0 && onSegment(p2, q1, q2)) {
return true;
}
// Doesn't fall in any of the above cases
return false;
}
// Returns true if the point p lies
// inside the polygon[] with n vertices
static boolean isInside(Point polygon[], int n, Point p) {
// There must be at least 3 vertices in polygon[]
if (n < 3) {
return false;
}
// Create a point for line segment from p to infinite
Point extreme = new Point(INF, p.y);
// Count intersections of the above line
// with sides of polygon
int count = 0, i = 0;
do {
int next = (i + 1) % n;
// Check if the line segment from 'p' to
// 'extreme' intersects with the line
// segment from 'polygon[i]' to 'polygon[next]'
if (doIntersect(polygon[i], polygon[next], p, extreme)) {
// If the point 'p' is colinear with line
// segment 'i-next', then check if it lies
// on segment. If it lies, return true, otherwise false
if (orientation(polygon[i], p, polygon[next]) == 0) {
return onSegment(polygon[i], p,
polygon[next]);
}
count++;
}
i = next;
} while (i != 0);
// Return true if count is odd, false otherwise
return (count % 2 == 1); // Same as (count%2 == 1)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment