001/*******************************************************************************
002 * This software is provided as a supplement to the authors' textbooks on digital
003 * image processing published by Springer-Verlag in various languages and editions.
004 * Permission to use and distribute this software is granted under the BSD 2-Clause
005 * "Simplified" License (see http://opensource.org/licenses/BSD-2-Clause).
006 * Copyright (c) 2006-2023 Wilhelm Burger, Mark J. Burge. All rights reserved.
007 * Visit https://imagingbook.com for additional details.
008 ******************************************************************************/
009package imagingbook.common.geometry.line;
010
011import imagingbook.common.math.Arithmetic;
012
013import java.util.Locale;
014
015/**
016 * <p>
017 * This class represents a line in slope-intercept form: y = k x + d. Instances are immutable. Not all possible lines in
018 * the 2D plane can be represented. A {@link SlopeInterceptLine} is merely a {@link AlgebraicLine} with a special
019 * constructor and getter methods for k, d. See Sec. 10.1 and Appendix F.1 of [1] for details.
020 * </p>
021 * <p>
022 * [1] W. Burger, M.J. Burge, <em>Digital Image Processing &ndash; An Algorithmic Introduction</em>, 3rd ed, Springer
023 * (2022).
024 * </p>
025 *
026 * @author WB
027 * @version 2022/11/18
028 */
029public class SlopeInterceptLine extends AlgebraicLine {
030        
031        public SlopeInterceptLine(double k, double d) {
032                super(k, -1, d);
033        }
034        
035        public SlopeInterceptLine(AlgebraicLine al) {
036                super(al.getParameters());
037                if (Arithmetic.isZero(al.B)) {
038                        throw new IllegalArgumentException("cannot convert vertical line (B=0)");
039                }
040        }
041        
042        public double getK() {
043                return A / -B;  // = k
044        }
045
046        public double getD() {
047                return C / -B;  // = d
048        }
049
050        /**
051         * Returns the line's y-value for the specified x-position.
052         *
053         * @param x position along the x-axis
054         * @return the associated y-value
055         */
056        public double getY(double x) {
057                return (A * x + C) / -B;        // = y = k * x + d
058        }
059        
060        // --------------------------------------------------
061        
062        @Override
063        public String toString() {
064                return String.format(Locale.US, "%s <A=%.3f B=%.3f C=%.3f k=%.3f, d=%.3f>",
065                                this.getClass().getSimpleName(), A, B, C, getK(), getD());
066        }
067        
068        // --------------------------------------------------
069        
070//      public static void main (String[] args) {
071//              Pnt2d p1 = Pnt2d.from(1, 2);
072//              Pnt2d p2 = Pnt2d.from(4, 3);
073//              
074//              AlgebraicLine al1 = AlgebraicLine.from(p1, p2);
075//              System.out.println("al1 = " + al1);
076//              
077//              SlopeInterceptLine sl = new SlopeInterceptLine(al1);
078//              System.out.println("sl = " + sl);
079//              System.out.println("sl k = " + (sl.A / -sl.B));
080//              System.out.println("sl d = " + (sl.C / -sl.B));
081//              
082//              AlgebraicLine al2 = AlgebraicLine.from(sl);
083//              System.out.println("al2 = " + al2);
084//              
085//              System.out.println("al1 = al2 ? " + al1.equals(al2, 1e-6));
086//      }
087/*
088al1 = AlgebraicLine <a=0.316, b=-0.949, c=1.581>
089sl = SlopeInterceptLine <A=0.316 B=-0.949 C=1.581 k=0.333, d=1.667>
090sl k = 0.33333333333333337
091sl d = 1.6666666666666665
092al2 = AlgebraicLine <a=0.316, b=-0.949, c=1.581>
093al1 = al2 ? true
094*/
095}