Support SMTP URLs
[zxing.git] / core / src / com / google / zxing / ResultPoint.java
1 /*
2  * Copyright 2007 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;
18
19 /**
20  * <p>Encapsulates a point of interest in an image containing a barcode. Typically, this
21  * would be the location of a finder pattern or the corner of the barcode, for example.</p>
22  *
23  * @author Sean Owen
24  */
25 public class ResultPoint {
26
27   private final float x;
28   private final float y;
29
30   public ResultPoint(float x, float y) {
31     this.x = x;
32     this.y = y;
33   }
34
35   public final float getX() {
36     return x;
37   }
38
39   public final float getY() {
40     return y;
41   }
42
43   public boolean equals(Object other) {
44     if (other instanceof ResultPoint) {
45       ResultPoint otherPoint = (ResultPoint) other;
46       return x == otherPoint.x && y == otherPoint.y;
47     }
48     return false;
49   }
50
51   public int hashCode() {
52     return 31 * Float.floatToIntBits(x) + Float.floatToIntBits(y);
53   }
54
55   public String toString() {
56     StringBuffer result = new StringBuffer(25);
57     result.append('(');
58     result.append(x);
59     result.append(',');
60     result.append(y);
61     result.append(')');
62     return result.toString();
63   }
64
65   /**
66    * <p>Orders an array of three ResultPoints in an order [A,B,C] such that AB < AC and
67    * BC < AC and the angle between BC and BA is less than 180 degrees.
68    */
69   public static void orderBestPatterns(ResultPoint[] patterns) {
70
71     // Find distances between pattern centers
72     float zeroOneDistance = distance(patterns[0], patterns[1]);
73     float oneTwoDistance = distance(patterns[1], patterns[2]);
74     float zeroTwoDistance = distance(patterns[0], patterns[2]);
75
76     ResultPoint pointA, pointB, pointC;
77     // Assume one closest to other two is B; A and C will just be guesses at first
78     if (oneTwoDistance >= zeroOneDistance && oneTwoDistance >= zeroTwoDistance) {
79       pointB = patterns[0];
80       pointA = patterns[1];
81       pointC = patterns[2];
82     } else if (zeroTwoDistance >= oneTwoDistance && zeroTwoDistance >= zeroOneDistance) {
83       pointB = patterns[1];
84       pointA = patterns[0];
85       pointC = patterns[2];
86     } else {
87       pointB = patterns[2];
88       pointA = patterns[0];
89       pointC = patterns[1];
90     }
91
92     // Use cross product to figure out whether A and C are correct or flipped.
93     // This asks whether BC x BA has a positive z component, which is the arrangement
94     // we want for A, B, C. If it's negative, then we've got it flipped around and
95     // should swap A and C.
96     if (crossProductZ(pointA, pointB, pointC) < 0.0f) {
97       ResultPoint temp = pointA;
98       pointA = pointC;
99       pointC = temp;
100     }
101
102     patterns[0] = pointA;
103     patterns[1] = pointB;
104     patterns[2] = pointC;
105   }
106
107
108   /**
109    * @return distance between two points
110    */
111   public static float distance(ResultPoint pattern1, ResultPoint pattern2) {
112     float xDiff = pattern1.getX() - pattern2.getX();
113     float yDiff = pattern1.getY() - pattern2.getY();
114     return (float) Math.sqrt((double) (xDiff * xDiff + yDiff * yDiff));
115   }
116
117   /**
118    * Returns the z component of the cross product between vectors BC and BA.
119    */
120   private static float crossProductZ(ResultPoint pointA, ResultPoint pointB, ResultPoint pointC) {
121     float bX = pointB.x;
122     float bY = pointB.y;
123     return ((pointC.x - bX) * (pointA.y - bY)) - ((pointC.y - bY) * (pointA.x - bX));
124   }
125
126
127 }