View Javadoc
1   /*
2    * Copyright (c) 2002-2025 Gargoyle Software Inc.
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    * https://www.apache.org/licenses/LICENSE-2.0
8    *
9    * Unless required by applicable law or agreed to in writing, software
10   * distributed under the License is distributed on an "AS IS" BASIS,
11   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12   * See the License for the specific language governing permissions and
13   * limitations under the License.
14   */
15  package org.htmlunit.util.geometry;
16  
17  /**
18   * Simple 2D shape line.
19   *
20   * @author Ronald Brill
21   */
22  public class Line2D implements Shape2D {
23  
24      private final double startX_;
25      private final double startY_;
26      private final double endX_;
27      private final double endY_;
28      private final boolean isVertical_;
29  
30      private final double slope_;
31      private final double yIntercept_;
32  
33      /**
34       * Ctor.
35       * @param start the start point
36       * @param end the end point
37       */
38      public Line2D(final Point2D start, final Point2D end) {
39          this(start.getX(), start.getY(), end.getX(), end.getY());
40      }
41  
42      /**
43       * Ctor.
44       * @param x1 the x value of the start point
45       * @param y1 the y value of the start point
46       * @param x2 the x value of the end point
47       * @param y2 the y value of the end point
48       */
49      public Line2D(final double x1, final double y1, final double x2, final double y2) {
50          startX_ = x1;
51          startY_ = y1;
52          endX_ = x2;
53          endY_ = y2;
54  
55          isVertical_ = Math.abs(startX_ - endX_) < EPSILON;
56          if (isVertical_) {
57              slope_ = Double.NaN;
58              yIntercept_ = Double.NaN;
59          }
60          else {
61              // y = slope * x + b
62              slope_ = (endY_ - startY_) / (endX_ - startX_);
63              yIntercept_ = startY_ - slope_ * startX_;
64          }
65      }
66  
67      /**
68       * @param line the line to intersect this with
69       * @return the intersection point of the two lines or null if they are parallel
70       */
71      public Point2D intersect(final Line2D line) {
72          if (isVertical_ && line.isVertical_) {
73              return null;
74          }
75  
76          if (isVertical_ && !line.isVertical_) {
77              final double intersectY = line.slope_ * startX_ + line.yIntercept_;
78              return new Point2D(startX_, intersectY);
79          }
80  
81          if (!isVertical_ && line.isVertical_) {
82              final double intersectY = slope_ * line.startX_ + yIntercept_;
83              return new Point2D(line.startX_, intersectY);
84          }
85  
86          // parallel?
87          if (Math.abs(slope_ - line.slope_) < EPSILON) {
88              return null;
89          }
90  
91          // x = (n2-n1)/(m1-m2)
92          final double intersectX = (line.yIntercept_ - yIntercept_) / (slope_ - line.slope_);
93          // y = m2*x+n2
94          final double intersectY = slope_ * intersectX + yIntercept_;
95          return new Point2D(intersectX, intersectY);
96      }
97  
98      /**
99       * {@inheritDoc}
100      */
101     @Override
102     public boolean contains(final double x, final double y) {
103         if (isVertical_) {
104             if (Math.abs(startX_ - x) > EPSILON) {
105                 return false;
106             }
107         }
108         else {
109             final double testY = slope_ * x + yIntercept_;
110             if (Math.abs(y - testY) > EPSILON) {
111                 return false;
112             }
113 
114             if (x < startX_ && x < endX_
115                     || (x > startX_ && x > endX_)) {
116                 return false;
117             }
118         }
119 
120         if (y < startY_ && y < endY_
121                 || (y > startY_ && y > endY_)) {
122             return false;
123         }
124 
125         return true;
126     }
127 
128     /**
129      * {@inheritDoc}
130      */
131     @Override
132     public boolean isEmpty() {
133         return Math.abs(startX_ - endX_) < EPSILON && Math.abs(startY_ - endY_) < EPSILON;
134     }
135 
136     @Override
137     public String toString() {
138         return "Line2D [ (" + startX_ + ", " + startY_ + "), (" + endX_ + ", " + endY_
139                 + "), " + (isVertical_ ? "isVertical" : "y = " + slope_ + "*x + " + yIntercept_ + "]");
140     }
141 }