Everything actually looks OK, except that following your use of sort->unique->erase, there's still potentially a single -1 in your convex array (if there were any points not on the convex hull), and while you skip it for i, you include it for j when i is at the end of your list. Perhaps a better option than sort->unique->erase is simply:
convex.remove(-1)
Also, if it isn't already assumed, your points must be specified in counter-clockwise order, and there can be no loops in the order of the resulting convex-hull vertices. (Loops in the polygon are OK as long as their points are eliminated from the convex hull. Mostly.)
While your solution for eliminating points looks like it should work fine, it's grossly inefficient. Imagine if you had 1,000 points: you'd be calling is_internal() on the order of a trillion times! So first of all, once P[l] is eliminated from the convex hull, it doesn't need to be checked again:
...
for(int l = 0; l < pts; l++) {
if(l != i && l != j && l != k && convex[l] != -1) {
if(is_internal(P[i], P[j], P[k], P[l])) {
convex[l] = -1;
}
}
}
...
Also, since you brute-force iterate over all of the points with i, j and k, you end up checking each triangle 6 times! (e.g., 012, 021, 102, 120, 201, 210.) Since each triangle is uniquely identified by ordering its point-indices, you only need to check larger values from the ones you …