Issue 158: Correct some off-by-one problems in Data Matrix detector and a few more...
[zxing.git] / core / src / com / google / zxing / common / GenericResultPoint.java
1 /*
2  * Copyright 2008 ZXing authors
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package com.google.zxing.common;
18
19 import com.google.zxing.ResultPoint;
20
21 /**
22  * <p>Simple implementation of {@link ResultPoint} for applications that don't need
23  * to use anything more complex.</p>
24  *
25  * @author dswitkin@google.com (Daniel Switkin)
26  */
27 public final class GenericResultPoint implements ResultPoint {
28
29   private final float posX;
30   private final float posY;
31
32   public GenericResultPoint(float posX, float posY) {
33     this.posX = posX;
34     this.posY = posY;
35   }
36
37   public float getX() {
38     return posX;
39   }
40
41   public float getY() {
42     return posY;
43   }
44
45   public String toString() {
46     StringBuffer result = new StringBuffer(25);
47     result.append('(');
48     result.append(posX);
49     result.append(',');
50     result.append(posY);
51     result.append(')');
52     return result.toString();
53   }
54
55   public boolean equals(Object other) {
56     if (other instanceof GenericResultPoint) {
57       GenericResultPoint otherPoint = (GenericResultPoint) other;
58       return posX == otherPoint.posX && posY == otherPoint.posY;
59     }
60     return false;
61   }
62
63   public int hashCode() {
64     return 31 * Float.floatToIntBits(posX) + Float.floatToIntBits(posY);
65   }
66
67     /**
68    * <p>Orders an array of three ResultPoints in an order [A,B,C] such that AB < AC and
69    * BC < AC and the angle between BC and BA is less than 180 degrees.
70    */
71   public static void orderBestPatterns(ResultPoint[] patterns) {
72
73     // Find distances between pattern centers
74     float zeroOneDistance = distance(patterns[0], patterns[1]);
75     float oneTwoDistance = distance(patterns[1], patterns[2]);
76     float zeroTwoDistance = distance(patterns[0], patterns[2]);
77
78     ResultPoint pointA, pointB, pointC;
79     // Assume one closest to other two is B; A and C will just be guesses at first
80     if (oneTwoDistance >= zeroOneDistance && oneTwoDistance >= zeroTwoDistance) {
81       pointB = patterns[0];
82       pointA = patterns[1];
83       pointC = patterns[2];
84     } else if (zeroTwoDistance >= oneTwoDistance && zeroTwoDistance >= zeroOneDistance) {
85       pointB = patterns[1];
86       pointA = patterns[0];
87       pointC = patterns[2];
88     } else {
89       pointB = patterns[2];
90       pointA = patterns[0];
91       pointC = patterns[1];
92     }
93
94     // Use cross product to figure out whether A and C are correct or flipped.
95     // This asks whether BC x BA has a positive z component, which is the arrangement
96     // we want for A, B, C. If it's negative, then we've got it flipped around and
97     // should swap A and C.
98     if (crossProductZ(pointA, pointB, pointC) < 0.0f) {
99       ResultPoint temp = pointA;
100       pointA = pointC;
101       pointC = temp;
102     }
103
104     patterns[0] = pointA;
105     patterns[1] = pointB;
106     patterns[2] = pointC;
107   }
108
109
110   /**
111    * @return distance between two points
112    */
113   public static float distance(ResultPoint pattern1, ResultPoint pattern2) {
114     float xDiff = pattern1.getX() - pattern2.getX();
115     float yDiff = pattern1.getY() - pattern2.getY();
116     return (float) Math.sqrt((double) (xDiff * xDiff + yDiff * yDiff));
117   }
118
119   /**
120    * Returns the z component of the cross product between vectors BC and BA.
121    */
122   public static float crossProductZ(ResultPoint pointA, ResultPoint pointB, ResultPoint pointC) {
123     float bX = pointB.getX();
124     float bY = pointB.getY();
125     return ((pointC.getX() - bX) * (pointA.getY() - bY)) - ((pointC.getY() - bY) * (pointA.getX() - bX));
126   }
127
128 }