Perpendicular Bisector Calculator

Perpendicular Bisector Calculator – Find Midpoint & Slope :root { –primary-color: #004a99; –success-color: #28a745; –background-color: #f8f9fa; –text-color: #333; –border-color: #dee2e6; –card-background: #ffffff; –shadow: 0 4px 8px rgba(0,0,0,0.1); } body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; background-color: var(–background-color); color: var(–text-color); line-height: 1.6; margin: 0; padding: 20px; display: flex; justify-content: center; align-items: flex-start; /* Align items to the top */ min-height: 100vh; } .container { background-color: var(–card-background); padding: 30px; border-radius: 8px; box-shadow: var(–shadow); max-width: 960px; /* Adjusted max-width */ width: 100%; box-sizing: border-box; text-align: center; } h1, h2, h3 { color: var(–primary-color); margin-bottom: 1.5em; } h1 { font-size: 2.5em; } h2 { font-size: 2em; border-bottom: 2px solid var(–primary-color); padding-bottom: 0.5em; margin-top: 1.5em; } h3 { font-size: 1.5em; margin-top: 1em; margin-bottom: 0.8em; } .loan-calc-container { margin-top: 20px; margin-bottom: 30px; padding: 25px; border: 1px solid var(–border-color); border-radius: 8px; background-color: var(–card-background); text-align: left; } .input-group { margin-bottom: 20px; text-align: left; } .input-group label { display: block; margin-bottom: 8px; font-weight: bold; color: var(–primary-color); } .input-group input[type="number"], .input-group select { width: calc(100% – 22px); /* Account for padding and border */ padding: 10px; border: 1px solid var(–border-color); border-radius: 4px; font-size: 1em; margin-bottom: 5px; /* Space for error message */ box-sizing: border-box; } .input-group .helper-text { font-size: 0.85em; color: #6c757d; display: block; margin-top: 5px; } .error-message { color: red; font-size: 0.9em; margin-top: 5px; min-height: 1.2em; /* Reserve space */ } .button-group { margin-top: 25px; display: flex; justify-content: center; gap: 15px; flex-wrap: wrap; /* Allow buttons to wrap on smaller screens */ } button { padding: 12px 25px; border: none; border-radius: 5px; font-size: 1em; cursor: pointer; font-weight: bold; transition: background-color 0.3s ease, transform 0.2s ease; min-width: 150px; /* Ensure consistent button width */ } button.primary { background-color: var(–primary-color); color: white; } button.primary:hover { background-color: #003366; transform: translateY(-2px); } button.secondary { background-color: #6c757d; color: white; } button.secondary:hover { background-color: #5a6268; transform: translateY(-2px); } button.success { background-color: var(–success-color); color: white; } button.success:hover { background-color: #218838; transform: translateY(-2px); } #results { margin-top: 30px; padding: 25px; border: 1px solid var(–border-color); border-radius: 8px; background-color: var(–card-background); text-align: left; display: none; /* Hidden by default */ } #results h3 { text-align: center; margin-top: 0; color: var(–success-color); } .result-item { margin-bottom: 15px; font-size: 1.1em; padding-bottom: 10px; border-bottom: 1px dashed var(–border-color); } .result-item:last-child { border-bottom: none; margin-bottom: 0; padding-bottom: 0; } .result-label { font-weight: bold; color: var(–primary-color); } .result-value { font-weight: bold; color: #28a745; /* Success color for values */ } #mainResult { font-size: 1.8em; color: var(–success-color); text-align: center; margin: 20px 0; padding: 15px; background-color: #e6ffed; border-radius: 5px; font-weight: bold; } .formula-explanation { font-style: italic; color: #555; margin-top: 10px; font-size: 0.95em; text-align: center; } table { width: 100%; border-collapse: collapse; margin-top: 20px; overflow-x: auto; /* Make table scrollable */ display: block; /* For overflow-x to work */ white-space: nowrap; /* Prevent wrapping inside table */ } th, td { padding: 12px 15px; border: 1px solid var(–border-color); text-align: center; } thead { background-color: var(–primary-color); color: white; } tbody tr:nth-child(even) { background-color: #f2f2f2; } caption { font-size: 1.1em; font-weight: bold; color: var(–primary-color); margin-bottom: 10px; caption-side: top; text-align: left; } #chartContainer { width: 100%; max-width: 100%; /* Ensure chart fits within container */ height: 400px; /* Fixed height for canvas */ margin-top: 30px; overflow: hidden; /* Hide overflow content */ position: relative; background-color: white; border: 1px solid var(–border-color); border-radius: 8px; box-sizing: border-box; } #chartCanvas { display: block; max-width: 100%; height: 100%; /* Make canvas fill container */ box-sizing: border-box; } .article-content { margin-top: 40px; text-align: left; background-color: var(–card-background); padding: 30px; border-radius: 8px; box-shadow: var(–shadow); } .article-content h2, .article-content h3 { margin-top: 2em; margin-bottom: 1em; text-align: left; border-bottom: none; padding-bottom: 0; color: var(–primary-color); } .article-content h1 { font-size: 2.2em; text-align: center; margin-bottom: 1em; } .article-content p, .article-content ul, .article-content ol { margin-bottom: 1.5em; font-size: 1.05em; color: #444; } .article-content ul, .article-content ol { padding-left: 25px; } .article-content li { margin-bottom: 10px; } .article-content strong { color: var(–primary-color); } .article-content a { color: var(–primary-color); text-decoration: none; font-weight: bold; } .article-content a:hover { text-decoration: underline; } .faq-item { margin-bottom: 1.5em; padding: 15px; background-color: #e9ecef; border-radius: 5px; } .faq-item strong { display: block; margin-bottom: 8px; color: var(–primary-color); font-size: 1.1em; } .related-tools { margin-top: 30px; padding: 25px; border: 1px solid var(–border-color); border-radius: 8px; background-color: var(–card-background); text-align: left; } .related-tools ul { list-style: none; padding: 0; } .related-tools li { margin-bottom: 15px; padding-bottom: 10px; border-bottom: 1px dashed var(–border-color); } .related-tools li:last-child { border-bottom: none; } .related-tools a { font-weight: bold; color: var(–primary-color); } .related-tools p { margin-top: 5px; font-size: 0.95em; color: #6c757d; } .mobile-scroll-wrapper { overflow-x: auto; -webkit-overflow-scrolling: touch; /* Smooth scrolling on iOS */ margin-bottom: 20px; /* Space below scrollable elements */ } .mobile-scroll-wrapper table { /* Table styles handled by parent for overflow */ white-space: normal; /* Allow text wrapping within cells if needed, but table itself scrolls */ min-width: 600px; /* Ensure table content is wide enough to warrant scrolling */ } .mobile-scroll-wrapper th, .mobile-scroll-wrapper td { white-space: nowrap; /* Keep cell content on one line for scrolling */ } .mobile-scroll-wrapper caption { white-space: normal; /* Allow caption to wrap */ } /* Responsive adjustments */ @media (max-width: 768px) { .container { padding: 20px; } h1 { font-size: 2em; } h2 { font-size: 1.7em; } h3 { font-size: 1.3em; } button { min-width: 120px; padding: 10px 20px; font-size: 0.95em; } #results { padding: 20px; } .result-item { font-size: 1em; } #mainResult { font-size: 1.5em; } .article-content { padding: 20px; } .article-content h1 { font-size: 1.8em; } .article-content h2 { font-size: 1.5em; } .mobile-scroll-wrapper table { min-width: unset; /* Remove min-width on mobile if it causes issues */ } }

Perpendicular Bisector Calculator

Calculate the midpoint, slope, and equation of the perpendicular bisector for any line segment.

Line Segment Endpoints

Perpendicular Bisector Results

Midpoint (M):
Slope of Segment (m_seg):
Slope of Perpendicular Bisector (m_perp):
Equation of Perpendicular Bisector:

The perpendicular bisector is the line that passes through the midpoint of a line segment and is perpendicular to it.

Perpendicular Bisector: Key Values

Key Values of the Perpendicular Bisector
Value Description Result
Midpoint (M) The exact center of the line segment.
Segment Slope (m_seg) The steepness of the original line segment.
Perp. Bisector Slope (m_perp) The steepness of the perpendicular bisector line.
Perp. Bisector Equation The equation defining the perpendicular bisector line (y = mx + c form).

Visual Representation

Visual representation of the line segment and its perpendicular bisector.

Understanding the Perpendicular Bisector Calculator

What is a Perpendicular Bisector?

A perpendicular bisector is a fundamental concept in geometry that defines a unique line related to any given line segment. It's a line that satisfies two critical conditions: it must intersect the original line segment at its exact midpoint, and it must form a 90-degree angle (be perpendicular) with the original line segment. Think of it as the line that cuts a segment exactly in half, perpendicularly. This concept is crucial for various geometric constructions, proving theorems, and solving problems in coordinate geometry. Anyone working with line segments in a mathematical context, such as students, engineers, architects, or surveyors, might need to utilize the properties of a perpendicular bisector.

A common misconception is that a perpendicular bisector is simply any line that crosses another line at a 90-degree angle. However, the "bisector" part is key – it MUST intersect at the midpoint of the segment. Another misconception is that the slope of the perpendicular bisector is simply the negative of the original segment's slope. While related, it's the *negative reciprocal* that is correct.

Perpendicular Bisector Formula and Mathematical Explanation

To find the perpendicular bisector, we need to determine its midpoint and its slope. The process involves a few straightforward steps:

  1. Find the Midpoint (M): The midpoint of a line segment with endpoints $(x_1, y_1)$ and $(x_2, y_2)$ is found by averaging the x-coordinates and the y-coordinates.
  2. Find the Slope of the Original Segment (m_seg): The slope is calculated as the change in y divided by the change in x between the two endpoints.
  3. Find the Slope of the Perpendicular Bisector (m_perp): The slope of a line perpendicular to another is the negative reciprocal of the original line's slope.
  4. Determine the Equation of the Perpendicular Bisector: Using the midpoint (which lies on the perpendicular bisector) and its slope, we can use the point-slope form of a linear equation ($y – y_m = m_{perp}(x – x_m)$) to find the equation, often rearranged into the slope-intercept form ($y = mx + c$).

Step-by-Step Derivation & Variable Explanations

Let the endpoints of the line segment be $P_1(x_1, y_1)$ and $P_2(x_2, y_2)$.

1. Midpoint Calculation

The midpoint $M(x_m, y_m)$ is calculated as:

$x_m = \frac{x_1 + x_2}{2}$

$y_m = \frac{y_1 + y_2}{2}$

2. Slope of the Segment Calculation

The slope of the segment $m_{seg}$ is:

$m_{seg} = \frac{y_2 – y_1}{x_2 – x_1}$

Special Cases:

  • If $x_1 = x_2$, the segment is vertical, and its slope is undefined. The perpendicular bisector will be horizontal with a slope of 0.
  • If $y_1 = y_2$, the segment is horizontal, and its slope is 0. The perpendicular bisector will be vertical with an undefined slope.

3. Slope of the Perpendicular Bisector Calculation

The slope of the perpendicular bisector, $m_{perp}$, is the negative reciprocal of $m_{seg}$:

$m_{perp} = -\frac{1}{m_{seg}} = -\frac{x_2 – x_1}{y_2 – y_1}$

Special Cases:

  • If $m_{seg}$ is undefined (vertical line), $m_{perp} = 0$ (horizontal line).
  • If $m_{seg} = 0$ (horizontal line), $m_{perp}$ is undefined (vertical line).

4. Equation of the Perpendicular Bisector

Using the midpoint $M(x_m, y_m)$ and the perpendicular slope $m_{perp}$, we use the point-slope form $y – y_m = m_{perp}(x – x_m)$. Rearranging to slope-intercept form ($y = mx + c$):

$y = m_{perp}x + (y_m – m_{perp}x_m)$

The y-intercept, $c$, is $y_m – m_{perp}x_m$. If the perpendicular bisector is a vertical line (undefined slope), its equation is simply $x = x_m$.

Variables Table

Variables Used in Perpendicular Bisector Calculation
Variable Meaning Unit Typical Range
$x_1, y_1$ Coordinates of the first endpoint Units (e.g., meters, pixels, abstract units) Any real number
$x_2, y_2$ Coordinates of the second endpoint Units (e.g., meters, pixels, abstract units) Any real number
$x_m, y_m$ Coordinates of the midpoint Units Depends on input coordinates
$m_{seg}$ Slope of the original line segment Ratio (unitless) $(-\infty, \infty)$
$m_{perp}$ Slope of the perpendicular bisector Ratio (unitless) $(-\infty, \infty)$, or undefined
$c$ Y-intercept of the perpendicular bisector Units Depends on midpoint and slope

Practical Examples (Real-World Use Cases)

Understanding the perpendicular bisector has tangible applications:

Example 1: Finding the Center of a Property Line

Imagine you have a plot of land defined by two corner points on a map: $P_1(10, 20)$ and $P_2(50, 60)$. You need to find the exact center point and the direction that cuts this boundary line perpendicularly, perhaps for placing a fence post exactly halfway along the boundary and perpendicular to it.

  • Inputs: $x_1 = 10, y_1 = 20, x_2 = 50, y_2 = 60$.
  • Calculations:
    • Midpoint $x_m = (10 + 50) / 2 = 30$.
    • Midpoint $y_m = (20 + 60) / 2 = 40$. So, $M(30, 40)$.
    • Segment Slope $m_{seg} = (60 – 20) / (50 – 10) = 40 / 40 = 1$.
    • Perpendicular Slope $m_{perp} = -1 / 1 = -1$.
    • Equation: $y – 40 = -1(x – 30) \implies y = -x + 30 + 40 \implies y = -x + 70$.
  • Outputs:
    • Midpoint: $(30, 40)$
    • Segment Slope: $1$
    • Perpendicular Bisector Slope: $-1$
    • Equation: $y = -x + 70$
  • Interpretation: The perpendicular bisector passes through the point (30, 40) and has a slope of -1. This line represents all points equidistant from the two endpoints of the property line segment.

Example 2: Locating a Point Equidistant from Two Landmarks

Suppose you have two known locations, say a fountain at $F_1(5, 15)$ and a statue at $F_2(25, 5)$. You want to find a location on a path that is exactly halfway between them along the line connecting them and perpendicular to that path. This could be relevant for placing a new bench.

  • Inputs: $x_1 = 5, y_1 = 15, x_2 = 25, y_2 = 5$.
  • Calculations:
    • Midpoint $x_m = (5 + 25) / 2 = 15$.
    • Midpoint $y_m = (15 + 5) / 2 = 10$. So, $M(15, 10)$.
    • Segment Slope $m_{seg} = (5 – 15) / (25 – 5) = -10 / 20 = -0.5$.
    • Perpendicular Slope $m_{perp} = -1 / (-0.5) = 2$.
    • Equation: $y – 10 = 2(x – 15) \implies y = 2x – 30 + 10 \implies y = 2x – 20$.
  • Outputs:
    • Midpoint: $(15, 10)$
    • Segment Slope: $-0.5$
    • Perpendicular Bisector Slope: $2$
    • Equation: $y = 2x – 20$
  • Interpretation: The perpendicular bisector is the line $y = 2x – 20$. Any point on this line is equidistant from the fountain and the statue. The midpoint (15, 10) is the specific point on this line that also lies on the segment connecting the fountain and statue.

How to Use This Perpendicular Bisector Calculator

Our perpendicular bisector calculator is designed for simplicity and accuracy. Follow these steps:

  1. Input Coordinates: Enter the X and Y coordinates for the two endpoints of your line segment into the respective input fields (Coordinate 1 X, Coordinate 1 Y, Coordinate 2 X, Coordinate 2 Y).
  2. Validate Inputs: Ensure you enter numerical values. The calculator will show error messages below fields if inputs are invalid (e.g., non-numeric, empty).
  3. Calculate: Click the "Calculate" button.
  4. Review Results: The results section will update in real-time. You will see:
    • The primary result: The equation of the perpendicular bisector.
    • Intermediate values: The midpoint coordinates, the slope of the original segment, and the slope of the perpendicular bisector.
    • A visual chart representing the line segment and its perpendicular bisector.
    • A table summarizing the key calculated values.
  5. Copy Results: If you need to save or use the calculated values elsewhere, click the "Copy Results" button. This will copy the main result and key intermediate values to your clipboard.
  6. Reset: To start over with a new calculation, click the "Reset" button. This will clear all fields and results, restoring default example values.

Decision-Making Guidance: The outputs help you understand the geometric relationship between the line segment and its perpendicular bisector. The midpoint is crucial for finding the exact center. The slopes indicate the orientation and steepness. The equation allows you to find any point lying on the perpendicular bisector, which are all points equidistant from the segment's endpoints.

Key Factors That Affect Perpendicular Bisector Results

While the calculation of a perpendicular bisector is purely mathematical based on coordinates, certain factors influence how we interpret or apply these results in practical scenarios:

  1. Coordinate Precision: The accuracy of your input coordinates directly impacts the precision of the calculated midpoint, slopes, and equation. Small errors in measurement or data entry can lead to noticeable deviations in the results.
  2. Scale and Units: The units used for the coordinates (e.g., meters, feet, pixels) will determine the units of the midpoint and the scale of the visual representation. Ensure consistency in units for meaningful interpretation.
  3. Geometric Context: The meaning of the perpendicular bisector depends on the context. In surveying, it might relate to property boundaries. In engineering, it could be used in designing symmetrical structures or locating points relative to two fixed positions.
  4. Vertical/Horizontal Segments: Special cases arise when the line segment is perfectly vertical ($x_1 = x_2$) or horizontal ($y_1 = y_2$). The slope calculations change (undefined or zero), leading to a horizontal or vertical perpendicular bisector, respectively. These edge cases are handled by the calculator.
  5. Numerical Stability: For very long or very short line segments, or segments with coordinates that are extremely close, floating-point arithmetic limitations might introduce minor inaccuracies. However, for typical use cases, this is negligible.
  6. Data Source Reliability: If the coordinates are derived from real-world measurements (e.g., GPS data, architectural plans), the reliability and potential errors in the source data are critical. The calculator assumes the input data is accurate.

Frequently Asked Questions (FAQ)

Q1: What is the main purpose of finding a perpendicular bisector?

A: The primary purpose is to find the line that is equidistant from the two endpoints of a line segment. It's also fundamental in constructing circumcenters of triangles and in various geometric proofs.

Q2: Can the perpendicular bisector be the same as the original line segment?

A: No, by definition, the perpendicular bisector must intersect the segment at its midpoint and be perpendicular to it. They are distinct lines unless the segment is a single point, which is a degenerate case.

Q3: What happens if the line segment is vertical?

A: If the segment is vertical ($x_1 = x_2$), its slope is undefined. The perpendicular bisector will be a horizontal line with a slope of 0, and its equation will be $y = y_m$, where $y_m$ is the y-coordinate of the midpoint.

Q4: What happens if the line segment is horizontal?

A: If the segment is horizontal ($y_1 = y_2$), its slope is 0. The perpendicular bisector will be a vertical line with an undefined slope, and its equation will be $x = x_m$, where $x_m$ is the x-coordinate of the midpoint.

Q5: How does the midpoint relate to the perpendicular bisector?

A: The midpoint is a crucial point that the perpendicular bisector *always* passes through. It's the intersection point of the segment and its perpendicular bisector.

Q6: Can I use this calculator for 3D coordinates?

A: No, this calculator is designed specifically for 2D Cartesian coordinates (X, Y). Calculating perpendicular bisectors in 3D involves planes and is significantly more complex.

Q7: What if the two endpoints are the same point?

A: If the endpoints are identical, it's a degenerate line segment (a point). Technically, infinitely many lines pass through this point, and the concept of a unique perpendicular bisector doesn't apply in the standard way. The calculator might produce division-by-zero errors or nonsensical results in this case.

Q8: How is the perpendicular bisector used in constructing a triangle's circumcenter?

A: The circumcenter of a triangle (the center of the circle passing through all three vertices) is found at the intersection of the perpendicular bisectors of the triangle's sides. Calculating these bisectors is the first step.

// Function to get input values and perform basic validation function getValidatedInputs() { var x1 = parseFloat(document.getElementById("x1").value); var y1 = parseFloat(document.getElementById("y1").value); var x2 = parseFloat(document.getElementById("x2").value); var y2 = parseFloat(document.getElementById("y2").value); var errors = false; // Clear previous errors document.getElementById("x1Error").textContent = ""; document.getElementById("y1Error").textContent = ""; document.getElementById("x2Error").textContent = ""; document.getElementById("y2Error").textContent = ""; if (isNaN(x1)) { document.getElementById("x1Error").textContent = "Please enter a valid number for X1."; errors = true; } if (isNaN(y1)) { document.getElementById("y1Error").textContent = "Please enter a valid number for Y1."; errors = true; } if (isNaN(x2)) { document.getElementById("x2Error").textContent = "Please enter a valid number for X2."; errors = true; } if (isNaN(y2)) { document.getElementById("y2Error").textContent = "Please enter a valid number for Y2."; errors = true; } if (x1 === x2 && y1 === y2) { document.getElementById("x1Error").textContent = "Endpoints cannot be the same."; document.getElementById("y1Error").textContent = "Endpoints cannot be the same."; document.getElementById("x2Error").textContent = "Endpoints cannot be the same."; document.getElementById("y2Error").textContent = "Endpoints cannot be the same."; errors = true; } if (errors) { return null; } return { x1: x1, y1: y1, x2: x2, y2: y2 }; } // Function to format coordinates function formatCoords(x, y) { if (x === null || y === null || isNaN(x) || isNaN(y)) return "-"; return `(${x.toFixed(3)}, ${y.toFixed(3)})`; } // Function to format slope function formatSlope(slope) { if (slope === null || isNaN(slope)) return "-"; if (slope === Infinity) return "Undefined (Vertical)"; if (slope === -Infinity) return "Undefined (Vertical)"; if (Math.abs(slope) < 1e-9) return "0 (Horizontal)"; // Check for near-zero slope return slope.toFixed(3); } // Function to format equation function formatEquation(slope, midpointX, midpointY) { if (isNaN(slope) || midpointX === null || midpointY === null || isNaN(midpointX) || isNaN(midpointY)) return "-"; if (Math.abs(slope) === Infinity) { // Vertical line return `x = ${midpointX.toFixed(3)}`; } else if (Math.abs(slope) < 1e-9) { // Horizontal line return `y = ${midpointY.toFixed(3)}`; } else { var c = midpointY – slope * midpointX; var slopeStr = slope.toFixed(3); var cStr = c.toFixed(3); if (Math.abs(c) 0) { return `y = ${slopeStr}x + ${cStr}`; } else { return `y = ${slopeStr}x – ${Math.abs(c).toFixed(3)}`; } } } // Main calculation function function calculatePerpendicularBisector() { var inputs = getValidatedInputs(); if (!inputs) { document.getElementById("results").style.display = "none"; return; } var x1 = inputs.x1; var y1 = inputs.y1; var x2 = inputs.x2; var y2 = inputs.y2; // 1. Calculate Midpoint var midpointX = (x1 + x2) / 2; var midpointY = (y1 + y2) / 2; var midpointStr = formatCoords(midpointX, midpointY); // 2. Calculate Slope of the Segment var segmentSlope; if (x1 === x2) { segmentSlope = Infinity; // Vertical segment } else { segmentSlope = (y2 – y1) / (x2 – x1); } var segmentSlopeStr = formatSlope(segmentSlope); // 3. Calculate Slope of the Perpendicular Bisector var perpendicularSlope; if (segmentSlope === Infinity) { // Original segment is vertical perpendicularSlope = 0; // Perpendicular is horizontal } else if (segmentSlope === 0) { // Original segment is horizontal perpendicularSlope = Infinity; // Perpendicular is vertical } else { perpendicularSlope = -1 / segmentSlope; } var perpendicularSlopeStr = formatSlope(perpendicularSlope); // 4. Calculate Equation of the Perpendicular Bisector var equationStr = formatEquation(perpendicularSlope, midpointX, midpointY); // Display Results document.getElementById("mainResult").textContent = equationStr; document.getElementById("midpoint").textContent = midpointStr; document.getElementById("segmentSlope").textContent = segmentSlopeStr; document.getElementById("perpendicularSlope").textContent = perpendicularSlopeStr; // Update Table document.getElementById("tableMidpoint").textContent = midpointStr; document.getElementById("tableSegmentSlope").textContent = segmentSlopeStr; document.getElementById("tablePerpendicularSlope").textContent = perpendicularSlopeStr; document.getElementById("tableEquation").textContent = equationStr; document.getElementById("results").style.display = "block"; // Update Chart updateChart(x1, y1, x2, y2, midpointX, midpointY, perpendicularSlope); } // Function to reset calculator inputs and results function resetCalculator() { document.getElementById("x1").value = "2"; document.getElementById("y1").value = "3"; document.getElementById("x2").value = "8"; document.getElementById("y2").value = "9"; // Clear errors document.getElementById("x1Error").textContent = ""; document.getElementById("y1Error").textContent = ""; document.getElementById("x2Error").textContent = ""; document.getElementById("y2Error").textContent = ""; // Clear results document.getElementById("results").style.display = "none"; document.getElementById("mainResult").textContent = ""; document.getElementById("midpoint").textContent = ""; document.getElementById("segmentSlope").textContent = ""; document.getElementById("perpendicularSlope").textContent = ""; document.getElementById("equation").textContent = ""; // Clear table values document.getElementById("tableMidpoint").textContent = "-"; document.getElementById("tableSegmentSlope").textContent = "-"; document.getElementById("tablePerpendicularSlope").textContent = "-"; document.getElementById("tableEquation").textContent = "-"; // Clear chart if (typeof chartInstance !== 'undefined') { chartInstance.destroy(); } document.getElementById("perpendicularBisectorChart").getContext('2d').clearRect(0, 0, canvas.width, canvas.height); // Clear canvas } // Function to copy results function copyResults() { var mainResult = document.getElementById("mainResult").textContent; var midpoint = document.getElementById("midpoint").textContent; var segmentSlope = document.getElementById("segmentSlope").textContent; var perpSlope = document.getElementById("perpendicularSlope").textContent; var equation = document.getElementById("equation").textContent; var resultText = "Perpendicular Bisector Results:\n"; resultText += "——————————–\n"; resultText += "Equation: " + equation + "\n"; resultText += "Midpoint: " + midpoint + "\n"; resultText += "Segment Slope: " + segmentSlope + "\n"; resultText += "Perpendicular Slope: " + perpSlope + "\n"; // Use a temporary textarea to copy var textArea = document.createElement("textarea"); textArea.value = resultText; textArea.style.position = "fixed"; textArea.style.left = "-9999px"; document.body.appendChild(textArea); textArea.focus(); textArea.select(); try { var successful = document.execCommand('copy'); var msg = successful ? 'Results copied successfully!' : 'Failed to copy results.'; // Optionally show a temporary message to the user alert(msg); } catch (err) { alert('Oops, unable to copy results.'); } document.body.removeChild(textArea); } // — Charting Logic — var chartInstance = null; var canvas = document.getElementById('perpendicularBisectorChart'); function updateChart(x1, y1, x2, y2, mx, my, m_perp) { if (chartInstance) { chartInstance.destroy(); } var ctx = canvas.getContext('2d'); ctx.clearRect(0, 0, canvas.width, canvas.height); // Clear previous drawings // Determine chart boundaries var allX = [x1, x2, mx]; var allY = [y1, y2, my]; // Calculate potential range for perpendicular bisector line points var extendFactor = 1.5; // Extend lines beyond segment endpoints var deltaX = Math.max(Math.abs(x1 – x2), 10) * extendFactor; // Ensure some minimum range var deltaY = Math.max(Math.abs(y1 – y2), 10) * extendFactor; var minX = Math.min(x1, x2) – deltaX; var maxX = Math.max(x1, x2) + deltaX; var minY = Math.min(y1, y2) – deltaY; var maxY = Math.max(y1, y2) + deltaY; // Adjust range based on perpendicular slope to ensure visibility if (Math.abs(m_perp) currentYRange * 1.2) { // If perp line needs more Y range var midY = (minY + maxY) / 2; minY = midY – rangeY / 2; maxY = midY + rangeY / 2; } else { var midX = (minX + maxX) / 2; var neededXRange = currentYRange / Math.abs(m_perp); minX = midX – neededXRange / 2; maxX = midX + neededXRange / 2; } } // Add padding to the bounds var paddingX = (maxX – minX) * 0.1; var paddingY = (maxY – minY) * 0.1; minX -= paddingX; maxX += paddingX; minY -= paddingY; maxY += paddingY; // Ensure bounds are reasonable and not collapsed if (minX === maxX) { minX -= 1; maxX += 1; } if (minY === maxY) { minY -= 1; maxY += 1; } // Calculate points for the original segment var segmentPoints = [ { x: x1, y: y1 }, { x: x2, y: y2 } ]; // Calculate points for the perpendicular bisector line var perpLinePoints = []; if (Math.abs(m_perp) === Infinity) { // Vertical line: x = mx perpLinePoints = [ { x: mx, y: minY }, { x: mx, y: maxY } ]; } else if (Math.abs(m_perp) = minX && point.x = minY && point.y <= maxY; }); // If filtered points are too few, add midpoint explicitly if (perpLinePoints.length < 2) { perpLinePoints.push({ x: mx, y: my }); } chartInstance = new Chart(ctx, { type: 'scatter', // Use scatter for points, line for lines data: { datasets: [ { label: 'Line Segment Endpoints', data: segmentPoints, backgroundColor: 'rgba(255, 99, 132, 0.8)', // Red for segment borderColor: 'rgba(255, 99, 132, 1)', pointRadius: 6, pointHoverRadius: 8, showLine: false // Don't draw line between segment points }, { label: 'Perpendicular Bisector', data: perpLinePoints, // Use calculated points for the line backgroundColor: 'rgba(54, 162, 235, 0.8)', // Blue for perp bisector borderColor: 'rgba(54, 162, 235, 1)', pointRadius: 0, // Hide individual points on the perp line pointHoverRadius: 5, showLine: true // Draw the line }, { label: 'Midpoint', data: [{ x: mx, y: my }], backgroundColor: 'rgba(75, 192, 192, 0.8)', // Green for midpoint borderColor: 'rgba(75, 192, 192, 1)', pointRadius: 7, pointHoverRadius: 9, showLine: false } ] }, options: { responsive: true, maintainAspectRatio: false, // Allow height control scales: { x: { type: 'linear', position: 'bottom', title: { display: true, text: 'X-coordinate' }, min: minX, max: maxX }, y: { title: { display: true, text: 'Y-coordinate' }, min: minY, max: maxY } }, plugins: { legend: { position: 'top', }, title: { display: true, text: 'Line Segment and Perpendicular Bisector' } }, tooltips: { // For older Chart.js versions callbacks: { label: function(tooltipItem, data) { var datasetLabel = data.datasets[tooltipItem.datasetIndex].label || ''; var xLabel = tooltipItem.xLabel.toFixed(3); var yLabel = tooltipItem.yLabel.toFixed(3); return datasetLabel + ': (' + xLabel + ', ' + yLabel + ')'; } } }, hover: { // For newer Chart.js versions mode: 'nearest', intersect: true, callbacks: { label: function(context) { var label = context.dataset.label || ''; if (label) { label += ': '; } if (context.parsed.x !== null) { label += '(' + context.parsed.x.toFixed(3) + ', ' + context.parsed.y.toFixed(3) + ')'; } return label; } } } } }); } // Initial setup: Call calculate on page load if default values exist document.addEventListener('DOMContentLoaded', function() { // Set default values on load document.getElementById("x1").value = "2"; document.getElementById("y1").value = "3"; document.getElementById("x2").value = "8"; document.getElementById("y2").value = "9"; calculatePerpendicularBisector(); // Calculate with default values // Add event listeners for input changes to update dynamically var inputs = document.querySelectorAll('.loan-calc-container input[type="number"]'); for (var i = 0; i < inputs.length; i++) { inputs[i].addEventListener('input', calculatePerpendicularBisector); } }); // Placeholder for Chart.js library if needed (this implementation is pure JS/Canvas) // In a real WordPress environment, you'd enqueue Chart.js properly. // For this single HTML file, assume Chart.js is available. // For this specific problem, I'll use native Canvas API drawing if Chart.js is not assumed. // — Correction: Re-reading the prompt, it says "Pure SVG () OR Native ". // I will implement using Native Canvas API drawing instead of Chart.js to avoid external dependency. // *** REVISING to native canvas drawing logic *** // — Revised Native Canvas Drawing Logic — function drawLine(ctx, x1, y1, x2, y2, color, lineWidth) { ctx.beginPath(); ctx.moveTo(x1, y1); ctx.lineTo(x2, y2); ctx.strokeStyle = color; ctx.lineWidth = lineWidth; ctx.stroke(); } function drawPoint(ctx, x, y, color, radius) { ctx.beginPath(); ctx.arc(x, y, radius, 0, Math.PI * 2); ctx.fillStyle = color; ctx.fill(); } // Global variables for canvas drawing var canvas = document.getElementById('perpendicularBisectorChart'); var ctx = canvas.getContext('2d'); var chartMargin = 40; // Margin around the drawing area function updateChart(x1, y1, x2, y2, mx, my, m_perp) { ctx.clearRect(0, 0, canvas.width, canvas.height); // Clear canvas // Determine chart boundaries dynamically based on input range + padding var allX = [x1, x2, mx]; var allY = [y1, y2, my]; // Calculate a sensible range for the axes var minInputX = Math.min(x1, x2); var maxInputX = Math.max(x1, x2); var minInputY = Math.min(y1, y2); var maxInputY = Math.max(y1, y2); var deltaX = Math.max(maxInputX – minInputX, 10); // Min span to avoid issues var deltaY = Math.max(maxInputY – minInputY, 10); var rangeX = deltaX * 2.5; // Extend range significantly var rangeY = deltaY * 2.5; // Adjust range based on perpendicular slope to ensure visibility if (Math.abs(m_perp) rangeY * 1.1) { // Need more Y range rangeY = potentialYRangeFromX * 1.1; minY = my – rangeY / 2; maxY = my + rangeY / 2; minX = mx – rangeX / 2; // Keep X range based on inputs maxX = mx + rangeX / 2; } else { // Need more X range rangeX = potentialXRangeFromY * 1.1; minX = mx – rangeX / 2; maxX = mx + rangeX / 2; minY = my – rangeY / 2; // Keep Y range based on inputs maxY = my + rangeY / 2; } } // Add padding to the bounds var paddingX = rangeX * 0.1; var paddingY = rangeY * 0.1; minX -= paddingX; maxX += paddingX; minY -= paddingY; maxY += paddingY; // Ensure bounds are reasonable and not collapsed if (minX === maxX) { minX -= 1; maxX += 1; } if (minY === maxY) { minY -= 1; maxY += 1; } // Transform coordinates from data space to canvas space function transformX(x) { return chartMargin + ((x – minX) / (maxX – minX)) * (canvas.width – 2 * chartMargin); } function transformY(y) { return canvas.height – chartMargin – ((y – minY) / (maxY – minY)) * (canvas.height – 2 * chartMargin); } // Draw Axes ctx.strokeStyle = '#ccc'; ctx.lineWidth = 1; // X Axis var xAxisY = transformY(0); if (xAxisY >= chartMargin && xAxisY <= canvas.height – chartMargin) { drawLine(ctx, chartMargin, xAxisY, canvas.width – chartMargin, xAxisY, '#ccc', 1); } else if (0 = chartMargin && yAxisX <= canvas.width – chartMargin) { drawLine(ctx, yAxisX, chartMargin, yAxisX, canvas.height – chartMargin, '#ccc', 1); } else if (0 < minX) { // If 0 is left of canvas, draw left line drawLine(ctx, chartMargin, chartMargin, chartMargin, canvas.height – chartMargin, '#ccc', 1); } else { // If 0 is right of canvas, draw right line drawLine(ctx, canvas.width – chartMargin, chartMargin, canvas.width – chartMargin, canvas.height – chartMargin, '#ccc', 1); } // Draw original line segment drawLine(ctx, transformX(x1), transformY(y1), transformX(x2), transformY(y2), 'red', 3); // Draw midpoint drawPoint(ctx, transformX(mx), transformY(my), 'green', 6); // Draw perpendicular bisector line var perpPoints = []; if (Math.abs(m_perp) === Infinity) { // Vertical line: x = mx perpPoints.push({ x: transformX(mx), y: transformY(minY) }); perpPoints.push({ x: transformX(mx), y: transformY(maxY) }); } else if (Math.abs(m_perp) = chartMargin && p.x = chartMargin && p.y <= canvas.height – chartMargin; }); // Ensure at least two points to draw a line, or just the midpoint if calculation fails if (perpPoints.length = 2) { drawLine(ctx, perpPoints[0].x, perpPoints[0].y, perpPoints[1].x, perpPoints[1].y, 'blue', 3); } else if (perpPoints.length === 1) { // Draw a point if only one is valid drawPoint(ctx, perpPoints[0].x, perpPoints[0].y, 'blue', 5); } // Add point for endpoints (optional, but helpful) drawPoint(ctx, transformX(x1), transformY(y1), 'red', 5); drawPoint(ctx, transformX(x2), transformY(y2), 'red', 5); // Optional: Add labels for axes or key points if space allows ctx.fillStyle = 'black'; ctx.font = '12px Arial'; ctx.textAlign = 'center'; ctx.fillText('X', canvas.width – chartMargin, transformY(0) + 15); // X-axis label ctx.fillText('Y', chartMargin – 15, chartMargin + 5); // Y-axis label // Add labels for endpoints and midpoint ctx.font = '10px Arial'; ctx.fillText('P1', transformX(x1), transformY(y1) – 10); ctx.fillText('P2', transformX(x2), transformY(y2) – 10); ctx.fillText('M', transformX(mx), transformY(my) – 10); } // Ensure canvas is sized correctly on load and resize function resizeCanvas() { var container = document.getElementById('chartContainer'); canvas.width = container.clientWidth; canvas.height = container.clientHeight; // Redraw chart if inputs are available var inputs = getValidatedInputs(); // Check if valid inputs exist if (inputs) { calculatePerpendicularBisector(); // Recalculate and redraw } } window.addEventListener('resize', resizeCanvas); // Initial canvas setup document.addEventListener('DOMContentLoaded', function() { resizeCanvas(); // Set initial size // Set default values on load document.getElementById("x1").value = "2"; document.getElementById("y1").value = "3"; document.getElementById("x2").value = "8"; document.getElementById("y2").value = "9"; calculatePerpendicularBisector(); // Calculate with default values // Add event listeners for input changes to update dynamically var inputs = document.querySelectorAll('.loan-calc-container input[type="number"]'); for (var i = 0; i < inputs.length; i++) { inputs[i].addEventListener('input', calculatePerpendicularBisector); } });

Leave a Comment