Skip to content

Commit

Permalink
Merge 726079d into da50e67
Browse files Browse the repository at this point in the history
  • Loading branch information
henrythasler committed Nov 16, 2019
2 parents da50e67 + 726079d commit 54bd9fa
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 69 deletions.
5 changes: 4 additions & 1 deletion docs/testing-circle.html
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,10 @@
color: 'red',
fill: true,
steps: 80
}).addTo(map);
}).bindTooltip("<Area>").bindPopup("GeodesicCircle").addTo(map);

geodesiccircle.setRadius(geodesiccircle.distanceTo(B.getLatLng()));
geodesiccircle.setTooltipContent(`Area: ${Math.round(geodesiccircle.radius**2*Math.PI/1000**2)} km²`);

var info = L.control();
info.onAdd = function (map) {
Expand Down Expand Up @@ -113,11 +114,13 @@
geodesiccircle.setLatLng(e.latlng);
geodesiccircle.setRadius(geodesiccircle.distanceTo(B.getLatLng()));
info.update(geodesiccircle.statistics);
geodesiccircle.setTooltipContent(`Area: ${Math.round(geodesiccircle.radius**2*Math.PI/1000**2)} km²`);
});
B.on('drag', (e) => {
B.setTooltipContent(`${Math.round(10000 * e.latlng.lat) / 10000} ${Math.round(10000 * e.latlng.lng) / 10000}`);
geodesiccircle.setRadius(geodesiccircle.distanceTo(e.latlng));
info.update(geodesiccircle.statistics);
geodesiccircle.setTooltipContent(`Area: ${Math.round(geodesiccircle.radius**2*Math.PI/1000**2)} km²`);
});

</script>
Expand Down
72 changes: 32 additions & 40 deletions spec/geodesic-circle.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,69 +33,65 @@ function checkFixture(specimen: L.LatLngLiteral[][], fixture: L.LatLngLiteral[][
});
}

function compareObject(specimen: object, fixture: object): void {
for (let [key, value] of Object.entries(specimen)) {
expect(specimen).to.have.own.property(key, value);
}
}

describe("Main functionality", function () {
let container: HTMLElement;
let map: L.Map;
const radius = 1000 * 1000;

beforeEach(function () {
map = L.map(document.createElement('div'));
});

afterEach(function () {
map.remove();
container = document.createElement('div');
container.style.width = '400px';
container.style.height = '400px';
map = L.map(container, { renderer: new L.SVG(), center: [0, 0], zoom: 12 });
});

it("Create class w/o any parameters", function () {
const circle = new GeodesicCircleClass();
expect(circle.options).to.be.deep.equal(defaultOptions);
expect(circle.polyline).to.be.an("object");
expect(circle).to.be.instanceOf(GeodesicCircleClass);
compareObject(circle.options, defaultOptions);
});

it("Create class with parameters", function () {
const circle = new GeodesicCircleClass(Beijing, { steps: 48 });
expect(circle.options).to.be.deep.equal({ ...defaultOptions, ...{ steps: 48 } });
expect(circle.polyline).to.be.an("object");
expect(circle).to.be.instanceOf(GeodesicCircleClass);
compareObject(circle.options, defaultOptions);
});

it("Add empty circle to map", async function () {
const circle = new GeodesicCircleClass().addTo(map);
expect(circle.options).to.be.deep.equal(defaultOptions);
expect(circle.polyline).to.be.an("object");

expect(circle).to.be.instanceOf(GeodesicCircleClass);
compareObject(circle.options, defaultOptions);
expect(map.hasLayer(circle)).to.be.true;
map.eachLayer(function (layer) {
expect(layer).to.be.instanceOf(GeodesicCircleClass);
});
});

it("update center", async function () {
const circle = new GeodesicCircleClass(Seattle).addTo(map);
expect(circle).to.be.instanceOf(GeodesicCircleClass);
compareObject(circle.options, defaultOptions);
expect(map.hasLayer(circle)).to.be.true;

circle.setLatLng(Beijing);
expect(circle.options).to.be.deep.equal(defaultOptions);
expect(circle.polyline).to.be.an("object");
expect(circle.center.lat).to.be.closeTo(Beijing.lat, eps);
expect(circle.center.lng).to.be.closeTo(Beijing.lng, eps);
expect(circle.radius).to.be.closeTo(radius, eps);

expect(map.hasLayer(circle)).to.be.true;
map.eachLayer(function (layer) {
expect(layer).to.be.instanceOf(GeodesicCircleClass);
});
});

it("update radius", async function () {
const circle = new GeodesicCircleClass(Seattle, { radius: radius }).addTo(map);
expect(circle.options).to.be.deep.equal({ ...defaultOptions, ...{ radius: radius } });
expect(circle.polyline).to.be.an("object");
expect(circle).to.be.instanceOf(GeodesicCircleClass);
compareObject(circle.options, { ...defaultOptions, ...{ radius: radius } });
expect(map.hasLayer(circle)).to.be.true;

expect(circle.center.lat).to.be.closeTo(Seattle.lat, eps);
expect(circle.center.lng).to.be.closeTo(Seattle.lng, eps);
circle.setRadius(2 * radius);
expect(circle.radius).to.be.closeTo(2 * radius, eps);

expect(map.hasLayer(circle)).to.be.true;
map.eachLayer(function (layer) {
expect(layer).to.be.instanceOf(GeodesicCircleClass);
});
});

it("distance function (wrapper for vincenty inverse)", function () {
Expand All @@ -117,30 +113,26 @@ describe("Main functionality", function () {
});

describe("Bugs", function () {
let container: HTMLElement;
let map: L.Map;

beforeEach(function () {
map = L.map(document.createElement('div'));
});

afterEach(function () {
map.remove();
container = document.createElement('div');
container.style.width = '400px';
container.style.height = '400px';
map = L.map(container, { renderer: new L.SVG(), center: [0, 0], zoom: 12 });
});

it("Calling getBounds on a GeodesicCircle throws an error (#48)", async function () {
const circle = new GeodesicCircleClass(Seattle, { radius: 10});
const group = new L.FeatureGroup([circle]).addTo(map);

expect(circle.options).to.be.deep.equal({ ...defaultOptions, ...{ radius: 10 } });
expect(circle.polyline).to.be.an("object");
compareObject(circle.options, { ...defaultOptions, ...{ radius: 10 } });
expect(circle.center.lat).to.be.closeTo(Seattle.lat, eps);
expect(circle.center.lng).to.be.closeTo(Seattle.lng, eps);

expect(map.hasLayer(group)).to.be.true;
map.eachLayer(function (layer) {
expect(layer).to.be.instanceOf(L.FeatureGroup);
});


const bounds = group.getBounds();
expect(bounds).to.be.instanceOf(L.LatLngBounds);
checkFixture([[bounds.getCenter()]], [[Seattle]]);
Expand Down
38 changes: 10 additions & 28 deletions src/geodesic-circle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,48 +3,30 @@ import { GeodesicGeometry, Statistics } from "./geodesic-geom"
import { GeodesicOptions } from "./geodesic-core"
import { latlngExpressiontoLiteral } from "./types-helper";

export class GeodesicCircleClass extends L.Layer {
polyline: L.Polyline;
options: GeodesicOptions = { wrap: true, steps: 24, fill: true, noClip: true };
export class GeodesicCircleClass extends L.Polyline {
defaultOptions: GeodesicOptions = { wrap: true, steps: 24, fill: true, noClip: true};
private geom: GeodesicGeometry;
center: L.LatLngLiteral = { lat: 0, lng: 0 };
radius: number = 0;
radius: number = 1000 * 1000;
statistics: Statistics = {} as any;

constructor(center?: L.LatLngExpression, options?: GeodesicOptions) {
super();
this.options = { ...this.options, ...options }; // noClip prevents broken fills
super([], options);
L.Util.setOptions(this, {...this.defaultOptions, ...options});

this.geom = new GeodesicGeometry(this.options);
const extendedOptions = this.options as GeodesicOptions;
this.radius = (extendedOptions.radius === undefined) ? 1000 * 1000 : extendedOptions.radius;

this.radius = (this.options.radius === undefined) ? 1000 * 1000 : this.options.radius;
this.geom = new GeodesicGeometry(this.options);

if (center) {
this.center = latlngExpressiontoLiteral(center);
let latlngs = this.geom.circle(this.center, this.radius);
this.statistics = this.geom.updateStatistics([[this.center]], [latlngs]);
// circumfence must be re-calculated from geodesic
this.statistics.totalDistance = this.geom.multilineDistance([latlngs]).reduce((x, y) => x + y, 0);

this.polyline = new L.Polyline(latlngs, this.options);
this.setLatLngs(latlngs);
}
else {
this.polyline = new L.Polyline([], this.options);
}
}

onAdd(map: L.Map): this {
this.polyline.addTo(map);
return this;
}

onRemove(): this {
this.polyline.remove();
return this;
}

getBounds(): L.LatLngBounds {
return this.polyline.getBounds();
}

private update(): void {
Expand All @@ -54,7 +36,7 @@ export class GeodesicCircleClass extends L.Layer {
// circumfence must be re-calculated from geodesic
this.statistics.totalDistance = this.geom.multilineDistance([latlngs]).reduce((x, y) => x + y, 0);

this.polyline.setLatLngs(latlngs);
this.setLatLngs(latlngs);
}

distanceTo(latlng: L.LatLngExpression): number {
Expand Down

0 comments on commit 54bd9fa

Please sign in to comment.