Commit a2498efb authored by Nguyeng Hoang Giang's avatar Nguyeng Hoang Giang

add

parent 0033e091
......@@ -16,22 +16,21 @@ ext{
}
dependencies {
List axisExGroups = [ 'org.bytedeco.javacpp-presets']
List axisExModules = [ 'ffmpeg' , 'artoolkitplus', 'ffmpeg-platform']
implementation('org.bytedeco:opencv:4.5.1-1.5.5:android-x86')
implementation('org.bytedeco:opencv:4.3.0-1.5.3:android-x86_64')
implementation('org.bytedeco:openblas:0.3.13-1.5.5:android-x86')
implementation('org.bytedeco:openblas:0.3.9-1.5.3:android-x86_64')
implementation(group:'org.apache.commons', name: 'commons-collections4', version: '4.0')
implementation(group :'org.bytedeco', name: 'javacv-platform', version: '1.5.5'){
exclude group: 'org.bytedeco.javacpp-presets'
axisExGroups.each { exclude group: "$it" }
axisExModules.each {exclude module: "$it"}
}
implementation('org.apache.commons:commons-lang3:3.12.0')
implementation('com.github.sh0nk:matplotlib4j:0.5.0')
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.1'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1'
// testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.1'
// testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1'
}
test {
......
package Entity;
public class Face {
protected static final int DELETED = 3;
protected static final int NON_CONVEX = 2;
protected static final int VISIBLE = 1;
protected double area;
protected HalfEdge he0;
protected int mask = VISIBLE;
protected Face next;
protected int numVerts;
protected Vertex outside;
protected double planeOffset;
private Point3D centroid;
private Vector3D normal;
public Face() {
normal = new Vector3D();
centroid = new Point3D();
mask = VISIBLE;
}
public static Face create(Vertex[] vtxArray, int[] indices) {
return null;
}
public static Face createTriangle(Vertex v0, Vertex v1, Vertex v2) {
return null;
}
/**
* Constructs a triangule Face from vertices v0, v1, and v2.
*
* @param v0 first vertex
* @param v1 second vertex
* @param v2 third vertex
* @param minArea
* @return
*/
public static Face createTriangle(Vertex v0, Vertex v1, Vertex v2, double minArea) {
Face face = new Face();
HalfEdge he0 = new HalfEdge(v0, face);
HalfEdge he1 = new HalfEdge(v1, face);
HalfEdge he2 = new HalfEdge(v2, face);
he0.prev = he2;
he0.next = he1;
he1.prev = he0;
he1.next = he2;
he2.prev = he1;
he2.next = he0;
face.he0 = he0;
//compute the normal and offset
face.computeNormalAndCentroid();
return face;
}
/**
* Compute Centroid
*/
public void computeCentroid(Point3D centroid) {
centroid.setZero();
HalfEdge he = he0;
do {
centroid.add(he.head().pnt);
he = he.next;
} while (he != he0);
centroid.scale(1 / (double) numVerts);
}
public void computeNormal(Vector3D normal) {
HalfEdge he1 = he0.next;
HalfEdge he2 = he1.next;
Point3D p0 = he0.head().pnt;
Point3D p2 = he1.head().pnt;
double d2x = p2.x - p0.x;
double d2y = p2.y - p0.y;
double d2z = p2.z - p0.z;
normal.setZero();
numVerts = 2;
while (he2 != he0) {
double d1x = d2x;
double d1y = d2y;
double d1z = d2z;
p2 = he2.head().pnt;
d2x = p2.x - p0.x;
d2y = p2.y - p0.y;
d2z = p2.z - p0.z;
normal.x += d1y * d2z - d1z * d2y;
normal.y += d1z * d2x - d1x * d2z;
normal.z += d1x * d2y - d1y * d2x;
he1 = he2;
he2 = he2.next;
numVerts++;
}
area = normal.norm();
normal.scale(1 / area);
}
public void computeNormal(Vector3D normal, double minArea) {
computeNormal(normal);
if (area < minArea) {
//make the normal more robust by remove components parallel to the longest edge
HalfEdge hedgeMax = null;
double lenSqrMax = 0;
HalfEdge hedge = he0;
do {
double lenSqr = hedge.lengthSquared();
if (lenSqr > lenSqrMax) {
hedgeMax = hedge;
lenSqrMax = lenSqr;
}
hedge = hedge.next;
} while (hedge != he0);
Point3D p2 = hedgeMax.head().pnt;
Point3D p1 = hedgeMax.tail().pnt;
double lenMax = Math.sqrt(lenSqrMax);
double ux = (p2.x - p1.x) / lenMax;
double uy = (p2.y - p1.y) / lenMax;
double uz = (p2.z - p1.z) / lenMax;
double dot = normal.x * ux + normal.y * uy + normal.z * uz;
normal.x -= dot * ux;
normal.y -= dot * uy;
normal.z -= dot * uz;
normal.normalize();
}
}
/**
* Compute the distance from a pont p to the plane of this face
*
* @param p the poin
* @return distance from the point to the plane
*/
public double distanceToPlane(Point3D p) {
return normal.x * p.x + normal.y * p.y + normal.z * p.z - planeOffset;
}
/**
* Finds the half-edge within this face which have tail vt and head vh
*
* @param vt tail point
* @param vh heat point
* @return the half-edge, or null if none is found.
*/
public HalfEdge findEdge(Vertex vt, Vertex vh) {
HalfEdge he = he0;
do {
if (he.head() == vh && he.tail() == vt) {
return he;
}
he = he.next;
} while (he != he0);
return null;
}
public Point3D getCentroid() {
return centroid;
}
/**
* Gets the i-th half-edge associated with the face
*
* @param i the half-edge index, in the range 0-2
* @return the half-edge
*/
public HalfEdge getEdge(int i) {
HalfEdge he = he0;
while (i > 0) {
he = he.next;
i--;
}
while (i < 0) {
he = he.prev;
i++;
}
return he;
}
public HalfEdge getFirstEdge() {
return he0;
}
public Vector3D getNormal() {
return normal;
}
public void getVertexIndices(int[] idxs) {
HalfEdge he = he0;
int i = 0;
do {
idxs[i++] = he.head().index;
he = he.next;
} while (he != he0);
}
public String getVertexString() {
String s = null;
HalfEdge he = he0;
do {
if (s == null) {
s = "" + he.head().index;
} else {
s += " " + he.head().index;
}
he = he.next;
} while (he != he0);
return s;
}
public int mergeAdjacentFace(HalfEdge hedgeAdj, Face[] discarded) {
Face oppFace = hedgeAdj.oppositeFace();
int numDiscarded = 0;
discarded[numDiscarded++] = oppFace;
oppFace.mask = DELETED;
HalfEdge hedgeOpp = hedgeAdj.getOpposite();
HalfEdge hedgeAdjPrev = hedgeAdj.prev;
HalfEdge hedgeAdjNext = hedgeAdj.next;
HalfEdge hedgeOppPrev = hedgeOpp.prev;
HalfEdge hedgeOppNext = hedgeOpp.next;
while (hedgeAdjPrev.oppositeFace() == oppFace) {
hedgeAdjPrev = hedgeAdjPrev.prev;
hedgeOppNext = hedgeOppNext.next;
}
while (hedgeAdjNext.oppositeFace() == oppFace) {
hedgeOppPrev = hedgeOppPrev.prev;
hedgeAdjNext = hedgeAdjNext.next;
}
HalfEdge hedge;
for (hedge = hedgeOppNext; hedge != hedgeOppPrev.next; hedge = hedge.next) {
hedge.face = this;
}
if (hedgeAdj == he0) {
he0 = hedgeAdjNext;
}
//handle the half edges at the head
Face discardedFace;
discardedFace = connectHalfEdges(hedgeOppPrev, hedgeAdjNext);
if (discardedFace != null) {
discarded[numDiscarded++] = discardedFace;
}
//handle the half edges at the tail
discardedFace = connectHalfEdges(hedgeAdjPrev, hedgeOppNext);
if (discardedFace != null) {
discarded[numDiscarded++] = discardedFace;
}
computeNormalAndCentroid();
checkConsistency();
return numDiscarded;
}
public int getNumVerts() {
return numVerts;
}
public void triangulate(FaceList newFaces, double minArea) {
HalfEdge hedge;
if (getNumVerts() < 4) {
return;
}
Vertex v0 = he0.head();
hedge = he0.next;
HalfEdge oppPrev = hedge.opposite;
Face face0 = null;
for (hedge = hedge.next; hedge != he0.prev; hedge = hedge.next) {
Face face = createTriangle(v0, hedge.prev.head(), hedge.head(), minArea);
face.he0.next.setOpposite(oppPrev);
face.he0.prev.setPrev(hedge.opposite);
oppPrev = face.he0;
newFaces.add(face);
if (face0 == null) {
face0 = face;
}
}
hedge = new HalfEdge(he0.prev.prev.head(), this);
hedge.setOpposite(oppPrev);
hedge.prev = he0;
hedge.prev.next = hedge;
hedge.next = he0.prev;
hedge.next.prev = hedge;
computeNormalAndCentroid(minArea);
checkConsistency();
for (Face face = face0; face != null; face = face.next) {
face.checkConsistency();
}
}
/**
* return the squared area of the triangle defined by the half edge hedge- and the point at the head of hedge1
*
* @param hedge0
* @param hedge1
* @return
*/
public double areaSquare(HalfEdge hedge0, HalfEdge hedge1) {
Point3D p0 = hedge0.tail().pnt;
Point3D p1 = hedge0.head().pnt;
Point3D p2 = hedge1.head().pnt;
double dx1 = p1.x - p0.x;
double dy1 = p1.y - p0.y;
double dz1 = p1.z - p0.z;
double dx2 = p2.x - p0.x;
double dy2 = p2.y - p0.y;
double dz2 = p2.z - p0.z;
double x = dy1 * dz2 - dz1 * dy2;
double y = dz1 * dx2 - dx1 * dz2;
double z = dx1 * dy2 - dy1 * dx2;
return x * x + y * y + z * z;
}
private void computeNormalAndCentroid() {
computeNormal(normal);
computeCentroid(centroid);
planeOffset = normal.dot(centroid);
int numv = 0;
HalfEdge he = he0;
do {
numv++;
he = he.next;
} while (he != he0);
if (numv != numVerts) {
throw new RuntimeException("face " + getVertexString() + " numVerts" +
numVerts + " shoule be " + numv);
}
}
private void computeNormalAndCentroid(double minArea) {
computeNormal(normal, minArea);
computeCentroid(centroid);
planeOffset = normal.dot(centroid);
}
private Face connectHalfEdges(HalfEdge hedgePrev, HalfEdge hedge) {
Face discardFace = null;
//have a redundant edge that can get rid off
if (hedgePrev.oppositeFace() == hedge.oppositeFace()) {
Face oppFace = hedge.oppositeFace();
HalfEdge hedgeOpp;
if (hedgePrev == he0) {
he0 = hedge;
}
if (oppFace.getNumVerts() == 3) {
//can get rid of the apposite face altogether
hedgeOpp = hedge.getOpposite().prev.getOpposite();
oppFace.mask = DELETED;
discardFace = oppFace;
} else {
hedgeOpp = hedge.getOpposite().next;
if (oppFace.he0 == hedgeOpp.prev) {
oppFace.he0 = hedgeOpp;
}
hedgeOpp.prev = hedgeOpp.prev.prev;
hedgeOpp.prev.next = hedgeOpp;
}
hedge.prev = hedgePrev.prev;
hedge.prev.next = hedge;
hedge.opposite = hedgeOpp;
hedgeOpp.opposite = hedge;
//oppFace was modified, so need to recompute
oppFace.computeNormalAndCentroid();
} else {
hedgePrev.next = hedge;
hedge.prev = hedgePrev;
}
return discardFace;
}
void checkConsistency() {
//do a santiy check on the face
HalfEdge hedge = he0;
double maxd = 0;
int numv = 0;
if (numVerts < 3) {
throw new RuntimeException("degenerate face: " + getVertexString());
}
do {
HalfEdge hedgeOpp = hedge.getOpposite();
if (hedgeOpp == null) {
throw new RuntimeException("face " + getVertexString() + ": " + "unreflected half edge " + hedge.getVertexString());
} else if (hedgeOpp.getOpposite() != hedge) {
throw new RuntimeException("face " + getVertexString() + ": " + "opposite half edge " + hedgeOpp.getVertexString() + " has opposite "
+ hedgeOpp.getOpposite().getVertexString());
}
if (hedgeOpp.head() != hedge.tail() || hedge.head() != hedgeOpp.tail()) {
throw new RuntimeException("face " + getVertexString() + ": " + "half edge " + hedge.getVertexString() + " reflected by " + hedgeOpp.getVertexString());
}
Face oppFace = hedgeOpp.face;
if (oppFace == null) {
throw new RuntimeException("face " + getVertexString() + ": " + "no face on half edge " + hedgeOpp.getVertexString());
} else if (oppFace.mask == DELETED) {
throw new RuntimeException("face " + getVertexString() + ": " + "opposite face " + oppFace.getVertexString() + " not on hull");
}
double d = Math.abs(distanceToPlane(hedge.head().pnt));
if (d > maxd) {
maxd = d;
}
numv++;
hedge = hedge.next;
} while (hedge != he0);
if (numv != numVerts) {
throw new RuntimeException("face " + getVertexString() + " numVerts=" + numVerts + " should be " + numv);
}
}
}
package Entity;
public class FaceList {
private Face head;
private Face tail;
/**
* Clears this list
*/
public void clear() {
head = tail = null;
}
/**
* Adds a vertex to the end of this list
*/
public void add(Face vtx) {
if (head == null) {
head = vtx;
} else {
tail.next = vtx;
}
vtx.next = null;
tail = vtx;
}
public Face first() {
return head;
}
/**
* Returns true if this list is empty
*/
public boolean isEmpty() {
return head == null;
}
}
package Entity;
public class HalfEdge {
/**
* The vertex associated with the heat of this half-edge
*/
protected Vertex vertex;
/**
* Triangular face associated with this half-edge
*/
protected Face face;
/**
* Next haft-edge in the triangle
*/
protected HalfEdge next;
/**
* Previous half-edge in the reiangle
*/
protected HalfEdge prev;
/**
* Half-edge associated with the opposite triangle adjacent to this edge
*/
protected HalfEdge opposite;
public HalfEdge() {
}
/**
* Constructs a HalfEdge with head vertex and left-hand triangular face
*
* @param vertex head vertex
* @param face left-hand triangular face
*/
public HalfEdge(Vertex vertex, Face face) {
this.vertex = vertex;
this.face = face;
}
/**
* Gets the triangular face located to the left of this half-edge
*
* @return left-hand triangular face
*/
public Face getFace() {
return face;
}
/**
* Gets the value of the next edge adjacent (counter-clockwise) to this one within the triangle
*
* @return next adjacent edge
*/
public HalfEdge getNext() {
return next;
}
/**
* Sets the value of the next edge adjacent (counter-clockwise) to this one within the triangle
*
* @param next next adjacent edge
*/
public void setNext(HalfEdge next) {
this.next = next;
}
/**
* Gets the value of the previous edge adjacent (clockwise) to this one within the triangle
*
* @return previous adjacent edge
*/
public HalfEdge getPrev() {
return prev;
}
/**
* Sets the value of the previous edge adjacent (clockwise) to this one within the triangle
*
* @param prev previous adjacent edge
*/
public void setPrev(HalfEdge prev) {
this.prev = prev;
}
/**
* Returns the half-edge opposite to this half-edge
*
* @return opposite half-edge
*/
public HalfEdge getOpposite() {
return opposite;
}
/**
* Sets the half-edge opposite to this half-edge
*
* @param opposite opposite half-edge
*/
public void setOpposite(HalfEdge opposite) {
this.opposite = opposite;
}
/**
* Returns the head vertex associated with this half-edge
*
* @return head vertex
*/
public Vertex head() {
return vertex;
}
/**
* Returns the tail vertex associate with this half-edge
*
* @return
*/
public Vertex tail() {
return prev != null ? prev.vertex : null;
}
/**
* Returns the opposite triangular face associate with this half-edge
*
* @return opposite triangular face
*/
public Face oppositeFace() {
return opposite != null ? opposite.face : null;
}
/**
* Produces a string identifying this half-edge by the point index values of its tail and head vertices
*
* @return identifying string
*/
public String getVertexString() {
if (tail() != null) {
return "" + tail().index + "-" + head().index;
} else {
return "?-" + head().index;
}
}
/**
* Returns the length of this half-edge
*
* @return half-edge length
*/
public double length() {
if (tail() != null) {
return head().pnt.distance(tail().pnt);
} else {
return -1;
}
}
/**
* Returns the length squared of this half-edge
*
* @return half-edge squared length
*/
public double lengthSquared() {
if (tail() != null) {
return head().pnt.distanceSquared(tail().pnt);
} else {
return -1;
}
}
}
package Entity;
public class Point3D extends Vector3D{
/**
* Create a Point3D amd initializes it to zero
*/
public Point3D() {
}
/**
* Creates a Point3D by copy a vector
* @param v
*/
public Point3D(Vector3D v) {
super(v);
}
/**
* Create a Point3D with the supplied element values
* @param x
* first element
* @param y
* second element
* @param z
* third element
*/
public Point3D(double x, double y, double z) {
super(x, y, z);
}
}
package Entity;
public class Vector3D {
static private final double DOUBLE_PREC = 2.2204460492503131e-16;//Precision of a double
public double x;//first element
public double y;//second element
public double z;//third element
//Creates a 3-vector and initializes its elements to 0
public Vector3D() {
}
/**
* Creates a 3-vector by copy existing one
*
* @param v vector to be copied
*/
public Vector3D(Vector3D v) {
set(v);
}
/**
* Creates a 3-vector with the supplied element values
*
* @param x first element
* @param y second element
* @param z third element
*/
public Vector3D(double x, double y, double z) {
set(x, y, z);
}
/**
* Gets a single element of this vector. Element 0, 1, and 2 correspond to x,y and z
*
* @param i element index
* @return element value throws ArrayIndexOutOfBoundsException if i is not in range 0 to 2
*/
public double get(int i) {
switch (i) {
case 0: {
return x;
}
case 1: {
return y;
}
case 2: {
return z;
}
default: {
throw new ArrayIndexOutOfBoundsException(i);
}
}
}
/**
* Sets a single element of this vector. Elements 0, 1, and 2 correspond to
* x, y, and z
*
* @param i element index
* @param value element value
* @return element value throws ArrayIndexOutOfBoundsException if i is not in the range 0 to 2
*/
public void set(int i, double value) {
switch (i) {
case 0: {
x = value;
break;
}
case 1: {
y = value;
break;
}
case 2: {
z = value;
break;
}
default: {
throw new ArrayIndexOutOfBoundsException(i);
}
}
}
/**
* Sets the values of this vector to those of v1
*
* @param v1 vector whose values are copied
*/
public void set(Vector3D v1) {
this.x = v1.x;
this.y = v1.y;
this.z = v1.z;
}
/**
* Sets the values of the vector to the prescribed values
*
* @param x value for first element
* @param y value for second element
* @param z value for third element
*/
public void set(double x, double y, double z) {
this.x = x;
this.y = y;
this.z = z;
}
/**
* Sets the elements of this vector to zero
*/
public void setZero() {
x = 0;
y = 0;
z = 0;
}
/**
* Adds vector v1 to v2 and places the result in this vector
*
* @param v1 left-hand vector
* @param v2 right-hand vector
*/
public void add(Vector3D v1, Vector3D v2) {
x = v1.x + v2.x;
y = v1.y + v2.y;
z = v1.z + v2.z;
}
/**
* Adds this vector to v and places the result in this vector
*
* @param v right-hand vector
*/
public void add(Vector3D v) {
x += v.x;
y += v.y;
z += v.z;
}
/**
* Subs vector v1 from v2 and places the result in this vector
*
* @param v1 left-hand vector
* @param v2 right-hand vector
*/
public void sub(Vector3D v1, Vector3D v2) {
x = v1.x - v2.x;
y = v1.y - v2.y;
z = v1.z - v2.z;
}
/**
* Subs this vector from v and places the result in this vector
*
* @param v right-hand vector
*/
public void sub(Vector3D v) {
x -= v.x;
y -= v.y;
z -= v.z;
}
/**
* Scales the elements of this vector by s
*
* @param s scaling factor
*/
public void scale(double s) {
x = s * x;
y = s * y;
z = s * z;
}
/**
* Scales the elements of vector v by s and place the results in this vector
*
* @param s scaling vector
* @param v vector to be scaled
*/
public void scale(double s, Vector3D v) {
x = s * v.x;
y = s * v.y;
z = s * v.z;
}
/**
* Returns the 2 norm of this vector. This is the square root of the sum of the squares of the elements
*
* @return vector 2 norm
*/
public double norm() {
return Math.sqrt(x * x + y * y + z * z);
}
/**
* Retruns the square of the 2 norm of this vector. this is the sum of the squares of the element
*
* @return square of the 2 norm
*/
public double normSquared() {
return x * x + y * y + z * z;
}
/**
* Returns the Euclidean distance between this vector and vector v
*
* @param v vector destination
* @return distance between this vector and v
*/
public double distance(Vector3D v) {
double dx = x - v.x;
double dy = y - v.y;
double dz = z - v.z;
return Math.sqrt(dx * dx + dy * dy + dz * dz);
}
/**
* Returns the squared of Euclidean distance between this vector and vector v
*
* @param v vector destination
* @return squared distance between this vector and v
*/
public double distanceSquared(Vector3D v) {
double dx = x - v.x;
double dy = y - v.y;
double dz = z - v.z;
return dx * dx + dy * dy + dz * dz;
}
/**
* Returns the dot product of this vector and v1
*
* @param v right-hand vector
* @return dot product
*/
public double dot(Vector3D v) {
return x * v.x + y * v.y + z * v.z;
}
/**
* Normalizes this vector in place
*/
public void normalize() {
double lenSqr = x * x + y * y + z * z;
double err = lenSqr - 1;
if (err > (2 * DOUBLE_PREC) || err < -(2 * DOUBLE_PREC)) {
double len = Math.sqrt(lenSqr);
x /= len;
y /= len;
z /= len;
}
}
/**
* Computes the cross product of v1 and v2 and places the result in this vector
*
* @param v1 left-hand vector
* @param v2 right-hand vector
*/
public void cross(Vector3D v1, Vector3D v2) {
double tmpx = v1.y * v2.z - v1.z * v2.y;
double tmpy = v1.z * v2.x - v1.x * v2.z;
double tmpz = v1.x * v2.y - v1.y - v2.x;
x = tmpx;
y = tmpy;
z = tmpz;
}
@Override
public String toString() {
return "Vector3D{" +
"x=" + x +
", y=" + y +
", z=" + z +
'}';
}
}
package Entity;
public class Vertex {
/**
* Spatial point associated with this vertex
*/
public Point3D pnt;
/**
* Back index into an array
*/
public int index;
/**
* List forward link
*/
public Vertex prev;
/**
* List backward link
*/
public Vertex next;
/**
* Current face that this vertex is outside of
*/
public Face face;
/**
* Constructs a vertex and sets its coordinates to 0
*/
public Vertex() {
}
/**
* Constructs a vertex with the specified coordinates and index
*/
public Vertex(double x, double y, double z, int idx) {
pnt = new Point3D(x, y, z);
index = idx;
}
}
package Entity;
public class VertexList {
private Vertex head;
private Vertex tail;
/**
* Clears this list
*/
public void clear() {
head = tail = null;
}
/**
* Adds a vertex to the end of this list
*/
public void add(Vertex vtx) {
if (head == null) {
head = vtx;
} else {
tail.next = vtx;
}
vtx.prev = tail;
vtx.next = null;
tail = vtx;
}
/**
* Adds a chain of vertices to the end of this list
*/
public void addAll(Vertex vtx) {
if (head == null) {
head = vtx;
} else {
tail.next = vtx;
}
vtx.prev = tail;
while (vtx.next != null) {
vtx = vtx.next;
}
tail = vtx;
}
/**
* Deletes a vertex from this list
*/
public void delete(Vertex vtx) {
if (vtx.prev == null) {
head = vtx.next;
} else {
vtx.prev.next = vtx.next;
}
if (vtx.next == null) {
tail = vtx.prev;
} else {
vtx.next.prev = vtx.prev;
}
}
/**
* Deletes a chain of vertices from this list
*/
public void delete(Vertex vtx1, Vertex vtx2) {
if (vtx1.prev == null) {
head = vtx2.next;
} else {
vtx1.prev.next = vtx2.next;
}
if (vtx2.next == null) {
tail = vtx1.prev;
} else {
vtx2.next.prev = vtx1.prev;
}
}
/**
* Inserts a vertex into this list before another specificed vertex
*/
public void insertBefore(Vertex vtx, Vertex next) {
vtx.prev = next.prev;
if (next.prev == null) {
head = vtx;
} else {
next.prev.next = vtx;
}
vtx.next = next;
next.prev = vtx;
}
/**
* return the first element in this list
*/
public Vertex first() {
return head;
}
/**
* Returns true if this list is empty
*/
public boolean isEmpty() {
return head == null;
}
}
import Entity.Point3D;
import org.opencv.core.Mat;
import org.opencv.core.Size;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
public class Fleet_single_cam {
private String id;
......@@ -14,6 +17,7 @@ public class Fleet_single_cam {
private int num_y;
private int num_z;
private boolean show;
private Point3D[] points;
// private
HashMap<String, intArray> side;
......@@ -32,6 +36,14 @@ public class Fleet_single_cam {
return intArray.clone();
}
public int getWidth() {
return intArray[0].length;
}
public int getHeight() {
return intArray.length;
}
public void setIntArray(int[][] intArray) {
this.intArray = intArray;
}
......@@ -126,6 +138,73 @@ public class Fleet_single_cam {
this.side.get("bottom").setIntArray(fill_matrix(bottom));
}
/**
* Create list point3d from 3 side
*/
public void initPoint3d() {
//init point list
List<Point3D> point3dList = new ArrayList<>();
//temp pixel
int xx = 0;
int yy = 0;
int zz = 0;
//get side front, side, bottom
int[][] front = this.side.get("front").getIntArray();
int[][] side = this.side.get("side").getIntArray();
int[][] bottom = this.side.get("bottom").getIntArray();
//add point 0 in side front
zz = num_z + 1;
yy = num_y + 1;
for (int i = 0; i < front.length; i++) {
zz -= 1;
xx = 0;
for (int j = 0; j < front[i].length; j++) {
xx += 1;
//add if point == 0
if (front[i][j] == 0) {
point3dList.add(new Point3D(xx, yy, zz));
}
}
}
//add point 0 in side side
zz = num_z + 1;
xx = 0;
for (int i = 0; i < side.length; i++) {
zz -= 1;
yy = 0;
for (int j = 0; j < side[i].length; j++) {
yy += 1;
//add if point == 0
if (side[i][j] == 0) {
point3dList.add(new Point3D(xx, yy, zz));
}
}
}
//add point 0 in side bottom
zz = 0;
yy = num_y + 1;
for (int i = 0; i < bottom.length; i++) {
yy -= 1;
xx = 0;
for (int j = 0; j < bottom[i].length; j++) {
xx += 1;
//add if point == 0
if (bottom[i][j] == 0) {
point3dList.add(new Point3D(xx, yy, zz));
}
}
}
points = point3dList.toArray(new Point3D[point3dList.size()]);
}
public Point3D[] getPoints() {
return points;
}
private int[][] padding(int[][] matrix, int require_height, int require_width) {
//get width, height
......@@ -160,7 +239,6 @@ public class Fleet_single_cam {
}
return return_matrix;
}
......
import org.bytedeco.javacpp.Loader;
import org.bytedeco.opencv.opencv_java;
import java.util.Arrays;
public class main {
public static void main(String[] args) {
Loader.load(opencv_java.class);
//Khoi tạo 1 cam, nhận ảnh tĩnh vào
Fleet_single_cam cam = new Fleet_single_cam("a", "5b8ab6b219c9d6978fd827.jpg", 0.5, 5, 5, 4, false);
Fleet_single_cam cam1 = new Fleet_single_cam("a", "1da36bd1c4aa0bf452bb24.jpg", 0.5, 5, 5, 4, false);
//create front side, add 4 đỉnh của side front vào
cam1.add_side("front", new float[][]{
new float[]{681, 54},
new float[]{1250, 115},
new float[]{984, 528},
new float[]{679, 366}
});
//create mặt side, add 4 đỉnh của mặt side vào
cam1.add_side("side", new float[][]{
new float[]{8, 152},
new float[]{681, 54},
new float[]{679, 366},
new float[]{288, 545}
});
//create bottom side, add 4 đỉnh của side bottom vào
cam1.add_side("bottom", new float[][]{
new float[]{679, 366},
new float[]{984, 528},
new float[]{732, 955},
new float[]{288, 545}
});
cam1.refine_matrix();
cam1.initPoint3d();
//Khoi tạo 1 cam, nhận ảnh tĩnh vào
Fleet_single_cam cam2 = new Fleet_single_cam("a", "5b8ab6b219c9d6978fd827.jpg", 0.5, 5, 5, 4, false);
//create front side, add 4 đỉnh của side front vào
cam.add_side("front", new float[][]{
cam2.add_side("front", new float[][]{
new float[]{687, 8},
new float[]{1264, 54},
new float[]{1027, 432},
......@@ -18,7 +50,7 @@ public class main {
});
//create mặt side, add 4 đỉnh của mặt side vào
cam.add_side("side", new float[][]{
cam2.add_side("side", new float[][]{
new float[]{12, 132},
new float[]{687, 8},
new float[]{672, 305},
......@@ -26,46 +58,40 @@ public class main {
});
//create bottom side, add 4 đỉnh của side bottom vào
cam.add_side("bottom", new float[][]{
cam2.add_side("bottom", new float[][]{
new float[]{672, 305},
new float[]{1027, 432},
new float[]{817, 923},
new float[]{275, 497}
});
cam.refine_matrix();
cam2.refine_matrix();
cam2.initPoint3d();
// Point3d[] poly = Arrays.copyOf(cam1.getPoints(), cam1.getPoints().length+cam2.getPoints().length);
// System.arraycopy(cam2.getPoints(), 0, poly, cam1.getPoints().length, cam2.getPoints().length);
//
// QuickHull3D hull = new QuickHull3D();
// hull.build(poly);
// System.out.println("Vertices:");
// Point3d[] vertices = hull.getVertices();
// for (int i = 0; i < vertices.length; i++) {
// Point3d pnt = vertices[i];
// System.out.println(pnt.x + " " + pnt.y + " " + pnt.z);
// }
//
// System.out.println("Faces:");
// int[][] faceIndices = hull.getFaces();
// for (int i = 0; i < vertices.length; i++) {
// for (int k = 0; k < faceIndices[i].length; k++) {
// System.out.print(faceIndices[i][k] + " ");
// }
// System.out.println("");
// }
//print matrix
int[][] matrix = cam.side.get("front").getIntArray();
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix[0].length; j++) {
System.out.print(matrix[i][j] + " ");
}
System.out.println();
}
System.out.println();
int[][] matrix2 = cam.side.get("side").getIntArray();
for (int i = 0; i < matrix2.length; i++) {
for (int j = 0; j < matrix2[0].length; j++) {
System.out.print(matrix2[i][j] + " ");
}
System.out.println();
}
System.out.println();
int[][] matrix3 = cam.side.get("bottom").getIntArray();
for (int i = 0; i < matrix2.length; i++) {
for (int j = 0; j < matrix3[0].length; j++) {
System.out.print(matrix3[i][j] + " ");
}
System.out.println();
}
}
}
package utils;
import Entity.*;
import java.util.Vector;
public class QuickHull3d {
/**
* Specifies that the distance tolerance should be computed automatically from the input point data
*/
public static final double AUTOMATIC_TOLERANCE = -1;
protected int findIndex = -1;
//estimated size of the point set
protected double charLength;
protected Vertex[] pointBuffer = new Vertex[0];
protected int[] vertexPointIndices = new int[0];
private Face[] discardedFaces = new Face[3];
private Vertex[] maxVtxs = new Vertex[3];
private Vertex[] minVtxs = new Vertex[3];
protected Vector face = new Vector(16);
protected Vector horizon = new Vector(16);
private FaceList newFaces = new FaceList();
private VertexList unclaimed = new VertexList();
private VertexList claimed = new VertexList();
protected int numVertices;
protected int numFaces;
protected int numPoints;
protected double explicitTolerance = AUTOMATIC_TOLERANCE;
protected double tolerance;
private static final double DOUBLE_PREC = 2.2204460492503131e-16;
/**
* Create a convex hull object and initializes it to the convex hull of a set of points
* @param points
* input points
* @throws IllegalArgumentException
* the number of input points is less than four, or the point appear to be coincident, colinear, or coplanar
*/
public QuickHull3d(Point3D[] points) throws IllegalArgumentException{
build(points, points.length);
}
/**
* Constructs the convex hull of a set of points
* @param points
* input points
* @param nump
* number of input poins
* @throws IllegalArgumentException
* the number of input points is less than four or greater than the length if points, or the points appear to be coincident, colinear, or coplanar
*/
public void build(Point3D[] points, int nump) throws IllegalArgumentException{
if (nump < 4){
throw new IllegalArgumentException("Less than four input points specified");
}
if (points.length < nump){
throw new IllegalArgumentException("Point array too small for specified number of points");
}
initBuffers(nump);
setPoints(points, nump);
buildHull();
}
protected void initBuffers(int nump){
if (pointBuffer.length < nump){
Vertex[] newBuffer = new Vertex[nump];
vertexPointIndices = new int[nump];
for (int i = 0; i < pointBuffer.length; i++){
newBuffer[i] = pointBuffer[i];
}
for (int i = pointBuffer.length; i < nump; i++){
newBuffer[i] = new Vertex();
}
pointBuffer = newBuffer;
}
face.clear();
claimed.clear();
numFaces = 0;
numPoints = nump;
}
protected void setPoints(Point3D[] pnts, int nump) {
for (int i = 0; i < nump; i++){
Vertex vtx = pointBuffer[i];
vtx.pnt.set(pnts[i]);
vtx.index = i;
}
}
protected void buildHull(){
int cnt = 0;
Vertex eyeVtx;
computeMaxAndMin();
createInitialSimplex();
while ((eyeVtx = nextPointToAdd()) != null){
addPointToHull(eyeVtx);
cnt++;
}
reindexFacesAndVertices();
}
protected void computeMaxAndMin(){
//initialize max, min
Vector3D max = new Vector3D();
Vector3D min = new Vector3D();
for (int i=0;i<3;i++){
maxVtxs[i] = minVtxs[i] = pointBuffer[0];
}
max.set(pointBuffer[0].pnt);
min.set(pointBuffer[0].pnt);
//check all point to find max, min
for (int i=1;i<numPoints;i++){
Point3D pnt = pointBuffer[i].pnt;
//find maxVtxs[0] and minVtxs[0] , vectors with max x and min x
if (pnt.x >max.x){
max.x = pnt.x;
maxVtxs[0] = pointBuffer[i];
}else if (pnt.x < min.x){
min.x = pnt.x;
minVtxs[0] = pointBuffer[i];
}
//find maxVtxs[1] and minVtxs[1] , vectors with max y and min y
if (pnt.y >max.y){
max.y = pnt.y;
maxVtxs[1] = pointBuffer[i];
}else if (pnt.y < min.y){
min.y = pnt.y;
minVtxs[1] = pointBuffer[i];
}
//find maxVtxs[2] and minVtxs[2] , vectors with max z and min z
if (pnt.z >max.z){
max.z = pnt.z;
maxVtxs[2] = pointBuffer[i];
}else if (pnt.z < min.z){
min.z = pnt.z;
minVtxs[2] = pointBuffer[i];
}
charLength = Math.max(max.x - min.x, max.y - min.y);
charLength = Math.max(max.z - min.z, charLength);
if (explicitTolerance == AUTOMATIC_TOLERANCE){
tolerance = 3* DOUBLE_PREC * (Math.max(Math.abs(max.x), Math.abs(min.x)) + Math.max(Math.abs(max.y), Math.abs(min.y)) + Math.max(Math.abs(max.z), Math.abs(min.z)));
}else{
tolerance = explicitTolerance;
}
}
}
protected void createInitialSimplex() throws IllegalArgumentException{
double max = 0;
int imax = 0;
for (int i = 0; i< 3; i++){
double diff = maxVtxs[i].pnt.get(i)-minVtxs[i].pnt.get(i);
if (diff > max){
max = diff;
imax = i;
}
}
if (max <= tolerance){
throw new IllegalArgumentException("Input points appear to be conicident");
}
Vertex[] vtx = new Vertex[4];
//set first two vertices to be those with the greatest one dimensional separation
vtx[0] = maxVtxs[imax];
vtx[1] = minVtxs[imax];
// set third vertex to be the vertex farthest from the line between vtx0 and vtx1
Vector3D u01 = new Vector3D();
Vector3D diff02 = new Vector3D();
Vector3D nrml = new Vector3D();
}
}
Vertices:
5.0 6.0 3.0
1.0 6.0 1.0
5.0 6.0 1.0
0.0 4.0 2.0
0.0 1.0 1.0
0.0 5.0 1.0
1.0 5.0 0.0
0.0 2.0 2.0
5.0 5.0 0.0
1.0 1.0 0.0
5.0 1.0 0.0
Faces:
1 3 0
9 6 8 10
5 3 1
5 1 6
2 8 6 1
2 1 0
2 0 10 8
7 10 0
7 0 3
4 9 10
4 10 7
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment