How do I draw such an arch through a chord point or corners?

The following task is worth it. Required using the library Maker.js draw an arch like this:

enter a description of the image here

Drawing an arch starts from the origin (0,0). The library automatically flips the image, since in svg the coordinates start from the upper-left corner. Input data (entered by the user):

L - Width (bottom base)
H - Height on the right
H1 - Height on the left
R - Radius (Cannot be less than R>L/2)

In the library Maker.js creating any shape is done through models (concept). My my model:

this.model = {
  models: {
    arch: {
      paths: {
        "h1": new makerjs.paths.Line([0, 0], [0, +this.parameters.H1.value]),
        "arc": new makerjs.paths.Arc( /* Необходимо вставить параметры */ ),
        "h2": new makerjs.paths.Line([+this.parameters.L.value, +this.parameters.H.value], [+this.parameters.L.value, 0]),
        "l": new makerjs.paths.Line([+this.parameters.L.value, 0], [0, 0]),
      },
    },
  },
};

In the Maker.The js circle can be constructed by 4 variants of. Of the proposed options, only 2 options are suitable for me. Or by three points:

new Arc(pointA: IPoint, pointB: IPoint, pointC: IPoint): Arc

Or by two points radius and angles:

new Arc(origin: IPoint, radius: number, startAngle: number, endAngle: number):

In the first option I do not know how to get a point on chord (marked in red), and in the second option I can't calculate the angles.


The calculation of points or angles must work correctly for a large radius (for example: 1000) and for equal H and H1 (H===H1).

2 answers

I advise you to learn how to build paths in your head, in fact it is very simple, in this particular case it is easier if you combine absolute and relative commands.

We start at point 0;0 is the command m0,0

Moving down to H1-command v${H1}

Then right on L - h${L}

Up on H - v${-H}

And now a small life hack - no longer need to count anything - the end point of the arc-the origin of coordinates-that is, it remains to draw the arc. radius by absolute command to point 0;0 - A${R},${R},0,0,0,0,0

let H = 60, H1 = 40, L = 40, R = 23.5;

path.setAttribute("d", `m0,0v${H1}h${L}v${-H}A${R},${R},0,0,0,0,0z`)
<svg viewbox=-100,-100,200,200><path id=path fill=none stroke=black></path></svg>
 3
Author: Stranger in the Q, 2019-10-07 07:32:48

When it is R - radius:

const makerjs = require('makerjs');

const L = 200;
const H = 200;
const H1 = 150;
const R = 150;

// Вычисение точки
function getArchCoordinate() {
  if (H === H1) {
    return {
      x: L/2,
      y: H + R - Math.sqrt(Math.abs(Math.pow(R, 2) - Math.pow(L, 2) / 4)),
    }
  } else {
    const big_hypotenuse = Math.sqrt(Math.pow(H - H1, 2) + Math.pow(L, 2));
    const height = R - Math.sqrt(Math.abs(Math.pow(R, 2) - Math.pow(big_hypotenuse, 2) / 4));
    return {
      x: L/2 - height*(H - H1)/big_hypotenuse,
      y: (H1 + H)/2 + height * L/big_hypotenuse,
    };
  }
}

const arch = getArchCoordinate();

const model = {
  models: {
    arch: {
      paths: {
        "line1": new makerjs.paths.Line([0, 0], [0, H1]),
        "arc": new makerjs.paths.Arc([0, H1], [arch.x, arch.y], [L, H]),
        "line2": new makerjs.paths.Line([L, H], [L, 0]),
        "line3": new makerjs.paths.Line([L, 0], [0, 0]),
      },
    },
  },
};

const svg = makerjs.exporter.toSVG(model);

document.write(svg);
<script src="https://cdn.jsdelivr.net/npm/makerjs@0/target/js/browser.maker.js"></script>

When R is the height of the segment:

const makerjs = require('makerjs');

const L = 100;
const H = 200;
const H1 = 100;
const R = 30;

function getArchCoordinate() {
 
  const x = L/2 - R*(H-H1)/Math.sqrt(L*L + (H-H1)*(H-H1));
  const y = H1 + (H-H1)/2 + R*L/Math.sqrt(L*L + (H-H1)*(H-H1));

  console.log('x', x);
  console.log('y', y);
  
  return {
    x: x,
    y: y,
  };
    
}

const arch = getArchCoordinate();

const model = {
  models: {
    arch: {
      paths: {
        "line1": new makerjs.paths.Line([0, 0], [0, H1]),
        "arc": new makerjs.paths.Arc([0, H1], [arch.x, arch.y], [L, H]),
        "line2": new makerjs.paths.Line([L, H], [L, 0]),
        "line3": new makerjs.paths.Line([L, 0], [0, 0]),
      },
    },
  },
};

const svg = makerjs.exporter.toSVG(model);

document.write(svg);
<script src="https://cdn.jsdelivr.net/npm/makerjs@0/target/js/browser.maker.js"></script>

UPD Detailed description and options for finding the desired point are described in here and here.

 1
Author: Не быть рабом на Руси, 2019-10-24 07:17:03