initial commit

This commit is contained in:
Alfred Melch 2019-07-14 20:37:26 +02:00
commit cf40583989
118 changed files with 28228 additions and 0 deletions

3
.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
.vscode/
node_modules/
*.wat

3
benchmarking/.babelrc Normal file
View File

@ -0,0 +1,3 @@
{
"presets": ["@babel/preset-react"]
}

4
benchmarking/.prettierrc Normal file
View File

@ -0,0 +1,4 @@
{
"semi": false,
"singleQuote": true
}

9878
benchmarking/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

45
benchmarking/package.json Normal file
View File

@ -0,0 +1,45 @@
{
"name": "linestring-simplification",
"version": "0.1.0",
"description": "",
"main": "index.js",
"directories": {
"lib": "lib"
},
"scripts": {
"build": "webpack --mode development",
"serve": "webpack serve",
"test": "echo \"Error: no test specified\" && exit 1",
"lint": "prettier --check '**/*.js'",
"format": "prettier --write '**/*.js'"
},
"repository": {
"type": "git",
"url": "git@qgit.de:melch/linestring-simplification.git"
},
"author": "Alfred Melch (code@melch.pro)",
"license": "ISC",
"dependencies": {
"benchmark": "^2.1.4",
"chart.js": "^2.8.0",
"eslint-plugin-standard": "^4.0.0",
"lodash": "^4.17.11",
"react": "^16.8.6",
"react-chartjs-2": "^2.7.6",
"react-dom": "^16.8.6"
},
"devDependencies": {
"@babel/core": "^7.4.5",
"@babel/preset-react": "^7.0.0",
"@webpack-cli/serve": "^0.1.8",
"babel-loader": "^8.0.6",
"clean-webpack-plugin": "^3.0.0",
"copy-webpack-plugin": "^5.0.3",
"file-loader": "^4.0.0",
"prettier": "^1.18.2",
"react-hot-loader": "^4.12.0",
"webpack": "^4.34.0",
"webpack-cli": "^3.3.4",
"webpack-dev-server": "^3.7.1"
}
}

View File

@ -0,0 +1,23 @@
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<link rel="stylesheet" href="./style.css">
</head>
<body>
<header>
<h1>Benchmarking</h1>
</header>
<main>
<div id="root"></div>
</main>
<script src="./bundle.js"></script>
</body>
</html>

View File

@ -0,0 +1,53 @@
html,
body {
font-family: Arial, Helvetica, sans-serif;
margin: 0;
padding: 0;
}
main {
width: 80%;
margin: 0 auto;
}
#status {
background-color: bisque;
}
form {
display: grid;
grid-template-columns: auto auto;
grid-gap: 10px;
align-items: center;
margin-top: 20px;
}
input[type="submit"] {
grid-column: 1 / -1;
}
#app {
display: flex;
flex-wrap: wrap;
border: 1px solid black;
justify-content: space-around;
}
#app > div {
margin: 10px 6px;
border: 1px solid red;
}
#form-component {
white-space: normal;
}
#chart-component {
width: 600px;
}
@media screen and (max-width: 800px) {
#app {
display: block;
}
#chart-component {
width: auto;
}
}

View File

@ -0,0 +1,12 @@
export class Case {
constructor(params) {
this.parameters = params
}
async fn() {
throw Error('No function to benchmark not implemented')
}
async setup() {}
async tearDown() {}
}

View File

@ -0,0 +1,43 @@
import { simplifyJSCase, origSimplifyJSCase } from './simplifyJS.js'
import {
transformToArrayFormCase,
transformToObjectFormCase,
origSimplifyWithTransformCase
} from './transforms.js'
import {
simplifyWASMCase,
storeCoordsCase,
loadResultCase
} from './simplifyWasm.js'
export const chartDependencies = {
wasmStack: [storeCoordsCase, loadResultCase, simplifyWASMCase],
simplifyJSStack: [
origSimplifyWithTransformCase,
transformToArrayFormCase,
transformToObjectFormCase
],
wasmVsJs: [origSimplifyJSCase, simplifyWASMCase, simplifyJSCase]
}
const uniqueFilter = (val, idx, self) => self.indexOf(val) === idx
export function getChartDependencies(chartNames) {
return chartNames
.map(name => chartDependencies[name])
.flat()
.filter(uniqueFilter)
}
export function generateCases(data, formState) {
const cases = []
const { tolRange, highQual, chart } = formState
let params = { data, highQuality: highQual }
for (let tol of tolRange) {
params = { ...params, tol }
for (let BenchCaseClass of chartDependencies[chart]) {
cases.push(new BenchCaseClass(params))
}
}
return cases
}

View File

@ -0,0 +1,33 @@
import { Case } from './Case.js'
import simplifyJS from '../../../lib/simplify-js-alternative/simplify.js'
import origSimplifyJS from '../../../lib/turf-simplify/lib/simplify.js'
function arrayToObjectFormat(coords) {
return coords.map(coord => {
return { x: coord[0], y: coord[1] }
})
}
export class simplifyJSCase extends Case {
get name() {
return 'simplifyJS'
}
async fn() {
const { data, tol, highQuality } = this.parameters
simplifyJS(data, tol, highQuality)
}
}
export class origSimplifyJSCase extends Case {
get name() {
return 'origSimplifyJS'
}
async setup() {
this.parameters.dataObjectForm = arrayToObjectFormat(this.parameters.data)
}
async fn() {
const { dataObjectForm, tol, highQuality } = this.parameters
origSimplifyJS(dataObjectForm, tol, highQuality)
}
}

View File

@ -0,0 +1,59 @@
import {
loadResult,
loadResultAndFreeMemory,
storeCoords
} from '../../../lib/wasm-util/coordinates.js'
import { simplifyWasm, getModule } from '../../../lib/simplify-wasm/index.js'
import { Case } from './Case.js'
export class simplifyWASMCase extends Case {
get name() {
return 'simplifyWASM'
}
async setup() {
this.parameters.module = await getModule()
}
async fn() {
const { data, tol, highQuality } = this.parameters
await simplifyWasm(data, tol, highQuality)
}
}
export class storeCoordsCase extends Case {
get name() {
return 'storeCoords'
}
async setup() {
this.parameters.module = await getModule()
}
async fn() {
const { module, data } = this.parameters
const buffer = storeCoords(module, data)
module._free(buffer)
}
}
export class loadResultCase extends Case {
get name() {
return 'loadResult'
}
async setup() {
const { data, tol, highQual } = this.parameters
const module = await getModule()
const buffer = storeCoords(module, data)
const result = module._simplify(buffer, data.length * 2, tol, highQual)
module._free(buffer)
this.parameters = { ...this.parameters, module, result }
}
async fn() {
const { module, result } = this.parameters
loadResult(module, result)
}
async tearDown() {
const { module, result } = this.parameters
loadResultAndFreeMemory(module, result)
}
}

View File

@ -0,0 +1,47 @@
import origSimplifyJS from '../../../lib/simplify-js/simplify.js'
import { Case } from './Case.js'
function arrayToObjectFormat(coords) {
return coords.map(coord => {
return { x: coord[0], y: coord[1] }
})
}
function objectToArrayFormat(coords) {
return coords.map(coord => [coord.x, coord.y])
}
export class transformToObjectFormCase extends Case {
get name() {
return 'transformToObjectFormCase'
}
async fn() {
arrayToObjectFormat(this.parameters.data)
}
}
export class transformToArrayFormCase extends Case {
get name() {
return 'transformToArrayFormCase'
}
async setup() {
const { data, tol, highQuality } = this.parameters
const transformed = arrayToObjectFormat(data)
this.parameters.simplified = origSimplifyJS(transformed, tol, highQuality)
}
async fn() {
objectToArrayFormat(this.parameters.simplified)
}
}
export class origSimplifyWithTransformCase extends Case {
get name() {
return 'origSimplifyWithTransformCase'
}
async fn() {
const { data, tol, highQuality } = this.parameters
const transformed = arrayToObjectFormat(data)
const simplified = origSimplifyJS(transformed, tol, highQuality)
objectToArrayFormat(simplified)
}
}

View File

@ -0,0 +1,31 @@
export class BenchmarkType {
/**
* Superclass for benchmarking a Case
* @param {object} parameters - Parameters for use in fn
* @param {object} functions - setup, fn and tearDown methods
*/
constructor() {
this.stats = {}
}
setCase(benchmarkCase) {
this.case = benchmarkCase
}
/** Returns the mean time in milliseconds */
async run() {
let mean
if (typeof this.case === 'undefined') {
throw Error('no Benchmarking case set')
}
await this.case.setup()
mean = await this.measure()
await this.case.tearDown()
return mean
}
/** Implementation of the benchmarking procedure */
async measure() {
throw new Error('Method "measure" not implemented!')
}
}

View File

@ -0,0 +1,40 @@
import { Benchmark as BenchmarkJS } from './initBenchmarkJS.js'
import { BenchmarkType } from './Benchmark.js'
export class BenchmarkJSBenchmark extends BenchmarkType {
async measure() {
this.constructSuite()
await this.runSuite()
return this.mean
}
constructSuite() {
this.suite = new BenchmarkJS.Suite()
this.suite.add(this.case.name, {
defer: true,
fn: this.resolvingFn.bind(this)
})
this.suite.on('cycle', this.onCycle.bind(this))
}
async resolvingFn(deferred) {
await this.case.fn()
deferred.resolve()
}
onCycle(ev) {
this.mean = ev.target.stats.mean * 1000
}
async runSuite() {
const suitePromise = this.promisifySuite()
this.suite.run({ async: true })
await suitePromise
}
promisifySuite() {
return new Promise(resolve => {
this.suite.on('complete', resolve)
})
}
}

View File

@ -0,0 +1,48 @@
export class BenchmarkSuite {
constructor() {
this.reset()
}
reset() {
this.cases = []
this.stats = {}
}
setBenchmarkType(benchmarktype) {
this.benchmarktype = benchmarktype
}
setCases(cases) {
this.stats = {}
this.cases = cases
for (let c of this.cases) {
this.stats[c.name] = []
}
}
onCycle(i, count, stats) {}
async run(callback) {
let mean
let i = 0
const count = this.cases.length
this.onCycle(i, count, this.stats)
for (const benchCase of this.cases) {
this.benchmarktype.setCase(benchCase)
mean = await this.benchmarktype.run()
this.stats[benchCase.name] = [...this.stats[benchCase.name], mean]
i++
this.onCycle(i, count, this.stats)
await this.freeEventLoop()
}
}
/**
* Promise that uses setTimeout to resolve.
* This is a hack to free the eventloop from microtasks.
* Without this rendering blocks during benchmarks.
*/
async freeEventLoop() {
return new Promise(resolve => setTimeout(resolve, 0))
}
}

View File

@ -0,0 +1,17 @@
import { BenchmarkType } from './Benchmark.js'
export class IterationsBenchmark extends BenchmarkType {
constructor(iterations) {
super()
this.iterations = iterations
}
async measure() {
let start = performance.now()
for (let i = 0; i < this.iterations; i++) {
await this.case.fn()
}
let stop = performance.now()
return (stop - start) / this.iterations
}
}

View File

@ -0,0 +1,19 @@
import { BenchmarkType } from './Benchmark.js'
export class OpsPerTimeBenchmark extends BenchmarkType {
constructor(timeToRun) {
super()
this.timeToRun = timeToRun
}
async measure() {
let start = performance.now()
let iterations = 0
while (performance.now() - start < this.timeToRun) {
iterations++
await this.case.fn()
}
let stop = performance.now()
return (stop - start) / iterations
}
}

View File

@ -0,0 +1,9 @@
import { IterationsBenchmark } from './IterationBenchmark'
import { OpsPerTimeBenchmark } from './OpsPerTimeBenchmark'
import { BenchmarkJSBenchmark } from './BenchmarkJSBenchmark'
export const benchmarkTypes = {
benchmarkJS: BenchmarkJSBenchmark,
iteration: IterationsBenchmark,
opsPerTime: OpsPerTimeBenchmark
}

View File

@ -0,0 +1,6 @@
import _ from 'lodash'
import process from 'process'
const benchmark = require('benchmark')
export const Benchmark = benchmark.runInContext({ _, process })
window.Benchmark = Benchmark

View File

@ -0,0 +1,104 @@
import React, { Component } from 'react'
import { Line } from 'react-chartjs-2'
import { data } from '../../../data/large.js'
import simplifyJS from '../../../lib/simplify-js-alternative/simplify.js'
export function simplifyMapper(labels, highQual) {
// console.log(labels, highQual)
// console.log(labels.map(tol => simplifyJS(data, tol, highQual)))
return labels.map(tol => simplifyJS(data, tol, highQual).length)
}
export class Chart extends Component {
constructor(props) {
super(props)
this.state = {
data: chartData,
options: chartOptions
}
}
render() {
let labels = this.props.labels.map(x => x.toFixed(3))
const data = { ...chartData, labels }
data.datasets[0].data = this.props.data['simplifyWASM'] || []
data.datasets[1].data = this.props.data['simplifyJS'] || []
data.datasets[2].data = this.props.data['origSimplifyJS'] || []
data.datasets[3].data = simplifyMapper(
this.props.labels,
this.props.highQual
)
return (
<div id="chart-component">
<h2>Chart</h2>
<Line
height={400}
width={600}
data={data}
options={this.state.options}
/>
</div>
)
}
}
const chartData = {
datasets: [
{
label: 'simplifyWASM',
backgroundColor: 'red',
borderColor: 'red',
fill: false
},
{
label: 'simplifyJS',
backgroundColor: 'blue',
borderColor: 'blue',
fill: false
},
{
label: 'origSimplifyJS',
backgroundColor: 'green',
borderColor: 'green',
fill: false
},
{
label: 'numberOfNodes',
fill: false,
yAxisID: 'nodes',
data: [1, 2, 3]
}
]
}
const chartOptions = {
title: {
display: true,
text: 'simplifyWasm VS simplifyJS'
},
tooltips: {
mode: 'index',
intersect: false
},
hover: {
mode: 'nearest',
intersect: false
},
scales: {
yAxes: [
{
id: 'performance',
type: 'linear'
},
{
id: 'nodes',
position: 'right',
type: 'linear',
gridLines: {
drawOnChartArea: false
}
}
]
}
}

View File

@ -0,0 +1,145 @@
import React, { Component } from 'react'
export class Form extends Component {
constructor(props) {
super(props)
this.state = {
tolStart: 0.1,
tolStep: 0.1,
tolEnd: 1,
highQual: true,
chart: 'wasmVsJs',
benchMethod: 'iteration',
iterations: 10,
timeToRun: 200
}
this.handleInputChange = this.handleInputChange.bind(this)
this.handleSubmit = this.handleSubmit.bind(this)
this.props.onFormChange(this.state)
}
handleSubmit(event) {
event.preventDefault()
this.props.onFormSubmit()
}
handleInputChange(event) {
let name, value
const target = event.target
value = target.type === 'checkbox' ? target.checked : target.value
value = target.type === 'number' ? Number(value) : value
value = target.type === 'range' ? Number(value) : value
name = target.name
this.setState({ [name]: value })
this.props.onFormChange({ ...this.state, [name]: value })
}
render() {
return (
<div id="form-component">
<h2>Settings</h2>
<form onSubmit={this.handleSubmit}>
<label>Tolerance start: </label>
<input
name="tolStart"
type="number"
min="0.001"
max="1"
step="0.001"
value={this.state.tolStart}
onChange={this.handleInputChange}
/>
<label>Tolerance step: </label>
<input
name="tolStep"
type="number"
min="0.001"
max="1"
step="0.001"
value={this.state.tolStep}
onChange={this.handleInputChange}
/>
<label>Tolerance end: </label>
<input
name="tolEnd"
type="number"
min="0.01"
max="5"
step="0.01"
value={this.state.tolEnd}
onChange={this.handleInputChange}
/>
<label>high Quality: </label>
<input
name="highQual"
type="checkbox"
checked={this.state.highQual}
onChange={this.handleInputChange}
/>
<label>Chart: </label>
<select
name="chart"
value={this.state.chart}
onChange={this.handleInputChange}
>
<option value="wasmVsJs">simplifyWasm vs. simplifyJS</option>
<option value="wasmStack">wasmStack</option>
<option value="simplifyStack">simplifyStack</option>
</select>
<label>Benchmarking method: </label>
<select
name="benchMethod"
value={this.state.benchMethod}
onChange={this.handleInputChange}
>
<option value="iteration">
Iterations (fast - low significance)
</option>
<option value="benchmarkJS">
BenchmarkJS (slow - statistically significant)
</option>
<option value="opsPerTime">
OpsPerTime (slow - low significance)
</option>
</select>
{this.state.benchMethod === 'iteration' && (
<label>Iterations ({this.state.iterations})</label>
)}
{this.state.benchMethod === 'iteration' && (
<input
name="iterations"
type="range"
min="1"
max="100"
step="1"
value={this.state.iterations}
onChange={this.handleInputChange}
></input>
)}
{this.state.benchMethod === 'opsPerTime' && (
<label>Time to run ({this.state.timeToRun}ms)</label>
)}
{this.state.benchMethod === 'opsPerTime' && (
<input
name="timeToRun"
type="range"
min="100"
max="1000"
step="10"
value={this.state.timeToRun}
onChange={this.handleInputChange}
></input>
)}
<input type="submit" value="run" />
</form>
</div>
)
}
}

View File

@ -0,0 +1,14 @@
import React from 'react'
export const Progress = props => {
const { totalCount, finishedCount } = props
let percentage = totalCount === 0 ? 0 : (finishedCount * 100) / totalCount
percentage = percentage.toFixed(2)
let text = `${percentage}% of benchmarks completed (${finishedCount}/${totalCount})`
return (
<div id="progress-component">
<h2>Status</h2>
<span>{text}</span>
</div>
)
}

102
benchmarking/src/index.js Normal file
View File

@ -0,0 +1,102 @@
import React, { Component } from 'react'
import ReactDOM from 'react-dom'
import { data } from '../../data/large.js'
import { Form } from './components/form.js'
import { Chart } from './components/chart.js'
import { Progress } from './components/progress.js'
import { BenchmarkSuite } from './benchmarks/BenchmarkSuite.js'
import { generateCases } from './benchmarkCases/index.js'
import { IterationsBenchmark } from './benchmarks/IterationBenchmark.js'
import { BenchmarkJSBenchmark } from './benchmarks/BenchmarkJSBenchmark.js'
import { OpsPerTimeBenchmark } from './benchmarks/OpsPerTimeBenchmark.js'
class App extends Component {
constructor(props) {
super(props)
this.handleformChange = this.handleformChange.bind(this)
this.handleFormSubmit = this.handleFormSubmit.bind(this)
this.state = {
stats: {},
formState: { tolRange: [] },
totalCount: 0,
finishedCount: 0
}
this.suite = new BenchmarkSuite(new IterationsBenchmark(10))
this.suite.onCycle = (i, count, stats) => {
this.setState({
finishedCount: i,
totalCount: count,
stats: stats
})
}
}
async handleFormSubmit() {
this.runBenchmarks()
}
handleformChange(formState) {
const { tolStart, tolEnd, tolStep } = formState
const tolRange = []
for (let i = tolStart; i < tolEnd; i += tolStep) {
tolRange.push(i)
}
this.setState({ formState: { ...formState, tolRange } })
}
async runBenchmarks() {
this.suite.reset()
let benchtype
console.log(this.state.formState.benchMethod)
switch (this.state.formState.benchMethod) {
case 'benchmarkJS':
benchtype = new BenchmarkJSBenchmark()
break
case 'iteration':
benchtype = new IterationsBenchmark(this.state.formState.iterations)
break
case 'opsPerTime':
benchtype = new OpsPerTimeBenchmark(this.state.formState.timeToRun)
break
default:
console.warn('benchmark type "' + this.state.benchtype + '" not known')
benchtype = new IterationsBenchmark(10)
}
this.suite.setBenchmarkType(benchtype)
this.suite.setCases(generateCases(data, this.state.formState))
updateStatus('Running')
await this.suite.run()
updateStatus('Finished')
}
render() {
return (
<div id="app">
<Form
onFormChange={this.handleformChange}
onFormSubmit={this.handleFormSubmit}
/>
<Progress
totalCount={this.state.totalCount}
finishedCount={this.state.finishedCount}
/>
<Chart
labels={this.state.formState.tolRange}
highQual={this.state.formState.highQual}
data={this.state.stats}
/>
</div>
)
}
}
ReactDOM.render(<App />, document.getElementsByTagName('main')[0])
const updateStatus = status => {
console.log(status)
}

View File

@ -0,0 +1,40 @@
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const CopyPlugin = require('copy-webpack-plugin')
const path = require('path')
module.exports = {
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
},
module: {
// Suppress warnings and errors logged by benchmark.js when bundled using webpack.
noParse: [path.resolve(__dirname, './node_modules/benchmark/benchmark.js')],
rules: [
{
test: /\.js$/,
loaders: ['babel-loader'],
exclude: [/node_modules/, /data/]
},
{
test: /\.wasm$/,
type: 'javascript/auto',
loader: 'file-loader',
options: {
name: '[name].[hash:5].[ext]'
}
}
]
},
plugins: [new CleanWebpackPlugin(), new CopyPlugin([{ from: 'public' }])],
devtool: 'source-map',
// to make webpack work with emscripten js files
target: 'web',
node: {
__dirname: false,
fs: 'empty',
Buffer: false,
process: false
}
}

1
data/large.js Normal file

File diff suppressed because one or more lines are too long

1
data/small.js Normal file
View File

@ -0,0 +1 @@
export const data = [[0, 0], [1, 1], [1, 2], [2, 2], [5, 5], [5, 0], [6, 10], [10, 10]]

470
lib/psimpl/LICENSE.txt Normal file
View File

@ -0,0 +1,470 @@
MOZILLA PUBLIC LICENSE
Version 1.1
---------------
1. Definitions.
1.0.1. "Commercial Use" means distribution or otherwise making the
Covered Code available to a third party.
1.1. "Contributor" means each entity that creates or contributes to
the creation of Modifications.
1.2. "Contributor Version" means the combination of the Original
Code, prior Modifications used by a Contributor, and the Modifications
made by that particular Contributor.
1.3. "Covered Code" means the Original Code or Modifications or the
combination of the Original Code and Modifications, in each case
including portions thereof.
1.4. "Electronic Distribution Mechanism" means a mechanism generally
accepted in the software development community for the electronic
transfer of data.
1.5. "Executable" means Covered Code in any form other than Source
Code.
1.6. "Initial Developer" means the individual or entity identified
as the Initial Developer in the Source Code notice required by Exhibit
A.
1.7. "Larger Work" means a work which combines Covered Code or
portions thereof with code not governed by the terms of this License.
1.8. "License" means this document.
1.8.1. "Licensable" means having the right to grant, to the maximum
extent possible, whether at the time of the initial grant or
subsequently acquired, any and all of the rights conveyed herein.
1.9. "Modifications" means any addition to or deletion from the
substance or structure of either the Original Code or any previous
Modifications. When Covered Code is released as a series of files, a
Modification is:
A. Any addition to or deletion from the contents of a file
containing Original Code or previous Modifications.
B. Any new file that contains any part of the Original Code or
previous Modifications.
1.10. "Original Code" means Source Code of computer software code
which is described in the Source Code notice required by Exhibit A as
Original Code, and which, at the time of its release under this
License is not already Covered Code governed by this License.
1.10.1. "Patent Claims" means any patent claim(s), now owned or
hereafter acquired, including without limitation, method, process,
and apparatus claims, in any patent Licensable by grantor.
1.11. "Source Code" means the preferred form of the Covered Code for
making modifications to it, including all modules it contains, plus
any associated interface definition files, scripts used to control
compilation and installation of an Executable, or source code
differential comparisons against either the Original Code or another
well known, available Covered Code of the Contributor's choice. The
Source Code can be in a compressed or archival form, provided the
appropriate decompression or de-archiving software is widely available
for no charge.
1.12. "You" (or "Your") means an individual or a legal entity
exercising rights under, and complying with all of the terms of, this
License or a future version of this License issued under Section 6.1.
For legal entities, "You" includes any entity which controls, is
controlled by, or is under common control with You. For purposes of
this definition, "control" means (a) the power, direct or indirect,
to cause the direction or management of such entity, whether by
contract or otherwise, or (b) ownership of more than fifty percent
(50%) of the outstanding shares or beneficial ownership of such
entity.
2. Source Code License.
2.1. The Initial Developer Grant.
The Initial Developer hereby grants You a world-wide, royalty-free,
non-exclusive license, subject to third party intellectual property
claims:
(a) under intellectual property rights (other than patent or
trademark) Licensable by Initial Developer to use, reproduce,
modify, display, perform, sublicense and distribute the Original
Code (or portions thereof) with or without Modifications, and/or
as part of a Larger Work; and
(b) under Patents Claims infringed by the making, using or
selling of Original Code, to make, have made, use, practice,
sell, and offer for sale, and/or otherwise dispose of the
Original Code (or portions thereof).
(c) the licenses granted in this Section 2.1(a) and (b) are
effective on the date Initial Developer first distributes
Original Code under the terms of this License.
(d) Notwithstanding Section 2.1(b) above, no patent license is
granted: 1) for code that You delete from the Original Code; 2)
separate from the Original Code; or 3) for infringements caused
by: i) the modification of the Original Code or ii) the
combination of the Original Code with other software or devices.
2.2. Contributor Grant.
Subject to third party intellectual property claims, each Contributor
hereby grants You a world-wide, royalty-free, non-exclusive license
(a) under intellectual property rights (other than patent or
trademark) Licensable by Contributor, to use, reproduce, modify,
display, perform, sublicense and distribute the Modifications
created by such Contributor (or portions thereof) either on an
unmodified basis, with other Modifications, as Covered Code
and/or as part of a Larger Work; and
(b) under Patent Claims infringed by the making, using, or
selling of Modifications made by that Contributor either alone
and/or in combination with its Contributor Version (or portions
of such combination), to make, use, sell, offer for sale, have
made, and/or otherwise dispose of: 1) Modifications made by that
Contributor (or portions thereof); and 2) the combination of
Modifications made by that Contributor with its Contributor
Version (or portions of such combination).
(c) the licenses granted in Sections 2.2(a) and 2.2(b) are
effective on the date Contributor first makes Commercial Use of
the Covered Code.
(d) Notwithstanding Section 2.2(b) above, no patent license is
granted: 1) for any code that Contributor has deleted from the
Contributor Version; 2) separate from the Contributor Version;
3) for infringements caused by: i) third party modifications of
Contributor Version or ii) the combination of Modifications made
by that Contributor with other software (except as part of the
Contributor Version) or other devices; or 4) under Patent Claims
infringed by Covered Code in the absence of Modifications made by
that Contributor.
3. Distribution Obligations.
3.1. Application of License.
The Modifications which You create or to which You contribute are
governed by the terms of this License, including without limitation
Section 2.2. The Source Code version of Covered Code may be
distributed only under the terms of this License or a future version
of this License released under Section 6.1, and You must include a
copy of this License with every copy of the Source Code You
distribute. You may not offer or impose any terms on any Source Code
version that alters or restricts the applicable version of this
License or the recipients' rights hereunder. However, You may include
an additional document offering the additional rights described in
Section 3.5.
3.2. Availability of Source Code.
Any Modification which You create or to which You contribute must be
made available in Source Code form under the terms of this License
either on the same media as an Executable version or via an accepted
Electronic Distribution Mechanism to anyone to whom you made an
Executable version available; and if made available via Electronic
Distribution Mechanism, must remain available for at least twelve (12)
months after the date it initially became available, or at least six
(6) months after a subsequent version of that particular Modification
has been made available to such recipients. You are responsible for
ensuring that the Source Code version remains available even if the
Electronic Distribution Mechanism is maintained by a third party.
3.3. Description of Modifications.
You must cause all Covered Code to which You contribute to contain a
file documenting the changes You made to create that Covered Code and
the date of any change. You must include a prominent statement that
the Modification is derived, directly or indirectly, from Original
Code provided by the Initial Developer and including the name of the
Initial Developer in (a) the Source Code, and (b) in any notice in an
Executable version or related documentation in which You describe the
origin or ownership of the Covered Code.
3.4. Intellectual Property Matters
(a) Third Party Claims.
If Contributor has knowledge that a license under a third party's
intellectual property rights is required to exercise the rights
granted by such Contributor under Sections 2.1 or 2.2,
Contributor must include a text file with the Source Code
distribution titled "LEGAL" which describes the claim and the
party making the claim in sufficient detail that a recipient will
know whom to contact. If Contributor obtains such knowledge after
the Modification is made available as described in Section 3.2,
Contributor shall promptly modify the LEGAL file in all copies
Contributor makes available thereafter and shall take other steps
(such as notifying appropriate mailing lists or newsgroups)
reasonably calculated to inform those who received the Covered
Code that new knowledge has been obtained.
(b) Contributor APIs.
If Contributor's Modifications include an application programming
interface and Contributor has knowledge of patent licenses which
are reasonably necessary to implement that API, Contributor must
also include this information in the LEGAL file.
(c) Representations.
Contributor represents that, except as disclosed pursuant to
Section 3.4(a) above, Contributor believes that Contributor's
Modifications are Contributor's original creation(s) and/or
Contributor has sufficient rights to grant the rights conveyed by
this License.
3.5. Required Notices.
You must duplicate the notice in Exhibit A in each file of the Source
Code. If it is not possible to put such notice in a particular Source
Code file due to its structure, then You must include such notice in a
location (such as a relevant directory) where a user would be likely
to look for such a notice. If You created one or more Modification(s)
You may add your name as a Contributor to the notice described in
Exhibit A. You must also duplicate this License in any documentation
for the Source Code where You describe recipients' rights or ownership
rights relating to Covered Code. You may choose to offer, and to
charge a fee for, warranty, support, indemnity or liability
obligations to one or more recipients of Covered Code. However, You
may do so only on Your own behalf, and not on behalf of the Initial
Developer or any Contributor. You must make it absolutely clear than
any such warranty, support, indemnity or liability obligation is
offered by You alone, and You hereby agree to indemnify the Initial
Developer and every Contributor for any liability incurred by the
Initial Developer or such Contributor as a result of warranty,
support, indemnity or liability terms You offer.
3.6. Distribution of Executable Versions.
You may distribute Covered Code in Executable form only if the
requirements of Section 3.1-3.5 have been met for that Covered Code,
and if You include a notice stating that the Source Code version of
the Covered Code is available under the terms of this License,
including a description of how and where You have fulfilled the
obligations of Section 3.2. The notice must be conspicuously included
in any notice in an Executable version, related documentation or
collateral in which You describe recipients' rights relating to the
Covered Code. You may distribute the Executable version of Covered
Code or ownership rights under a license of Your choice, which may
contain terms different from this License, provided that You are in
compliance with the terms of this License and that the license for the
Executable version does not attempt to limit or alter the recipient's
rights in the Source Code version from the rights set forth in this
License. If You distribute the Executable version under a different
license You must make it absolutely clear that any terms which differ
from this License are offered by You alone, not by the Initial
Developer or any Contributor. You hereby agree to indemnify the
Initial Developer and every Contributor for any liability incurred by
the Initial Developer or such Contributor as a result of any such
terms You offer.
3.7. Larger Works.
You may create a Larger Work by combining Covered Code with other code
not governed by the terms of this License and distribute the Larger
Work as a single product. In such a case, You must make sure the
requirements of this License are fulfilled for the Covered Code.
4. Inability to Comply Due to Statute or Regulation.
If it is impossible for You to comply with any of the terms of this
License with respect to some or all of the Covered Code due to
statute, judicial order, or regulation then You must: (a) comply with
the terms of this License to the maximum extent possible; and (b)
describe the limitations and the code they affect. Such description
must be included in the LEGAL file described in Section 3.4 and must
be included with all distributions of the Source Code. Except to the
extent prohibited by statute or regulation, such description must be
sufficiently detailed for a recipient of ordinary skill to be able to
understand it.
5. Application of this License.
This License applies to code to which the Initial Developer has
attached the notice in Exhibit A and to related Covered Code.
6. Versions of the License.
6.1. New Versions.
Netscape Communications Corporation ("Netscape") may publish revised
and/or new versions of the License from time to time. Each version
will be given a distinguishing version number.
6.2. Effect of New Versions.
Once Covered Code has been published under a particular version of the
License, You may always continue to use it under the terms of that
version. You may also choose to use such Covered Code under the terms
of any subsequent version of the License published by Netscape. No one
other than Netscape has the right to modify the terms applicable to
Covered Code created under this License.
6.3. Derivative Works.
If You create or use a modified version of this License (which you may
only do in order to apply it to code which is not already Covered Code
governed by this License), You must (a) rename Your license so that
the phrases "Mozilla", "MOZILLAPL", "MOZPL", "Netscape",
"MPL", "NPL" or any confusingly similar phrase do not appear in your
license (except to note that your license differs from this License)
and (b) otherwise make it clear that Your version of the license
contains terms which differ from the Mozilla Public License and
Netscape Public License. (Filling in the name of the Initial
Developer, Original Code or Contributor in the notice described in
Exhibit A shall not of themselves be deemed to be modifications of
this License.)
7. DISCLAIMER OF WARRANTY.
COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
WITHOUT LIMITATION, WARRANTIES THAT THE COVERED CODE IS FREE OF
DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING.
THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED CODE
IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT,
YOU (NOT THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE
COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER
OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF
ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER.
8. TERMINATION.
8.1. This License and the rights granted hereunder will terminate
automatically if You fail to comply with terms herein and fail to cure
such breach within 30 days of becoming aware of the breach. All
sublicenses to the Covered Code which are properly granted shall
survive any termination of this License. Provisions which, by their
nature, must remain in effect beyond the termination of this License
shall survive.
8.2. If You initiate litigation by asserting a patent infringement
claim (excluding declatory judgment actions) against Initial Developer
or a Contributor (the Initial Developer or Contributor against whom
You file such action is referred to as "Participant") alleging that:
(a) such Participant's Contributor Version directly or indirectly
infringes any patent, then any and all rights granted by such
Participant to You under Sections 2.1 and/or 2.2 of this License
shall, upon 60 days notice from Participant terminate prospectively,
unless if within 60 days after receipt of notice You either: (i)
agree in writing to pay Participant a mutually agreeable reasonable
royalty for Your past and future use of Modifications made by such
Participant, or (ii) withdraw Your litigation claim with respect to
the Contributor Version against such Participant. If within 60 days
of notice, a reasonable royalty and payment arrangement are not
mutually agreed upon in writing by the parties or the litigation claim
is not withdrawn, the rights granted by Participant to You under
Sections 2.1 and/or 2.2 automatically terminate at the expiration of
the 60 day notice period specified above.
(b) any software, hardware, or device, other than such Participant's
Contributor Version, directly or indirectly infringes any patent, then
any rights granted to You by such Participant under Sections 2.1(b)
and 2.2(b) are revoked effective as of the date You first made, used,
sold, distributed, or had made, Modifications made by that
Participant.
8.3. If You assert a patent infringement claim against Participant
alleging that such Participant's Contributor Version directly or
indirectly infringes any patent where such claim is resolved (such as
by license or settlement) prior to the initiation of patent
infringement litigation, then the reasonable value of the licenses
granted by such Participant under Sections 2.1 or 2.2 shall be taken
into account in determining the amount or value of any payment or
license.
8.4. In the event of termination under Sections 8.1 or 8.2 above,
all end user license agreements (excluding distributors and resellers)
which have been validly granted by You or any distributor hereunder
prior to termination shall survive termination.
9. LIMITATION OF LIABILITY.
UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT
(INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL YOU, THE INITIAL
DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF COVERED CODE,
OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO ANY PERSON FOR
ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY
CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL,
WORK STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER
COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN
INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF
LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY
RESULTING FROM SUCH PARTY'S NEGLIGENCE TO THE EXTENT APPLICABLE LAW
PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE
EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO
THIS EXCLUSION AND LIMITATION MAY NOT APPLY TO YOU.
10. U.S. GOVERNMENT END USERS.
The Covered Code is a "commercial item," as that term is defined in
48 C.F.R. 2.101 (Oct. 1995), consisting of "commercial computer
software" and "commercial computer software documentation," as such
terms are used in 48 C.F.R. 12.212 (Sept. 1995). Consistent with 48
C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995),
all U.S. Government End Users acquire Covered Code with only those
rights set forth herein.
11. MISCELLANEOUS.
This License represents the complete agreement concerning subject
matter hereof. If any provision of this License is held to be
unenforceable, such provision shall be reformed only to the extent
necessary to make it enforceable. This License shall be governed by
California law provisions (except to the extent applicable law, if
any, provides otherwise), excluding its conflict-of-law provisions.
With respect to disputes in which at least one party is a citizen of,
or an entity chartered or registered to do business in the United
States of America, any litigation relating to this License shall be
subject to the jurisdiction of the Federal Courts of the Northern
District of California, with venue lying in Santa Clara County,
California, with the losing party responsible for costs, including
without limitation, court costs and reasonable attorneys' fees and
expenses. The application of the United Nations Convention on
Contracts for the International Sale of Goods is expressly excluded.
Any law or regulation which provides that the language of a contract
shall be construed against the drafter shall not apply to this
License.
12. RESPONSIBILITY FOR CLAIMS.
As between Initial Developer and the Contributors, each party is
responsible for claims and damages arising, directly or indirectly,
out of its utilization of rights under this License and You agree to
work with Initial Developer and Contributors to distribute such
responsibility on an equitable basis. Nothing herein is intended or
shall be deemed to constitute any admission of liability.
13. MULTIPLE-LICENSED CODE.
Initial Developer may designate portions of the Covered Code as
"Multiple-Licensed". "Multiple-Licensed" means that the Initial
Developer permits you to utilize portions of the Covered Code under
Your choice of the NPL or the alternative licenses, if any, specified
by the Initial Developer in the file described in Exhibit A.
EXHIBIT A -Mozilla Public License.
``The contents of this file are subject to the Mozilla Public License
Version 1.1 (the "License"); you may not use this file except in
compliance with the License. You may obtain a copy of the License at
http://www.mozilla.org/MPL/
Software distributed under the License is distributed on an "AS IS"
basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
License for the specific language governing rights and limitations
under the License.
The Original Code is ______________________________________.
The Initial Developer of the Original Code is ________________________.
Portions created by ______________________ are Copyright (C) ______
_______________________. All Rights Reserved.
Contributor(s): ______________________________________.
Alternatively, the contents of this file may be used under the terms
of the _____ license (the "[___] License"), in which case the
provisions of [______] License are applicable instead of those
above. If you wish to allow use of your version of this file only
under the terms of the [____] License and not to allow others to use
your version of this file under the MPL, indicate your decision by
deleting the provisions above and replace them with the notice and
other provisions required by the [___] License. If you do not delete
the provisions above, a recipient may use your version of this file
under either the MPL or the [___] License."
[NOTE: The text of this Exhibit A may differ slightly from the text of
the notices in the Source Code files of the Original Code. You should
use the text of this Exhibit A rather than the text found in the
Original Code Source Code for Your Modifications.]

97
lib/psimpl/README.txt Normal file
View File

@ -0,0 +1,97 @@
psimpl - generic n-dimensional polyline simplification
Copyright (C) 2010-2011 Elmar de Koning, edekoning@gmail.com
--------------------------------------------------------------------------------
28-09-2010 - Initial version
23-10-2010 - Changed license from CPOL to MPL
26-10-2010 - Clarified input (type) requirements, and changed the
behavior of the algorithms under invalid input.
01-12-2010 - Added the nth point, perpendicular distance and Reumann-Witkam
routines; moved all functions related to distance calculations to
the math namespace
10-12-2010 - Fixed a bug in the perpendicular distance routine
27-02-2011 - Added Opheim simplification, and functions for computing positional
errors due to simplification; renamed simplify_douglas_peucker_alt
to simplify_douglas_peucker_n
18-06-2011 Added Lang simplification; fixed divide by zero bug when using
integers; fixed a bug where incorrect output iterators were
returned under invalid input; fixed a bug in douglas_peucker_n
where an incorrect number of points could be returned; fixed a bug
in compute_positional_errors2 that required the output and input
iterator types to be the same; fixed a bug in
compute_positional_error_statistics where invalid statistics could
be returned under questionable input; documented input iterator
requirements for each algorithm; miscellaneous refactoring of most
algorithms.
--------------------------------------------------------------------------------
'psimpl' is licensed under the Mozilla Public License Version 1.1 (MPL), see
the accompanying LICENSE.txt file. Alternatively a copy of this license may be
obtained from http://www.mozilla.org/MPL/.
--------------------------------------------------------------------------------
'psimpl' is hosted at SourceForge: http://sourceforge.net/projects/psimpl/ and
has a dedicated website: http://psimpl.sf.net
Originally psimpl was released as part of the article 'Polyline Simplification'
at The Code Project:
http://www.codeproject.com/KB/recipes/PolylineSimplification.aspx
================================================================================
'psimpl' is a c++ polyline simplification library that is generic, easy to use,
and supports the following algorithms:
Simplification
* Nth point - A naive algorithm that keeps only each nth point
* Distance between points - Removes successive points that are clustered
together
* Perpendicular distance - Removes points based on their distance to the line
segment defined by their left and right neighbors
* Reumann-Witkam - Shifts a strip along the polyline and removes points that
fall outside
* Opheim - A constrained version of Reumann-Witkam
* Lang - Similar to the Perpendicular distance routine, but instead of looking
only at direct neighbors, an entire search region is processed
* Douglas-Peucker - A classic simplification algorithm that provides an
excellent approximation of the original line
* A variation on the Douglas-Peucker algorithm - Slower, but yields better
results at lower resolutions
Errors
* positional error - Distance of each polyline point to its simplification
All the algorithms have been implemented in a single standalone C++ header
using an STL-style interface that operates on input and output iterators.
Polylines can be of any dimension, and defined using floating point or signed
integer data types.
================================================================================
The demo package contains a win32 demo application for 'psimpl'. The demo
application allows you to experiment with the different simplification
algorithms. It can generate pseudo random 2D-polylines of up to 10.000.000
vertices in various types of containers. The boundingbox of the generated
polyline is always 2n x n, where n is the amount of vertices of the generated
polyline. Use this fact to specify a proper distance tolerance.
Internally, the generated and simplified polyline are always stored in a
QVector<double>. Just before simplification, it is converted to the selected
container type. Afterwards, this temporary container is destructed. Normally you
won't notice this, but it seems that creating and destructing a
std::list(10.000.000) can take a rather long time. The resulting performance
measurements never include these conversion steps. I chose this approach as it
allowed me to quickly add new container types.
Note that the entire application is single threaded (sorry for being lazy),
meaning it could go 'not responding' during a long running simplification.
The demo application was made using Qt 4.7.3, Qt Creator 2.1.0 and Visual Studio
2008 Express. Complete source code is included.
================================================================================
If you decide to use my code for your (commercial) project, let me know! I would
love to hear where my code ends up and why you chose to use it! If possible, a
voluntary donation to my PayPal account (edekoning@gmail.com) would be much
appreciated.
Regards,
Elmar de Koning
edekoning@gmail.com

View File

@ -0,0 +1,782 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is
* 'psimpl - generic n-dimensional polyline simplification'.
*
* The Initial Developer of the Original Code is
* Elmar de Koning.
* Portions created by the Initial Developer are Copyright (C) 2010-2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* ***** END LICENSE BLOCK ***** */
/*
psimpl - generic n-dimensional polyline simplification
Copyright (C) 2010-2011 Elmar de Koning, edekoning@gmail.com
This file is part of psimpl, and is hosted at SourceForge:
http://sourceforge.net/projects/psimpl/
*/
#include "DPWorker.h"
#include "psimpl_reference.h"
#include "../lib/psimpl.h"
#include <cmath>
#include <QtCore/QTime>
namespace psimpl {
DPWorker::DPWorker (QObject* inParent) :
QObject (inParent)
{
// note: disable this line during testing
srand ((unsigned)QTime::currentTime ().msec ());
}
void DPWorker::Generate (int inCount) {
emit SignalGeneratingPolyline ();
QTime t;
t.start ();
mGeneratedCoords.resize (inCount*2);
mSimplifiedCoords.clear ();
qreal miny = inCount;
qreal maxy = -inCount;
const qreal PI = std::atan (1.0) * 4;
qreal step = 2 * PI / inCount;
int a = 1 + (rand () % 2); // [1, 3]
int b = 2 + (rand () % 3); // [2, 5]
int c = 3 + (rand () % 7); // [3, 10]
// generate a random line
for (int i=0; i<inCount; i++) {
mGeneratedCoords [i*2] = i;
qreal tmp1 = cos (step * i * a) / 3;
qreal tmp2 = sin (step * i * b) / 5;
qreal tmp3 = sin (step * i * c) / 10;
mGeneratedCoords [i*2+1] = tmp1 + tmp2 + tmp3;
miny = qMin (miny, mGeneratedCoords [i*2+1]);
maxy = qMax (maxy, mGeneratedCoords [i*2+1]);
}
// translate the line to (0,0) and scale the line to (2 * inCount, inCount)
qreal scaley = (inCount-1) / (maxy-miny);
for (int i=0; i<inCount; i++) {
mGeneratedCoords [i*2+1] = (mGeneratedCoords [i*2+1] - miny) * 0.5 * scaley;
}
//mGeneratedCoords.push_back(0);
emit SignalGeneratedPolyline (t.elapsed (), mGeneratedCoords);
}
void DPWorker::SimplifyNP (Container cont, int n) {
QTime t;
int duration = 0;
mSimplifiedCoords.clear ();
switch (cont) {
case ARRAY_FLOAT:
{
// convert
emit SignalConvertingPolyline ();
float* generatedPoints = new float [mGeneratedCoords.size ()];
for (int c=0; c<mGeneratedCoords.size (); c++) {
generatedPoints [c] = mGeneratedCoords [c];
}
// simplify
emit SignalSimplifyingPolyline ();
const float* begin = generatedPoints;
const float* end = generatedPoints + mGeneratedCoords.size ();
t.start ();
simplify_nth_point <2> (begin, end, n,
std::back_inserter (mSimplifiedCoords));
duration = t.elapsed ();
// done
emit SignalCleaningConvertedPolyline ();
delete [] generatedPoints;
break;
}
case QVECTOR_DOUBLE:
{
// simplify
emit SignalSimplifyingPolyline ();
QVector <qreal>::const_iterator begin = mGeneratedCoords.constBegin ();
QVector <qreal>::const_iterator end = mGeneratedCoords.constEnd ();
t.start ();
simplify_nth_point <2> (begin, end, n,
std::back_inserter (mSimplifiedCoords));
duration = t.elapsed ();
break;
}
case VECTOR_DOUBLE:
{
// convert
emit SignalConvertingPolyline ();
std::vector <double> generatedPoints = mGeneratedCoords.toStdVector ();
// simplify
emit SignalSimplifyingPolyline ();
std::vector <double>::const_iterator begin = generatedPoints.begin ();
std::vector <double>::const_iterator end = generatedPoints.end ();
t.start ();
simplify_nth_point <2> (begin, end, n,
std::back_inserter (mSimplifiedCoords));
duration = t.elapsed ();
emit SignalCleaningConvertedPolyline ();
break;
}
case LIST_LONGLONG:
{
// convert
emit SignalConvertingPolyline ();
std::list <long long> generatedPoints;
foreach (double coord, mGeneratedCoords) {
generatedPoints.push_back (coord);
}
// simplify
emit SignalSimplifyingPolyline ();
std::list <long long>::const_iterator begin = generatedPoints.begin ();
std::list <long long>::const_iterator end = generatedPoints.end ();
t.start ();
simplify_nth_point <2> (begin, end, n,
std::back_inserter (mSimplifiedCoords));
duration = t.elapsed ();
emit SignalCleaningConvertedPolyline ();
break;
}
default:
break;
}
DoSignalSimplifiedPolyline (duration);
}
void DPWorker::SimplifyRD (Container cont, QString tol) {
QTime t;
int duration = 0;
mSimplifiedCoords.clear ();
switch (cont) {
case ARRAY_FLOAT:
{
// convert
emit SignalConvertingPolyline ();
float* generatedPoints = new float [mGeneratedCoords.size ()];
for (int c=0; c<mGeneratedCoords.size (); c++) {
generatedPoints [c] = mGeneratedCoords [c];
}
// simplify
emit SignalSimplifyingPolyline ();
const float* begin = generatedPoints;
const float* end = generatedPoints + mGeneratedCoords.size ();
t.start ();
simplify_radial_distance <2> (begin, end, tol.toFloat(),
std::back_inserter (mSimplifiedCoords));
duration = t.elapsed ();
// done
emit SignalCleaningConvertedPolyline ();
delete [] generatedPoints;
break;
}
case QVECTOR_DOUBLE:
{
// simplify
emit SignalSimplifyingPolyline ();
QVector <qreal>::const_iterator begin = mGeneratedCoords.constBegin ();
QVector <qreal>::const_iterator end = mGeneratedCoords.constEnd ();
t.start ();
simplify_radial_distance <2> (begin, end, tol.toDouble (),
std::back_inserter (mSimplifiedCoords));
duration = t.elapsed ();
break;
}
case VECTOR_DOUBLE:
{
// convert
emit SignalConvertingPolyline ();
std::vector <double> generatedPoints = mGeneratedCoords.toStdVector ();
// simplify
emit SignalSimplifyingPolyline ();
std::vector <double>::const_iterator begin = generatedPoints.begin ();
std::vector <double>::const_iterator end = generatedPoints.end ();
t.start ();
simplify_radial_distance <2> (begin, end, tol.toDouble (),
std::back_inserter (mSimplifiedCoords));
duration = t.elapsed ();
emit SignalCleaningConvertedPolyline ();
break;
}
case LIST_LONGLONG:
{
// convert
emit SignalConvertingPolyline ();
std::list <long long> generatedPoints;
foreach (double coord, mGeneratedCoords) {
generatedPoints.push_back (coord);
}
// simplify
emit SignalSimplifyingPolyline ();
std::list <long long>::const_iterator begin = generatedPoints.begin ();
std::list <long long>::const_iterator end = generatedPoints.end ();
t.start ();
simplify_radial_distance <2> (begin, end, tol.toLongLong (),
std::back_inserter (mSimplifiedCoords));
duration = t.elapsed ();
emit SignalCleaningConvertedPolyline ();
break;
}
default:
break;
}
DoSignalSimplifiedPolyline (duration);
}
void DPWorker::SimplifyPD (Container cont, QString tol, int repeat) {
QTime t;
int duration = 0;
mSimplifiedCoords.clear ();
switch (cont) {
case ARRAY_FLOAT:
{
// convert
emit SignalConvertingPolyline ();
float* generatedPoints = new float [mGeneratedCoords.size ()];
for (int c=0; c<mGeneratedCoords.size (); c++) {
generatedPoints [c] = mGeneratedCoords [c];
}
// simplify
emit SignalSimplifyingPolyline ();
const float* begin = generatedPoints;
const float* end = generatedPoints + mGeneratedCoords.size ();
t.start ();
simplify_perpendicular_distance <2> (begin, end, tol.toFloat(), repeat,
std::back_inserter (mSimplifiedCoords));
duration = t.elapsed ();
// done
emit SignalCleaningConvertedPolyline ();
delete [] generatedPoints;
break;
}
case QVECTOR_DOUBLE:
{
// simplify
emit SignalSimplifyingPolyline ();
QVector <qreal>::const_iterator begin = mGeneratedCoords.constBegin ();
QVector <qreal>::const_iterator end = mGeneratedCoords.constEnd ();
t.start ();
simplify_perpendicular_distance <2> (begin, end, tol.toDouble (), repeat,
std::back_inserter (mSimplifiedCoords));
duration = t.elapsed ();
break;
}
case VECTOR_DOUBLE:
{
// convert
emit SignalConvertingPolyline ();
std::vector <double> generatedPoints = mGeneratedCoords.toStdVector ();
// simplify
emit SignalSimplifyingPolyline ();
std::vector <double>::const_iterator begin = generatedPoints.begin ();
std::vector <double>::const_iterator end = generatedPoints.end ();
t.start ();
simplify_perpendicular_distance <2> (begin, end, tol.toDouble (), repeat,
std::back_inserter (mSimplifiedCoords));
duration = t.elapsed ();
emit SignalCleaningConvertedPolyline ();
break;
}
case LIST_LONGLONG:
{
// convert
emit SignalConvertingPolyline ();
std::list <long long> generatedPoints;
foreach (double coord, mGeneratedCoords) {
generatedPoints.push_back (coord);
}
// simplify
emit SignalSimplifyingPolyline ();
std::list <long long>::const_iterator begin = generatedPoints.begin ();
std::list <long long>::const_iterator end = generatedPoints.end ();
t.start ();
simplify_perpendicular_distance <2> (begin, end, tol.toLongLong (), repeat,
std::back_inserter (mSimplifiedCoords));
duration = t.elapsed ();
emit SignalCleaningConvertedPolyline ();
break;
}
default:
break;
}
DoSignalSimplifiedPolyline (duration);
}
void DPWorker::SimplifyRW (Container cont, QString tol)
{
QTime t;
int duration = 0;
mSimplifiedCoords.clear ();
switch (cont) {
case ARRAY_FLOAT:
{
// convert
emit SignalConvertingPolyline ();
float* generatedPoints = new float [mGeneratedCoords.size ()];
for (int c=0; c<mGeneratedCoords.size (); c++) {
generatedPoints [c] = mGeneratedCoords [c];
}
// simplify
emit SignalSimplifyingPolyline ();
const float* begin = generatedPoints;
const float* end = generatedPoints + mGeneratedCoords.size ();
t.start ();
simplify_reumann_witkam <2> (begin, end, tol.toFloat(),
std::back_inserter (mSimplifiedCoords));
duration = t.elapsed ();
// done
emit SignalCleaningConvertedPolyline ();
delete [] generatedPoints;
break;
}
case QVECTOR_DOUBLE:
{
// simplify
emit SignalSimplifyingPolyline ();
QVector <qreal>::const_iterator begin = mGeneratedCoords.constBegin ();
QVector <qreal>::const_iterator end = mGeneratedCoords.constEnd ();
t.start ();
simplify_reumann_witkam <2> (begin, end, tol.toDouble (),
std::back_inserter (mSimplifiedCoords));
duration = t.elapsed ();
break;
}
case VECTOR_DOUBLE:
{
// convert
emit SignalConvertingPolyline ();
std::vector <double> generatedPoints = mGeneratedCoords.toStdVector ();
// simplify
emit SignalSimplifyingPolyline ();
std::vector <double>::const_iterator begin = generatedPoints.begin ();
std::vector <double>::const_iterator end = generatedPoints.end ();
t.start ();
simplify_reumann_witkam <2> (begin, end, tol.toDouble (),
std::back_inserter (mSimplifiedCoords));
duration = t.elapsed ();
emit SignalCleaningConvertedPolyline ();
break;
}
case LIST_LONGLONG:
{
// convert
emit SignalConvertingPolyline ();
std::list <long long> generatedPoints;
foreach (double coord, mGeneratedCoords) {
generatedPoints.push_back (coord);
}
// simplify
emit SignalSimplifyingPolyline ();
std::list <long long>::const_iterator begin = generatedPoints.begin ();
std::list <long long>::const_iterator end = generatedPoints.end ();
t.start ();
simplify_reumann_witkam <2> (begin, end, tol.toLongLong (),
std::back_inserter (mSimplifiedCoords));
duration = t.elapsed ();
emit SignalCleaningConvertedPolyline ();
break;
}
default:
break;
}
DoSignalSimplifiedPolyline (duration);
}
void DPWorker::SimplifyOp (Container cont, QString minTol, QString maxTol) {
QTime t;
int duration = 0;
mSimplifiedCoords.clear ();
switch (cont) {
case ARRAY_FLOAT:
{
// convert
emit SignalConvertingPolyline ();
float* generatedPoints = new float [mGeneratedCoords.size ()];
for (int c=0; c<mGeneratedCoords.size (); c++) {
generatedPoints [c] = mGeneratedCoords [c];
}
// simplify
emit SignalSimplifyingPolyline ();
const float* begin = generatedPoints;
const float* end = generatedPoints + mGeneratedCoords.size ();
t.start ();
simplify_opheim <2> (begin, end, minTol.toFloat(), maxTol.toFloat(),
std::back_inserter (mSimplifiedCoords));
duration = t.elapsed ();
// done
emit SignalCleaningConvertedPolyline ();
delete [] generatedPoints;
break;
}
case QVECTOR_DOUBLE:
{
// simplify
emit SignalSimplifyingPolyline ();
QVector <qreal>::const_iterator begin = mGeneratedCoords.constBegin ();
QVector <qreal>::const_iterator end = mGeneratedCoords.constEnd ();
t.start ();
simplify_opheim <2> (begin, end, minTol.toDouble(), maxTol.toDouble(),
std::back_inserter (mSimplifiedCoords));
duration = t.elapsed ();
break;
}
case VECTOR_DOUBLE:
{
// convert
emit SignalConvertingPolyline ();
std::vector <double> generatedPoints = mGeneratedCoords.toStdVector ();
// simplify
emit SignalSimplifyingPolyline ();
std::vector <double>::const_iterator begin = generatedPoints.begin ();
std::vector <double>::const_iterator end = generatedPoints.end ();
t.start ();
simplify_opheim <2> (begin, end, minTol.toDouble(), maxTol.toDouble(),
std::back_inserter (mSimplifiedCoords));
duration = t.elapsed ();
emit SignalCleaningConvertedPolyline ();
break;
}
case LIST_LONGLONG:
{
// convert
emit SignalConvertingPolyline ();
std::list <long long> generatedPoints;
foreach (double coord, mGeneratedCoords) {
generatedPoints.push_back (coord);
}
// simplify
emit SignalSimplifyingPolyline ();
std::list <long long>::const_iterator begin = generatedPoints.begin ();
std::list <long long>::const_iterator end = generatedPoints.end ();
t.start ();
simplify_opheim <2> (begin, end, minTol.toLongLong(), maxTol.toLongLong(),
std::back_inserter (mSimplifiedCoords));
duration = t.elapsed ();
emit SignalCleaningConvertedPolyline ();
break;
}
default:
break;
}
DoSignalSimplifiedPolyline (duration);
}
void DPWorker::SimplifyLa (Container cont, QString tol, int size) {
QTime t;
int duration = 0;
mSimplifiedCoords.clear ();
switch (cont) {
case ARRAY_FLOAT:
{
// convert
emit SignalConvertingPolyline ();
float* generatedPoints = new float [mGeneratedCoords.size ()];
for (int c=0; c<mGeneratedCoords.size (); c++) {
generatedPoints [c] = mGeneratedCoords [c];
}
// simplify
emit SignalSimplifyingPolyline ();
const float* begin = generatedPoints;
const float* end = generatedPoints + mGeneratedCoords.size ();
t.start ();
simplify_lang <2> (begin, end, tol.toFloat(), size,
std::back_inserter (mSimplifiedCoords));
duration = t.elapsed ();
// done
emit SignalCleaningConvertedPolyline ();
delete [] generatedPoints;
break;
}
case QVECTOR_DOUBLE:
{
// simplify
emit SignalSimplifyingPolyline ();
QVector <qreal>::const_iterator begin = mGeneratedCoords.constBegin ();
QVector <qreal>::const_iterator end = mGeneratedCoords.constEnd ();
t.start ();
simplify_lang <2> (begin, end, tol.toDouble(), size,
std::back_inserter (mSimplifiedCoords));
duration = t.elapsed ();
break;
}
case VECTOR_DOUBLE:
{
// convert
emit SignalConvertingPolyline ();
std::vector <double> generatedPoints = mGeneratedCoords.toStdVector ();
// simplify
emit SignalSimplifyingPolyline ();
std::vector <double>::const_iterator begin = generatedPoints.begin ();
std::vector <double>::const_iterator end = generatedPoints.end ();
t.start ();
simplify_lang <2> (begin, end, tol.toDouble(), size,
std::back_inserter (mSimplifiedCoords));
duration = t.elapsed ();
emit SignalCleaningConvertedPolyline ();
break;
}
case LIST_LONGLONG:
{
// convert
emit SignalConvertingPolyline ();
std::list <long long> generatedPoints;
foreach (double coord, mGeneratedCoords) {
generatedPoints.push_back (coord);
}
// simplify
emit SignalSimplifyingPolyline ();
std::list <long long>::const_iterator begin = generatedPoints.begin ();
std::list <long long>::const_iterator end = generatedPoints.end ();
t.start ();
simplify_lang <2> (begin, end, tol.toLongLong(), size,
std::back_inserter (mSimplifiedCoords));
duration = t.elapsed ();
emit SignalCleaningConvertedPolyline ();
break;
}
default:
break;
}
DoSignalSimplifiedPolyline (duration);
}
void DPWorker::SimplifyDP (Container cont, QString tol) {
QTime t;
int duration = 0;
mSimplifiedCoords.clear ();
switch (cont) {
case ARRAY_FLOAT:
{
// convert
emit SignalConvertingPolyline ();
float* generatedPoints = new float [mGeneratedCoords.size ()];
for (int c=0; c<mGeneratedCoords.size (); c++) {
generatedPoints [c] = mGeneratedCoords [c];
}
// simplify
emit SignalSimplifyingPolyline ();
const float* begin = generatedPoints;
const float* end = generatedPoints + mGeneratedCoords.size ();
t.start ();
simplify_douglas_peucker <2> (begin, end, tol.toFloat(),
std::back_inserter (mSimplifiedCoords));
duration = t.elapsed ();
// done
emit SignalCleaningConvertedPolyline ();
delete [] generatedPoints;
break;
}
case QVECTOR_DOUBLE:
{
// simplify
emit SignalSimplifyingPolyline ();
QVector <qreal>::const_iterator begin = mGeneratedCoords.constBegin ();
QVector <qreal>::const_iterator end = mGeneratedCoords.constEnd ();
t.start ();
simplify_douglas_peucker <2> (begin, end, tol.toDouble (),
std::back_inserter (mSimplifiedCoords));
duration = t.elapsed ();
break;
}
case VECTOR_DOUBLE:
{
// convert
emit SignalConvertingPolyline ();
std::vector <double> generatedPoints = mGeneratedCoords.toStdVector ();
// simplify
emit SignalSimplifyingPolyline ();
std::vector <double>::const_iterator begin = generatedPoints.begin ();
std::vector <double>::const_iterator end = generatedPoints.end ();
t.start ();
simplify_douglas_peucker <2> (begin, end, tol.toDouble (),
std::back_inserter (mSimplifiedCoords));
duration = t.elapsed ();
emit SignalCleaningConvertedPolyline ();
break;
}
case LIST_LONGLONG:
{
// convert
emit SignalConvertingPolyline ();
std::list <long long> generatedPoints;
foreach (double coord, mGeneratedCoords) {
generatedPoints.push_back (coord);
}
// simplify
emit SignalSimplifyingPolyline ();
std::list <long long>::const_iterator begin = generatedPoints.begin ();
std::list <long long>::const_iterator end = generatedPoints.end ();
t.start ();
simplify_douglas_peucker <2> (begin, end, tol.toLongLong (),
std::back_inserter (mSimplifiedCoords));
duration = t.elapsed ();
emit SignalCleaningConvertedPolyline ();
break;
}
default:
break;
}
DoSignalSimplifiedPolyline (duration);
}
void DPWorker::SimplifyDP_variant (Container cont, int count) {
QTime t;
int duration = 0;
mSimplifiedCoords.clear ();
switch (cont) {
case ARRAY_FLOAT:
{
// convert
emit SignalConvertingPolyline ();
float* generatedPoints = new float [mGeneratedCoords.size ()];
for (int c=0; c<mGeneratedCoords.size (); c++) {
generatedPoints [c] = mGeneratedCoords [c];
}
// simplify
emit SignalSimplifyingPolyline ();
const float* begin = generatedPoints;
const float* end = generatedPoints + mGeneratedCoords.size ();
t.start ();
simplify_douglas_peucker_n <2> (begin, end, count,
std::back_inserter (mSimplifiedCoords));
duration = t.elapsed ();
// done
emit SignalCleaningConvertedPolyline ();
delete [] generatedPoints;
break;
}
case QVECTOR_DOUBLE:
{
// simplify
emit SignalSimplifyingPolyline ();
QVector <qreal>::const_iterator begin = mGeneratedCoords.constBegin ();
QVector <qreal>::const_iterator end = mGeneratedCoords.constEnd ();
t.start ();
simplify_douglas_peucker_n <2> (begin, end, count,
std::back_inserter (mSimplifiedCoords));
duration = t.elapsed ();
break;
}
case VECTOR_DOUBLE:
{
// convert
emit SignalConvertingPolyline ();
std::vector <double> generatedPoints = mGeneratedCoords.toStdVector ();
// simplify
emit SignalSimplifyingPolyline ();
std::vector <double>::const_iterator begin = generatedPoints.begin ();
std::vector <double>::const_iterator end = generatedPoints.end ();
t.start ();
simplify_douglas_peucker_n <2> (begin, end, count,
std::back_inserter (mSimplifiedCoords));
duration = t.elapsed ();
emit SignalCleaningConvertedPolyline ();
break;
}
case LIST_LONGLONG:
{
// convert
emit SignalConvertingPolyline ();
std::list <long long> generatedPoints;
foreach (double coord, mGeneratedCoords) {
generatedPoints.push_back (coord);
}
// simplify
emit SignalSimplifyingPolyline ();
std::list <long long>::const_iterator begin = generatedPoints.begin ();
std::list <long long>::const_iterator end = generatedPoints.end ();
t.start ();
simplify_douglas_peucker_n <2> (begin, end, count,
std::back_inserter (mSimplifiedCoords));
duration = t.elapsed ();
emit SignalCleaningConvertedPolyline ();
break;
}
default:
break;
}
DoSignalSimplifiedPolyline (duration);
}
void DPWorker::SimplifyDP_reference (QString tol) {
mSimplifiedCoords.clear();
// convert generated polyline to Point array
emit SignalConvertingPolyline ();
int pointCount = mGeneratedCoords.size () / 2;
classic::Point* generatedPoints = new classic::Point [pointCount];
classic::Point* simplifiedPoints = new classic::Point [pointCount];
for (int i=0; i<pointCount; i++) {
generatedPoints [i].x = mGeneratedCoords [i*2];
generatedPoints [i].y = mGeneratedCoords [i*2+1];
}
emit SignalSimplifyingPolyline ();
QTime t;
t.start ();
// simplify
int simplCount = classic::poly_simplify (tol.toFloat (), generatedPoints,
pointCount, simplifiedPoints);
int duration = t.elapsed ();
// convert simplified Point array to simplified polyline
mSimplifiedCoords.resize (simplCount * 2);
for (int i=0; i<simplCount; i++) {
mSimplifiedCoords [i*2] = simplifiedPoints [i].x;
mSimplifiedCoords [i*2+1] = simplifiedPoints [i].y;
}
// done
delete [] generatedPoints;
delete [] simplifiedPoints;
DoSignalSimplifiedPolyline (duration);
}
void DPWorker::DoSignalSimplifiedPolyline (qreal duration) {
bool validStatistics = false;
math::Statistics stats =
compute_positional_error_statistics <2> (
mGeneratedCoords.constBegin (), mGeneratedCoords.constEnd (),
mSimplifiedCoords.constBegin (), mSimplifiedCoords.constEnd (), &validStatistics);
if (validStatistics) {
emit SignalSimplifiedPolyline (duration, mSimplifiedCoords, stats.max, stats.sum, stats.mean, stats.std);
}
else {
emit SignalSimplifiedPolyline (duration, mSimplifiedCoords);
}
}
} // namespace psimpl

101
lib/psimpl/demo/DPWorker.h Normal file
View File

@ -0,0 +1,101 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is
* 'psimpl - generic n-dimensional polyline simplification'.
*
* The Initial Developer of the Original Code is
* Elmar de Koning.
* Portions created by the Initial Developer are Copyright (C) 2010-2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* ***** END LICENSE BLOCK ***** */
/*
psimpl - generic n-dimensional polyline simplification
Copyright (C) 2010-2011 Elmar de Koning, edekoning@gmail.com
This file is part of psimpl, and is hosted at SourceForge:
http://sourceforge.net/projects/psimpl/
*/
#ifndef DPWORKER_H
#define DPWORKER_H
#include <QtCore/QObject>
#include <QtCore/QVector>
namespace psimpl {
typedef enum CONTAINER
{
ARRAY_FLOAT,
QVECTOR_DOUBLE,
VECTOR_DOUBLE,
LIST_LONGLONG,
} Container;
/*!
\brief Worker class for generating and simplifying polylines.
Polylines are always generated in a QVector <qreal> container. Before simplification the
polyline is converted to the specified container type. This allows for easy adding of new
container types.
*/
class DPWorker : public QObject
{
Q_OBJECT
public:
DPWorker (QObject* inParent = 0);
void Generate (int inCount);
void SimplifyNP (Container cont, int n);
void SimplifyRD (Container cont, QString tol);
void SimplifyPD (Container cont, QString tol, int repeat);
void SimplifyRW (Container cont, QString tol);
void SimplifyOp (Container cont, QString minTol, QString maxTol);
void SimplifyLa (Container cont, QString tol, int size);
void SimplifyDP (Container cont, QString tol);
void SimplifyDP_variant (Container cont, int count);
void SimplifyDP_reference (QString tol);
int GetGeneratedPointCount () { return mGeneratedCoords.size () / 2; }
int GetSimplifiedGeneratedPointCount () { return mSimplifiedCoords.size () / 2; }
private:
void DoSignalSimplifiedPolyline (qreal duration);
signals:
void SignalGeneratingPolyline ();
void SignalConvertingPolyline ();
void SignalSimplifyingPolyline ();
void SignalCleaningConvertedPolyline ();
void SignalGeneratedPolyline (int duration, QVector <qreal>& polyline);
void SignalSimplifiedPolyline (int duration, QVector <qreal>& polyline);
void SignalSimplifiedPolyline (int duration, QVector <qreal>& polyline, double max, double sum, double mean, double std);
private:
QVector <qreal> mGeneratedCoords;
QVector <qreal> mSimplifiedCoords;
};
} // namespace psimpl
#endif // DPWORKER_H

View File

@ -0,0 +1,256 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is
* 'psimpl - generic n-dimensional polyline simplification'.
*
* The Initial Developer of the Original Code is
* Elmar de Koning.
* Portions created by the Initial Developer are Copyright (C) 2010-2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* ***** END LICENSE BLOCK ***** */
/*
psimpl - generic n-dimensional polyline simplification
Copyright (C) 2010-2011 Elmar de Koning, edekoning@gmail.com
This file is part of psimpl, and is hosted at SourceForge:
http://sourceforge.net/projects/psimpl/
*/
#include "MainWindow.h"
#include "ui_MainWindow.h"
#include "DPWorker.h"
#include <cmath>
#include <QtGui/QToolButton>
namespace psimpl {
MainWindow::MainWindow (QWidget *parent) :
QMainWindow (parent),
ui (new Ui::MainWindow)
{
mWorker = new DPWorker (this);
ui->setupUi (this);
ui->polyTypeComboBox->setCurrentIndex(VECTOR_DOUBLE);
#ifndef _DEBUG
ui->algorithmComboBox->removeItem (DOUGLAS_PEUCKER_REFERENCE);
#endif
connect (mWorker, SIGNAL (SignalGeneratingPolyline ()),
this, SLOT (SlotGeneratingPolyline ()));
connect (mWorker, SIGNAL (SignalConvertingPolyline ()),
this, SLOT (SlotConvertingPolyline ()));
connect (mWorker, SIGNAL (SignalSimplifyingPolyline ()),
this, SLOT (SlotSimplifyingPolyline ()));
connect (mWorker, SIGNAL (SignalCleaningConvertedPolyline ()),
this, SLOT (SlotCleaningConvertedPolyline ()));
connect (mWorker, SIGNAL (SignalGeneratedPolyline (int, QVector <qreal>&)),
this, SLOT (SlotGeneratedPolyline (int, QVector <qreal>&)));
connect (mWorker, SIGNAL (SignalSimplifiedPolyline (int, QVector <qreal>&)),
this, SLOT (SlotSimplifiedPolyline (int, QVector <qreal>&)));
connect (mWorker, SIGNAL (SignalSimplifiedPolyline (int, QVector <qreal>&, double, double, double, double)),
this, SLOT (SlotSimplifiedPolyline (int, QVector <qreal>&, double, double, double, double)));
}
MainWindow::~MainWindow ()
{
delete ui;
delete mWorker;
}
void MainWindow::changeEvent (QEvent *e)
{
QMainWindow::changeEvent (e);
switch (e->type ()) {
case QEvent::LanguageChange:
ui->retranslateUi (this);
break;
default:
break;
}
}
void MainWindow::EnableButtons ()
{
ui->generatePushButton->setEnabled (true);
ui->simplifyPushButton->setEnabled (true);
ui->togglePushButton->setEnabled(
ui->generatedPolylineCheckBox->isChecked () !=
ui->simplifiedPolylineCheckBox->isChecked ());
}
void MainWindow::DisableButtons ()
{
ui->generatePushButton->setDisabled (true);
ui->simplifyPushButton->setDisabled (true);
ui->togglePushButton->setDisabled (true);
}
void MainWindow::on_generatePushButton_clicked ()
{
QApplication::setOverrideCursor (QCursor (Qt::WaitCursor));
DisableButtons ();
mWorker->Generate (ui->polyPointCountSpinBox->value ());
}
void MainWindow::on_simplifyPushButton_clicked ()
{
QApplication::setOverrideCursor (QCursor (Qt::WaitCursor));
DisableButtons ();
switch (ui->algorithmComboBox->currentIndex ())
{
case NTH_POINT:
mWorker->SimplifyNP ((Container)ui->polyTypeComboBox->currentIndex (), ui->npSpinBox->value ());
break;
case RADIAL_DISTANCE:
mWorker->SimplifyRD ((Container)ui->polyTypeComboBox->currentIndex (), ui->rdLineEdit->text ());
break;
case PERPENDICULAR_DISTANCE:
mWorker->SimplifyPD ((Container)ui->polyTypeComboBox->currentIndex (), ui->pdLineEdit->text (), ui->pdSpinBox->value ());
break;
case REUMANN_WITKAM:
mWorker->SimplifyRW ((Container)ui->polyTypeComboBox->currentIndex (), ui->rwLineEdit->text ());
break;
case OPHEIM:
mWorker->SimplifyOp ((Container)ui->polyTypeComboBox->currentIndex (), ui->minOpLineEdit->text (), ui->maxOpLineEdit->text ());
break;
case LANG:
mWorker->SimplifyLa ((Container)ui->polyTypeComboBox->currentIndex (), ui->laLineEdit->text (), ui->lookAheadLaSpinBox->value ());
break;
case DOUGLAS_PEUCKER:
mWorker->SimplifyDP ((Container)ui->polyTypeComboBox->currentIndex (), ui->dpLineEdit->text ());
break;
case DOUGLAS_PEUCKER_VARIANT:
mWorker->SimplifyDP_variant ((Container)ui->polyTypeComboBox->currentIndex (), ui->dpvSpinBox->value ());
break;
case DOUGLAS_PEUCKER_REFERENCE:
mWorker->SimplifyDP_reference (ui->dprLineEdit->text ());
break;
}
}
void MainWindow::on_algorithmComboBox_currentIndexChanged (int index)
{
if (index == DOUGLAS_PEUCKER_REFERENCE) {
ui->polyTypeComboBox->setCurrentIndex (ARRAY_FLOAT);
ui->polyTypeComboBox->setDisabled (true);
}
else {
ui->polyTypeComboBox->setEnabled (true);
}
}
void MainWindow::on_generatedPolylineCheckBox_toggled (bool checked)
{
ui->renderArea->SetVisibleGeneratedPolyline (checked);
ui->togglePushButton->setDisabled(
ui->generatedPolylineCheckBox->isChecked () ==
ui->simplifiedPolylineCheckBox->isChecked ());
update();
}
void MainWindow::on_simplifiedPolylineCheckBox_toggled (bool checked)
{
ui->renderArea->SetVisibleSimplifiedPolyline (checked);
ui->togglePushButton->setDisabled(
ui->generatedPolylineCheckBox->isChecked () ==
ui->simplifiedPolylineCheckBox->isChecked ());
update();
}
void MainWindow::on_keepAspectRatioCheckBox_toggled (bool checked)
{
ui->renderArea->SetKeepAspectRatio (checked);
update();
}
void MainWindow::SlotGeneratingPolyline () {
ui->statusBar->showMessage ("Generating polyline...");
}
void MainWindow::SlotConvertingPolyline () {
ui->statusBar->showMessage (QString ("Converting polyline to '%1'...").arg (ui->polyTypeComboBox->currentText ()));
}
void MainWindow::SlotSimplifyingPolyline () {
ui->statusBar->showMessage ("Simplifying polyline...");
}
void MainWindow::SlotCleaningConvertedPolyline () {
ui->statusBar->showMessage ("Deleting converted polyline...");
}
void MainWindow::SlotGeneratedPolyline (int duration, QVector <qreal>& polyline)
{
ui->statusBar->showMessage (QString ("Generation took %1 ms").arg (duration));
ui->renderArea->SetGeneratedPolyline (polyline);
ui->simplGroupBox->setEnabled (true);
EnableButtons ();
QApplication::restoreOverrideCursor ();
update();
}
void MainWindow::SlotSimplifiedPolyline (int duration, QVector <qreal>& polyline)
{
int pointCount = polyline.count () / 2;
ui->maxValueLabel->setText ("-");
ui->sumValueLabel->setText ("-");
ui->meanValueLabel->setText ("-");
ui->stdValueLabel->setText ("-");
ui->statusBar->showMessage (
QString ("Simplification took %1 ms; %2 (%3%) points remaining").
arg (duration).
arg (pointCount).
arg (100.0 * pointCount / mWorker->GetGeneratedPointCount()));
ui->renderArea->SetSimplifiedPolyline(polyline);
EnableButtons ();
QApplication::restoreOverrideCursor ();
update();
}
void MainWindow::SlotSimplifiedPolyline (int duration, QVector <qreal>& polyline, double max, double sum, double mean, double std)
{
int pointCount = polyline.count () / 2;
ui->maxValueLabel->setText (QString::number (max));
ui->sumValueLabel->setText (QString::number (sum));
ui->meanValueLabel->setText (QString::number (mean));
ui->stdValueLabel->setText (QString::number (std));
ui->statusBar->showMessage (
QString ("Simplification took %1 ms; %2 (%3%) points remaining").
arg (duration).
arg (pointCount).
arg (100.0 * pointCount / mWorker->GetGeneratedPointCount()));
ui->renderArea->SetSimplifiedPolyline(polyline);
EnableButtons ();
QApplication::restoreOverrideCursor ();
update();
}
} // namespace psimpl

View File

@ -0,0 +1,106 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is
* 'psimpl - generic n-dimensional polyline simplification'.
*
* The Initial Developer of the Original Code is
* Elmar de Koning.
* Portions created by the Initial Developer are Copyright (C) 2010-2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* ***** END LICENSE BLOCK ***** */
/*
psimpl - generic n-dimensional polyline simplification
Copyright (C) 2010-2011 Elmar de Koning, edekoning@gmail.com
This file is part of psimpl, and is hosted at SourceForge:
http://sourceforge.net/projects/psimpl/
*/
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QtGui/QMainWindow>
namespace Ui {
class MainWindow;
}
namespace psimpl {
class DPWorker;
typedef enum ALGORITHM
{
NTH_POINT,
RADIAL_DISTANCE,
PERPENDICULAR_DISTANCE,
REUMANN_WITKAM,
OPHEIM,
LANG,
DOUGLAS_PEUCKER,
DOUGLAS_PEUCKER_VARIANT,
DOUGLAS_PEUCKER_REFERENCE,
} Algorithm;
/*!
\brief Mainwindow where polylines can be generated and simplified.
Multiple simplification algorithms, implementations and container types can be experimented
with.
*/
class MainWindow : public QMainWindow {
Q_OBJECT
public:
MainWindow (QWidget *parent = 0);
~MainWindow ();
protected:
void changeEvent (QEvent *e);
private:
void EnableButtons ();
void DisableButtons ();
private:
Ui::MainWindow *ui;
DPWorker* mWorker;
private slots:
void on_simplifiedPolylineCheckBox_toggled(bool checked);
void on_generatedPolylineCheckBox_toggled(bool checked);
void on_keepAspectRatioCheckBox_toggled(bool checked);
void on_simplifyPushButton_clicked ();
void on_algorithmComboBox_currentIndexChanged(int index);
void on_generatePushButton_clicked ();
void SlotGeneratingPolyline ();
void SlotConvertingPolyline ();
void SlotSimplifyingPolyline ();
void SlotCleaningConvertedPolyline ();
void SlotGeneratedPolyline (int duration, QVector <qreal>& polyline);
void SlotSimplifiedPolyline (int duration, QVector <qreal>& polyline);
void SlotSimplifiedPolyline (int duration, QVector <qreal>& polyline, double max, double sum, double mean, double std);
};
} // namespace psimpl
#endif // MAINWINDOW_H

View File

@ -0,0 +1,855 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>600</height>
</rect>
</property>
<property name="windowTitle">
<string>psimpl v7 - generic n-dimensional polyline simplification</string>
</property>
<property name="locale">
<locale language="English" country="UnitedStates"/>
</property>
<widget class="QWidget" name="centralWidget">
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p align=&quot;center&quot; style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:10pt; font-weight:600;&quot;&gt;psimple v7&lt;/span&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; &lt;/span&gt;&lt;span style=&quot; font-size:8pt; color:#000000;&quot;&gt;© Copyright 2010 - 2011 &lt;/span&gt;&lt;a href=&quot;edekoning@gmail.com&quot;&gt;&lt;span style=&quot; font-size:8pt; text-decoration: underline; color:#0000ff;&quot;&gt;Elmar de Koning&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;; License - &lt;/span&gt;&lt;a href=&quot;http://www.opensource.org/licenses/mozilla1.1.php&quot;&gt;&lt;span style=&quot; font-size:8pt; text-decoration: underline; color:#0000ff;&quot;&gt;MPL 1.1&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;; Website - &lt;/span&gt;&lt;a href=&quot;http://psimpl.sf.net&quot;&gt;&lt;span style=&quot; font-size:8pt; text-decoration: underline; color:#0000ff;&quot;&gt;psimpl.sf.net&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;; Article - &lt;/span&gt;&lt;a href=&quot;http://www.codeproject.com/KB/recipes/PolylineSimplification.aspx&quot;&gt;&lt;span style=&quot; font-size:8pt; text-decoration: underline; color:#0000ff;&quot;&gt;CodeProject&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="openExternalLinks">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse</set>
</property>
</widget>
</item>
<item>
<widget class="psimpl::RenderArea" name="renderArea">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>3</verstretch>
</sizepolicy>
</property>
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QGroupBox" name="polyGroupBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>Polyline</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="1" column="0">
<widget class="QLabel" name="polyTypeLabel">
<property name="text">
<string>Type</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="polyTypeComboBox">
<item>
<property name="text">
<string>float []</string>
</property>
</item>
<item>
<property name="text">
<string>QVector &lt;double&gt;</string>
</property>
</item>
<item>
<property name="text">
<string>std::vector &lt;double&gt;</string>
</property>
</item>
<item>
<property name="text">
<string>std::list &lt;long long&gt;</string>
</property>
</item>
</widget>
</item>
<item row="4" column="1">
<widget class="QPushButton" name="generatePushButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Generate</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="polyPointCountLabel">
<property name="text">
<string>Point count</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QSpinBox" name="polyPointCountSpinBox">
<property name="minimum">
<number>2</number>
</property>
<property name="maximum">
<number>10000000</number>
</property>
<property name="singleStep">
<number>10000</number>
</property>
<property name="value">
<number>100000</number>
</property>
</widget>
</item>
<item row="2" column="1">
<spacer name="verticalSpacer_13">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="simplGroupBox">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>Simplification</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="1">
<widget class="QComboBox" name="algorithmComboBox">
<item>
<property name="text">
<string>Nth point</string>
</property>
</item>
<item>
<property name="text">
<string>Radial distance</string>
</property>
</item>
<item>
<property name="text">
<string>Perpendicular distance</string>
</property>
</item>
<item>
<property name="text">
<string>Reumann-Witkam</string>
</property>
</item>
<item>
<property name="text">
<string>Opheim</string>
</property>
</item>
<item>
<property name="text">
<string>Lang</string>
</property>
</item>
<item>
<property name="text">
<string>Douglas-Peucker</string>
</property>
</item>
<item>
<property name="text">
<string>Douglas-Peucker (variant)</string>
</property>
</item>
<item>
<property name="text">
<string>Douglas-Peucker (reference)</string>
</property>
</item>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="algorithmLabel">
<property name="text">
<string>Algorithm</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QPushButton" name="simplifyPushButton">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Simplify</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QStackedWidget" name="editStackedWidget">
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="npPage_2">
<layout class="QVBoxLayout" name="verticalLayout_16">
<property name="margin">
<number>0</number>
</property>
<item>
<widget class="QSpinBox" name="npSpinBox">
<property name="maximum">
<number>10000000</number>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="rdPage_2">
<layout class="QVBoxLayout" name="verticalLayout">
<property name="margin">
<number>0</number>
</property>
<item>
<widget class="QLineEdit" name="rdLineEdit">
<property name="text">
<string>0</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="pdPage_2">
<layout class="QVBoxLayout" name="verticalLayout_15">
<property name="margin">
<number>0</number>
</property>
<item>
<widget class="QLineEdit" name="pdLineEdit">
<property name="text">
<string>0</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="pdSpinBox">
<property name="maximum">
<number>1000000</number>
</property>
<property name="value">
<number>1</number>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="rwPage_2">
<layout class="QVBoxLayout" name="verticalLayout_6">
<property name="margin">
<number>0</number>
</property>
<item>
<widget class="QLineEdit" name="rwLineEdit">
<property name="inputMask">
<string/>
</property>
<property name="text">
<string>0</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="opPage_2">
<layout class="QVBoxLayout" name="verticalLayout_18">
<property name="margin">
<number>0</number>
</property>
<item>
<widget class="QLineEdit" name="minOpLineEdit">
<property name="text">
<string>0</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="maxOpLineEdit">
<property name="text">
<string>0</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="laPage_2">
<layout class="QVBoxLayout" name="verticalLayout_20">
<property name="margin">
<number>0</number>
</property>
<item>
<widget class="QLineEdit" name="laLineEdit">
<property name="text">
<string>0</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="lookAheadLaSpinBox">
<property name="maximum">
<number>10000000</number>
</property>
<property name="value">
<number>1</number>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="dpPage_2">
<layout class="QVBoxLayout" name="verticalLayout_8">
<property name="margin">
<number>0</number>
</property>
<item>
<widget class="QLineEdit" name="dpLineEdit">
<property name="text">
<string>0</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="dpvPage_2">
<layout class="QVBoxLayout" name="verticalLayout_7">
<property name="margin">
<number>0</number>
</property>
<item>
<widget class="QSpinBox" name="dpvSpinBox">
<property name="minimum">
<number>0</number>
</property>
<property name="maximum">
<number>10000000</number>
</property>
<property name="singleStep">
<number>10</number>
</property>
<property name="value">
<number>0</number>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="dprPage_2">
<layout class="QVBoxLayout" name="verticalLayout_12">
<property name="margin">
<number>0</number>
</property>
<item>
<widget class="QLineEdit" name="dprLineEdit">
<property name="text">
<string>0</string>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
<item row="1" column="0">
<widget class="QStackedWidget" name="labelStackedWidget">
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="npPage">
<layout class="QVBoxLayout" name="verticalLayout_14">
<property name="margin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="npLabel">
<property name="text">
<string>n</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="rdPage">
<layout class="QVBoxLayout" name="verticalLayout_4">
<property name="margin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="rdLabel">
<property name="text">
<string>Radial distance</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="pdPage">
<layout class="QVBoxLayout" name="verticalLayout_13">
<property name="margin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="pdLabel">
<property name="text">
<string>Perpendicular distance</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="repeatLabel">
<property name="text">
<string>Repeat count</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="rwPage">
<layout class="QVBoxLayout" name="verticalLayout_5">
<property name="margin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="rwLabel">
<property name="text">
<string>Perpendicular distance</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="opPage">
<layout class="QVBoxLayout" name="verticalLayout_17">
<property name="margin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="minOpLabel">
<property name="text">
<string>Minimum distance</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="maxOpLabel">
<property name="text">
<string>Maximum distance</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="laPage">
<layout class="QVBoxLayout" name="verticalLayout_19">
<property name="margin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="laLabel">
<property name="text">
<string>Perpendicular distance</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="lookAheadLaLabel">
<property name="text">
<string>Look ahead</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="dpPage">
<layout class="QVBoxLayout" name="verticalLayout_9">
<property name="margin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="dpLabel">
<property name="text">
<string>Perpendicular distance</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="dpvPage">
<layout class="QVBoxLayout" name="verticalLayout_10">
<property name="margin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="dpvLabel">
<property name="text">
<string>Point count</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="dprPage">
<layout class="QVBoxLayout" name="verticalLayout_11">
<property name="margin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="dprLabel">
<property name="text">
<string>Perpendicular distance</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="graphiscGroupBox">
<property name="title">
<string>Graphics</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QCheckBox" name="generatedPolylineCheckBox">
<property name="text">
<string>Generated Polyline</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="simplifiedPolylineCheckBox">
<property name="text">
<string>Simplified Polyline</string>
</property>
<property name="checked">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="togglePushButton">
<property name="text">
<string>Toggle</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="keepAspectRatioCheckBox">
<property name="text">
<string>Keep aspect ratio</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="positionalErrorGroupBox">
<property name="toolTip">
<string>Positional errors are only calculated for doubles!</string>
</property>
<property name="title">
<string>Positional error</string>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<item row="0" column="0">
<widget class="QLabel" name="sumLabel">
<property name="text">
<string>Sum</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="maxLabel">
<property name="text">
<string>Max</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="meanLabel">
<property name="text">
<string>Mean</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="stdLabel">
<property name="text">
<string>Std</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="sumValueLabel">
<property name="text">
<string>-</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="maxValueLabel">
<property name="text">
<string>-</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLabel" name="meanValueLabel">
<property name="text">
<string>-</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLabel" name="stdValueLabel">
<property name="text">
<string>-</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</widget>
<widget class="QStatusBar" name="statusBar"/>
<action name="aboutAction">
<property name="text">
<string>?</string>
</property>
<property name="toolTip">
<string>About psimpl</string>
</property>
<property name="shortcut">
<string>F1</string>
</property>
</action>
</widget>
<layoutdefault spacing="6" margin="11"/>
<customwidgets>
<customwidget>
<class>psimpl::RenderArea</class>
<extends>QFrame</extends>
<header>RenderArea.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<tabstops>
<tabstop>polyPointCountSpinBox</tabstop>
<tabstop>polyTypeComboBox</tabstop>
<tabstop>generatePushButton</tabstop>
<tabstop>algorithmComboBox</tabstop>
<tabstop>npSpinBox</tabstop>
<tabstop>rdLineEdit</tabstop>
<tabstop>pdLineEdit</tabstop>
<tabstop>pdSpinBox</tabstop>
<tabstop>rwLineEdit</tabstop>
<tabstop>dpLineEdit</tabstop>
<tabstop>dpvSpinBox</tabstop>
<tabstop>dprLineEdit</tabstop>
<tabstop>simplifyPushButton</tabstop>
<tabstop>generatedPolylineCheckBox</tabstop>
<tabstop>simplifiedPolylineCheckBox</tabstop>
</tabstops>
<resources/>
<connections>
<connection>
<sender>togglePushButton</sender>
<signal>clicked()</signal>
<receiver>generatedPolylineCheckBox</receiver>
<slot>toggle()</slot>
<hints>
<hint type="sourcelabel">
<x>674</x>
<y>559</y>
</hint>
<hint type="destinationlabel">
<x>674</x>
<y>504</y>
</hint>
</hints>
</connection>
<connection>
<sender>togglePushButton</sender>
<signal>clicked()</signal>
<receiver>simplifiedPolylineCheckBox</receiver>
<slot>toggle()</slot>
<hints>
<hint type="sourcelabel">
<x>674</x>
<y>559</y>
</hint>
<hint type="destinationlabel">
<x>674</x>
<y>529</y>
</hint>
</hints>
</connection>
<connection>
<sender>algorithmComboBox</sender>
<signal>currentIndexChanged(int)</signal>
<receiver>labelStackedWidget</receiver>
<slot>setCurrentIndex(int)</slot>
<hints>
<hint type="sourcelabel">
<x>256</x>
<y>503</y>
</hint>
<hint type="destinationlabel">
<x>210</x>
<y>519</y>
</hint>
</hints>
</connection>
<connection>
<sender>algorithmComboBox</sender>
<signal>currentIndexChanged(int)</signal>
<receiver>editStackedWidget</receiver>
<slot>setCurrentIndex(int)</slot>
<hints>
<hint type="sourcelabel">
<x>281</x>
<y>490</y>
</hint>
<hint type="destinationlabel">
<x>279</x>
<y>512</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -0,0 +1,41 @@
<?xml version="1.0" encoding="utf-8"?>
<VisualStudioToolFile
Name="QT rules"
Version="8.00"
>
<Rules>
<CustomBuildRule
Name="UIC"
DisplayName="UI compiler"
CommandLine="$(QTDIR)\bin\uic $(InputPath) -o $(InputDir)\ui_$(InputName).h"
Outputs="$(InputDir)\ui_$(InputName).h"
FileExtensions="*.ui"
ExecutionDescription="Uic&apos;ing $(InputFileName)"
>
<Properties>
</Properties>
</CustomBuildRule>
<CustomBuildRule
Name="MOC"
DisplayName="MOC compiler"
CommandLine="$(QTDIR)\bin\moc $(InputPath) -o $(InputDir)\moc_$(InputName).cpp"
Outputs="$(InputDir)\moc_$(InputName).cpp"
FileExtensions="*.moc"
ExecutionDescription="Moc&apos;ing $(InputFileName)"
>
<Properties>
</Properties>
</CustomBuildRule>
<CustomBuildRule
Name="RCC"
DisplayName="RCC compiler"
CommandLine="$(QTDIR)\bin\rcc $(InputPath) -o $(InputDir)\qrc_$(InputName).cpp -name $(ProjectName)"
Outputs="$(InputDir)\qrc_$(InputName).cpp"
FileExtensions="*.qrc"
ExecutionDescription="RCC&apos;ing $(InputFileName)"
>
<Properties>
</Properties>
</CustomBuildRule>
</Rules>
</VisualStudioToolFile>

View File

@ -0,0 +1,123 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is
* 'psimpl - generic n-dimensional polyline simplification'.
*
* The Initial Developer of the Original Code is
* Elmar de Koning.
* Portions created by the Initial Developer are Copyright (C) 2010-2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* ***** END LICENSE BLOCK ***** */
/*
psimpl - generic n-dimensional polyline simplification
Copyright (C) 2010-2011 Elmar de Koning, edekoning@gmail.com
This file is part of psimpl, and is hosted at SourceForge:
http://sourceforge.net/projects/psimpl/
*/
#include "RenderArea.h"
#include <QtGui/QPainter>
namespace psimpl {
RenderArea::RenderArea (QWidget *inParent, Qt::WindowFlags inFlags) :
QFrame (inParent, inFlags),
mDrawGeneratedPolyline (true),
mDrawSimplifiedPolyline (false),
mKeepAspectRatio (true)
{
}
void RenderArea::paintEvent(QPaintEvent * /*inEvent*/) {
if (!mGeneratedPolyline.elementCount ())
return;
QRectF rect = mGeneratedPolyline.boundingRect ();
if (!rect.isValid ())
return;
QPainter painter (this);
if (mKeepAspectRatio) {
qreal scale = qMin ((width () - 1) / rect.width (), (height () - 1) / rect.height ());
painter.translate ((width () - (rect.width () * scale)) / 2.0,
(height () - (rect.height () * scale)) / 2.0);
painter.scale (scale, scale);
painter.translate (-rect.left (), -rect.top ());
}
else {
painter.scale ((width () - 1) / rect.width (), (height () - 1) / rect.height ());
painter.translate (-rect.left (), -rect.top ());
}
if (mDrawGeneratedPolyline) {
painter.setPen (Qt::darkBlue);
painter.drawPath (mGeneratedPolyline);
}
if (!mSimplifiedPolyline.elementCount ())
return;
if (mDrawSimplifiedPolyline) {
painter.setPen (Qt::darkRed);
painter.drawPath (mSimplifiedPolyline);
}
}
QPainterPath RenderArea::Convert (QVector <qreal>& polyline)
{
// limit paths to max 100.000 points to speed up drawing
const int threshold = 100000;
QPainterPath path;
if (polyline.empty ()) {
return path;
}
int pointCount = polyline.size () / 2;
qreal skipStep = (qreal) (pointCount - threshold) / (qreal) threshold;
qreal skipValue = skipStep;
path.moveTo(polyline [0], polyline [1]);
for (int i=1; i<pointCount; i++) {
if (skipValue > 1.0) {
skipValue -= 1.0;
}
else {
path.lineTo (polyline [i*2], polyline [i*2+1]);
skipValue += skipStep;
}
}
int elemCount = path.elementCount ();
elemCount++;
return path;
}
void RenderArea::SetGeneratedPolyline (QVector <qreal>& polyline)
{
mSimplifiedPolyline = QPainterPath ();
mGeneratedPolyline = Convert (polyline);
}
void RenderArea::SetSimplifiedPolyline (QVector <qreal>& polyline)
{
mSimplifiedPolyline = Convert (polyline);
}
} // namespace psimpl

View File

@ -0,0 +1,76 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is
* 'psimpl - generic n-dimensional polyline simplification'.
*
* The Initial Developer of the Original Code is
* Elmar de Koning.
* Portions created by the Initial Developer are Copyright (C) 2010-2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* ***** END LICENSE BLOCK ***** */
/*
psimpl - generic n-dimensional polyline simplification
Copyright (C) 2010-2011 Elmar de Koning, edekoning@gmail.com
This file is part of psimpl, and is hosted at SourceForge:
http://sourceforge.net/projects/psimpl/
*/
#ifndef RENDERAREA_H
#define RENDERAREA_H
#include <QtGui/QFrame>
#include <QtGui/QPainterPath>
namespace psimpl {
/*!
\brief A frame that can draw polylines and their simplification.
Note that the point count of each polyline is always limited to 100.000 to speed up drawing.
*/
class RenderArea : public QFrame
{
public:
RenderArea (QWidget *inParent = 0, Qt::WindowFlags inFlags = 0);
void SetGeneratedPolyline (QVector <qreal>& polyline);
void SetSimplifiedPolyline (QVector <qreal>& polyline);
void SetVisibleGeneratedPolyline (bool visible) { mDrawGeneratedPolyline = visible; }
void SetVisibleSimplifiedPolyline (bool visible) { mDrawSimplifiedPolyline = visible; }
void SetKeepAspectRatio (bool keep) { mKeepAspectRatio = keep; }
protected:
void paintEvent (QPaintEvent *inEvent);
private:
QPainterPath Convert (QVector <qreal>& polyline);
private:
QPainterPath mGeneratedPolyline;
QPainterPath mSimplifiedPolyline;
bool mDrawGeneratedPolyline;
bool mDrawSimplifiedPolyline;
bool mKeepAspectRatio;
};
} // namespace psimpl
#endif // RENDERAREA_H

43
lib/psimpl/demo/main.cpp Normal file
View File

@ -0,0 +1,43 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is
* 'psimpl - generic n-dimensional polyline simplification'.
*
* The Initial Developer of the Original Code is
* Elmar de Koning.
* Portions created by the Initial Developer are Copyright (C) 2010-2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* ***** END LICENSE BLOCK ***** */
/*
psimpl - generic n-dimensional polyline simplification
Copyright (C) 2010-2011 Elmar de Koning, edekoning@gmail.com
This file is part of psimpl, and is hosted at SourceForge:
http://sourceforge.net/projects/psimpl/
*/
#include <QtGui/QApplication>
#include "MainWindow.h"
int main (int argc, char *argv [])
{
QApplication a (argc, argv);
psimpl::MainWindow w;
w.show ();
return a.exec ();
}

View File

@ -0,0 +1,22 @@
# -------------------------------------------------
# Project created by QtCreator 2010-06-05T12:09:26
# -------------------------------------------------
TARGET = psimpl-demo
TEMPLATE = app
VERSION = 7
SOURCES += main.cpp \
MainWindow.cpp \
DPWorker.cpp \
RenderArea.cpp
HEADERS += MainWindow.h \
DPWorker.h \
RenderArea.h \
psimpl_reference.h \
psimpl.h \
../lib/psimpl.h
FORMS += MainWindow.ui
OTHER_FILES += \
resource.rc \
../README.txt \
../LICENSE.txt
RC_FILE = resource.rc

View File

@ -0,0 +1,304 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9,00"
Name="psimpl"
ProjectGUID="{B27BE17F-AC18-4797-9E81-1C04D37B8AC4}"
RootNamespace="DouglasPeucker"
Keyword="Win32Proj"
TargetFrameworkVersion="196613"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
<ToolFile
RelativePath=".\QTRules.rules"
/>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="MOC"
/>
<Tool
Name="RCC"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="UIC"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="$(QTDIR)/include"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="0"
WarningLevel="4"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="qtmaind.lib qtcored4.lib qtguid4.lib"
OutputFile="$(OutDir)\$(ProjectName)-demod.exe"
LinkIncremental="2"
AdditionalLibraryDirectories="$(QTDIR)/lib"
GenerateDebugInformation="true"
SubSystem="1"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="MOC"
/>
<Tool
Name="RCC"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="UIC"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
EnableIntrinsicFunctions="true"
AdditionalIncludeDirectories="$(QTDIR)/include"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
RuntimeLibrary="2"
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="0"
WarningLevel="4"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="qtmain.lib qtcore4.lib qtgui4.lib"
OutputFile="$(OutDir)\$(ProjectName)-demo.exe"
LinkIncremental="1"
AdditionalLibraryDirectories="$(QTDIR)/lib"
GenerateDebugInformation="true"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="doc"
>
<File
RelativePath="..\doc\Doxyfile"
>
</File>
</Filter>
<Filter
Name="demo"
>
<File
RelativePath=".\DPWorker.cpp"
>
</File>
<File
RelativePath=".\DPWorker.h"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="MOC"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="MOC"
/>
</FileConfiguration>
</File>
<File
RelativePath=".\main.cpp"
>
</File>
<File
RelativePath=".\MainWindow.cpp"
>
</File>
<File
RelativePath=".\MainWindow.h"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="MOC"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="MOC"
/>
</FileConfiguration>
</File>
<File
RelativePath=".\MainWindow.ui"
>
</File>
<File
RelativePath=".\moc_DPWorker.cpp"
>
</File>
<File
RelativePath=".\moc_MainWindow.cpp"
>
</File>
<File
RelativePath=".\psimpl_reference.h"
>
</File>
<File
RelativePath=".\RenderArea.cpp"
>
</File>
<File
RelativePath=".\RenderArea.h"
>
</File>
<File
RelativePath=".\ui_MainWindow.h"
>
</File>
</Filter>
<Filter
Name="lib"
>
<File
RelativePath="..\lib\psimpl.h"
>
</File>
</Filter>
<File
RelativePath="..\LICENSE.txt"
>
</File>
<File
RelativePath="..\README.txt"
>
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@ -0,0 +1,238 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is
* 'psimpl - generic n-dimensional polyline simplification'.
*
* The Initial Developer of the Original Code is
* Elmar de Koning.
* Portions created by the Initial Developer are Copyright (C) 2010-2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* ***** END LICENSE BLOCK ***** */
/*
psimpl - generic n-dimensional polyline simplification
Copyright (C) 2010-2011 Elmar de Koning, edekoning@gmail.com
This file is part of psimpl, and is hosted at SourceForge:
http://sourceforge.net/projects/psimpl/
*/
#ifndef PSIMPL_CLASSIC_H
#define PSIMPL_CLASSIC_H
#include <stack>
namespace psimpl {
namespace classic {
// Contains a minimal modified version of the Douglas-Peucker recursive simplification
// routine as available from www.softsurfer.com. Modifications include:
// - Removed recursion by using a stack
// - Added minimal Point, Vector, and Segment classes as needed by the algorithm
// minimal point class
class Point {
public:
Point () :
x (0.f),
y (0.f)
{}
Point (float x, float y) :
x (x),
y (y)
{}
float x, y;
};
// reuse the point class for a vector
typedef Point Vector;
// operators as needed by the algorithm
Point operator+ (const Point& P, const Vector& V) {
return Point (P.x+V.x, P.y+V.y);
}
Vector operator- (const Point& P0, const Point& P1) {
return Vector (P0.x-P1.x, P0.y-P1.y);
}
Vector operator* (double s, const Vector& V) {
return Vector (s*V.x, s*V.y);
}
// minimal segment class
class Segment {
public:
Segment (const Point& P0, const Point& P1) :
P0(P0),
P1(P1)
{}
Point P0;
Point P1;
};
// define the stack and sub poly that are used to replace the original recusion
typedef std::pair< int, int > SubPoly;
typedef std::stack< SubPoly > Stack;
// Copyright 2002, softSurfer (www.softsurfer.com)
// This code may be freely used and modified for any purpose
// providing that this copyright notice is included with it.
// SoftSurfer makes no warranty for this code, and cannot be held
// liable for any real or imagined damage resulting from its use.
// Users of this code must verify correctness for their application.
// Assume that classes are already given for the objects:
// Point and Vector with
// coordinates {float x, y, z;} // as many as are needed
// operators for:
// == to test equality
// != to test inequality
// (Vector)0 = (0,0,0) (null vector)
// Point = Point ± Vector
// Vector = Point - Point
// Vector = Vector ± Vector
// Vector = Scalar * Vector (scalar product)
// Vector = Vector * Vector (cross product)
// Segment with defining endpoints {Point P0, P1;}
//===================================================================
// dot product (3D) which allows vector operations in arguments
#define __dot(u,v) ((u).x * (v).x + (u).y * (v).y)
#define __norm2(v) __dot(v,v) // norm2 = squared length of vector
#define __norm(v) sqrt(__norm2(v)) // norm = length of vector
#define __d2(u,v) __norm2(u-v) // distance squared = norm2 of difference
#define __d(u,v) __norm(u-v) // distance = norm of difference
// simplifyDP():
// This is the Douglas-Peucker recursive simplification routine
// It just marks vertices that are part of the simplified polyline
// for approximating the polyline subchain v[j] to v[k].
// Input: tol = approximation tolerance
// v[] = polyline array of vertex points
// j,k = indices for the subchain v[j] to v[k]
// Output: mk[] = array of markers matching vertex array v[]
void
simplifyDP( Stack& stack, float tol, Point* v, int j, int k, int* mk )
{
if (k <= j+1) // there is nothing to simplify
return;
// check for adequate approximation by segment S from v[j] to v[k]
int maxi = j; // index of vertex farthest from S
float maxd2 = 0; // distance squared of farthest vertex
float tol2 = tol * tol; // tolerance squared
Segment S (v[j], v[k]); // segment from v[j] to v[k]
Vector u = S.P1 - S.P0; // segment direction vector
double cu = __dot(u,u); // segment length squared
// test each vertex v[i] for max distance from S
// compute using the Feb 2001 Algorithm's dist_Point_to_Segment()
// Note: this works in any dimension (2D, 3D, ...)
Vector w;
Point Pb; // base of perpendicular from v[i] to S
double b, cw, dv2; // dv2 = distance v[i] to S squared
for (int i=j+1; i<k; i++)
{
// compute distance squared
w = v[i] - S.P0;
cw = __dot(w,u);
if ( cw <= 0 )
dv2 = __d2(v[i], S.P0);
else if ( cu <= cw )
dv2 = __d2(v[i], S.P1);
else {
b = cw / cu;
Pb = S.P0 + b * u;
dv2 = __d2(v[i], Pb);
}
// test with current max distance squared
if (dv2 <= maxd2)
continue;
// v[i] is a new max vertex
maxi = i;
maxd2 = dv2;
}
if (maxd2 > tol2) // error is worse than the tolerance
{
// split the polyline at the farthest vertex from S
mk[maxi] = 1; // mark v[maxi] for the simplified polyline
// recursively simplify the two subpolylines at v[maxi]
stack.push( std::make_pair (j, maxi));
stack.push( std::make_pair (maxi, k));
}
// else the approximation is OK, so ignore intermediate vertices
return;
}
// poly_simplify():
// Input: tol = approximation tolerance
// V[] = polyline array of vertex points
// n = the number of points in V[]
// Output: sV[]= simplified polyline vertices (max is n)
// Return: m = the number of points in sV[]
int
poly_simplify(float tol, Point* V, int n, Point* sV )
{
int i, k, m, pv; // misc counters
float tol2 = tol * tol; // tolerance squared
Point* vt = new Point[n]; // vertex buffer
int* mk = new int[n]; // marker buffer
for (i=0; i<n; i++) {
mk[i] = 0;
}
// STAGE 1. Vertex Reduction within tolerance of prior vertex cluster
vt[0] = V[0]; // start at the beginning
for (i=k=1, pv=0; i<n; i++) {
if (__d2(V[i], V[pv]) < tol2)
continue;
vt[k++] = V[i];
pv = i;
}
if (pv < n-1)
vt[k++] = V[n-1]; // finish at the end
// STAGE 2. Douglas-Peucker polyline simplification
mk[0] = mk[k-1] = 1; // mark the first and last vertices
Stack stack; // use a stack i.s.o. recursion (NEW)
stack.push( std::make_pair( 0, k-1 )); // add complete poly
while (!stack.empty()) {
SubPoly subPoly = stack.top(); // take a sub poly
stack.pop(); // and simplify it
simplifyDP( stack, tol, vt, subPoly.first, subPoly.second, mk );
}
// copy marked vertices to the output simplified polyline
for (i=m=0; i<k; i++) {
if (mk[i])
sV[m++] = vt[i];
}
delete vt;
delete mk;
return m; // m vertices in simplified polyline
}
//===================================================================
}
}
#endif // PSIMPL_CLASSIC_H

View File

@ -0,0 +1,34 @@
# if defined(UNDER_CE)
# include <winbase.h>
# else
# include <winver.h>
# endif
VS_VERSION_INFO VERSIONINFO
FILEVERSION 7,0,0,0
PRODUCTVERSION 7,0,0,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS VS_FF_DEBUG
#else
FILEFLAGS 0x0L
#endif
FILEOS VOS__WINDOWS32
FILETYPE VFT_DLL
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904B0"
BEGIN
VALUE "CompanyName", "Elmar de Koning\0"
VALUE "FileDescription", "psimpl demo application\0"
VALUE "FileVersion", "7.0.0.0\0"
VALUE "LegalCopyright", "Copyright (C) 2010-2011 Elmar de Koning\0"
VALUE "OriginalFilename", "psimpl-demo.exe\0"
VALUE "ProductName", "psimpl - generic n-dimensional polyline simplification\0"
END
END
END
/* End of Version info */

1890
lib/psimpl/psimpl.h Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,2 @@
simplify.diff:
diff ../turf-simplify/lib/simplify.js simplify.js > simplify.diff || true

View File

@ -0,0 +1 @@
This is an alternative Simplify.js version to take coordinates as a nested array.

View File

@ -0,0 +1,42 @@
1,9d0
< /*
< (c) 2013, Vladimir Agafonkin
< Simplify.js, a high-performance JS polyline simplification library
< mourner.github.io/simplify-js
< */
<
< // to suit your point format, run search/replace for '.x' and '.y';
< // for 3D version, see 3d branch (configurability would draw significant performance overhead)
<
13,14c4,5
< var dx = p1.x - p2.x,
< dy = p1.y - p2.y;
---
> var dx = p1[0] - p2[0],
> dy = p1[1] - p2[1];
22,25c13,16
< var x = p1.x,
< y = p1.y,
< dx = p2.x - x,
< dy = p2.y - y;
---
> var x = p1[0],
> y = p1[1],
> dx = p2[0] - x,
> dy = p2[1] - y;
29c20
< var t = ((p.x - x) * dx + (p.y - y) * dy) / (dx * dx + dy * dy);
---
> var t = ((p[0] - x) * dx + (p[1] - y) * dy) / (dx * dx + dy * dy);
32,33c23,24
< x = p2.x;
< y = p2.y;
---
> x = p2[0];
> y = p2[1];
41,42c32,33
< dx = p.x - x;
< dy = p.y - y;
---
> dx = p[0] - x;
> dy = p[1] - y;

View File

@ -0,0 +1,102 @@
// square distance between 2 points
function getSqDist(p1, p2) {
var dx = p1[0] - p2[0],
dy = p1[1] - p2[1];
return dx * dx + dy * dy;
}
// square distance from a point to a segment
function getSqSegDist(p, p1, p2) {
var x = p1[0],
y = p1[1],
dx = p2[0] - x,
dy = p2[1] - y;
if (dx !== 0 || dy !== 0) {
var t = ((p[0] - x) * dx + (p[1] - y) * dy) / (dx * dx + dy * dy);
if (t > 1) {
x = p2[0];
y = p2[1];
} else if (t > 0) {
x += dx * t;
y += dy * t;
}
}
dx = p[0] - x;
dy = p[1] - y;
return dx * dx + dy * dy;
}
// rest of the code doesn't care about point format
// basic distance-based simplification
function simplifyRadialDist(points, sqTolerance) {
var prevPoint = points[0],
newPoints = [prevPoint],
point;
for (var i = 1, len = points.length; i < len; i++) {
point = points[i];
if (getSqDist(point, prevPoint) > sqTolerance) {
newPoints.push(point);
prevPoint = point;
}
}
if (prevPoint !== point) newPoints.push(point);
return newPoints;
}
function simplifyDPStep(points, first, last, sqTolerance, simplified) {
var maxSqDist = sqTolerance,
index;
for (var i = first + 1; i < last; i++) {
var sqDist = getSqSegDist(points[i], points[first], points[last]);
if (sqDist > maxSqDist) {
index = i;
maxSqDist = sqDist;
}
}
if (maxSqDist > sqTolerance) {
if (index - first > 1) simplifyDPStep(points, first, index, sqTolerance, simplified);
simplified.push(points[index]);
if (last - index > 1) simplifyDPStep(points, index, last, sqTolerance, simplified);
}
}
// simplification using Ramer-Douglas-Peucker algorithm
function simplifyDouglasPeucker(points, sqTolerance) {
var last = points.length - 1;
var simplified = [points[0]];
simplifyDPStep(points, 0, last, sqTolerance, simplified);
simplified.push(points[last]);
return simplified;
}
// both algorithms combined for awesome performance
export default function simplify(points, tolerance, highestQuality) {
if (points.length <= 2) return points;
var sqTolerance = tolerance !== undefined ? tolerance * tolerance : 1;
points = highestQuality ? points : simplifyRadialDist(points, sqTolerance);
points = simplifyDouglasPeucker(points, sqTolerance);
return points;
}

28
lib/simplify-js/.gitignore vendored Normal file
View File

@ -0,0 +1,28 @@
### Node template
# Logs
logs
*.log
# Runtime data
pids
*.pid
*.seed
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# node-waf configuration
.lock-wscript
# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release
# Dependency directory
# https://docs.npmjs.com/misc/faq#should-i-check-my-node-modules-folder-into-git
node_modules

22
lib/simplify-js/LICENSE Normal file
View File

@ -0,0 +1,22 @@
Copyright (c) 2017, Vladimir Agafonkin
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are
permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of
conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list
of conditions and the following disclaimer in the documentation and/or other materials
provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

19
lib/simplify-js/README.md Normal file
View File

@ -0,0 +1,19 @@
Simplify.js is a high-performance JavaScript polyline simplification library by Vladimir Agafonkin, extracted from [Leaflet](http://leafletjs.com).
Checkout the demo with docs: http://mourner.github.io/simplify-js/
#### Ports
* Python: [omarestrella / simplify.py](https://github.com/omarestrella/simplify.py) (by Omar Estrella)
* PHP: [AKeN / simplify-php](https://github.com/AKeN/simplify-php) (by Rotari Gheorghe)
* PHP: [andreychumak / simplify-php](https://github.com/andreychumak/simplify-php) (by Andrey Chumak)
* Java: [ekeneijeoma / simplify-java](https://github.com/ekeneijeoma/simplify-java) (by Ekene Ijeoma)
* Java: [hgoebl / simplify-java](https://github.com/hgoebl/simplify-java) (by Heinrich Göbl)
* Processing: [ekeneijeoma / simplify-processing](https://github.com/ekeneijeoma/simplify-processing) (by Ekene Ijeoma)
* AS3: [fnicollet / simplify-as3](https://github.com/fnicollet/simplify-as3) (by Fabien Nicollet)
* Rust: [calvinmetcalf / simplify-rs](https://github.com/calvinmetcalf/simplify-rs) (by Calvin Metcalf)
* Ruby: [odlp / simplify_rb](https://github.com/odlp/simplify_rb) (by Oliver Peate)
* Go: [yrsh / simplify_go](https://github.com/yrsh/simplify-go) (by Anton Korotkikh)
* C# (Portable): [imshz / simplify-net](https://github.com/imshz/simplify-net) (by Shees Ul-Hassan)
* Swift: [malcommac / SwiftSimplify](https://github.com/malcommac/SwiftSimplify) (by Daniele Margutti)
* Unreal Engine: [SINTEF-9012 / SimplifyUnreal](https://github.com/SINTEF-9012/SimplifyUnreal) (by Antoine Pultier)

View File

@ -0,0 +1,19 @@
var Benchmark = require('benchmark');
var simplify = require('../simplify');
var points = require('../test/fixtures/1k.json');
console.log('Benchmarking simplify on ' + points.length + ' points...');
new Benchmark.Suite()
.add('simplify (HQ)', function() {
simplify(points, 1, true);
})
.add('simplify', function() {
simplify(points, 1, false);
})
.on('cycle', function(event) {
console.log(String(event.target));
})
.run();

9
lib/simplify-js/index.d.ts vendored Normal file
View File

@ -0,0 +1,9 @@
interface Point {
x: number;
y: number;
}
declare function simplify (points: Point[], tolerance?: number, highQuality?: boolean): Point[];
declare namespace simplify {}
export = simplify;

View File

@ -0,0 +1,38 @@
{
"name": "simplify-js",
"version": "1.2.3",
"description": "A high-performance JavaScript 2D/3D polyline simplification library",
"homepage": "http://mourner.github.com/simplify-js/",
"author": "Vladimir Agafonkin",
"license": "BSD-2-Clause",
"keywords": [
"math",
"geometry",
"polyline",
"simplification"
],
"repository": {
"type": "git",
"url": "git://github.com/mourner/simplify-js.git"
},
"main": "simplify.js",
"files": [
"index.d.ts",
"simplify.js"
],
"types": "index.d.ts",
"devDependencies": {
"benchmark": "^2.1.4",
"faucet": "0.0.1",
"jshint": "^2.9.5",
"tape": "^4.8.0"
},
"scripts": {
"test": "jshint simplify.js test/test.js && node test/test.js | faucet"
},
"jshintConfig": {
"quotmark": "single",
"trailing": true,
"unused": true
}
}

123
lib/simplify-js/simplify.js Normal file
View File

@ -0,0 +1,123 @@
/*
(c) 2017, Vladimir Agafonkin
Simplify.js, a high-performance JS polyline simplification library
mourner.github.io/simplify-js
*/
(function () { 'use strict';
// to suit your point format, run search/replace for '.x' and '.y';
// for 3D version, see 3d branch (configurability would draw significant performance overhead)
// square distance between 2 points
function getSqDist(p1, p2) {
var dx = p1.x - p2.x,
dy = p1.y - p2.y;
return dx * dx + dy * dy;
}
// square distance from a point to a segment
function getSqSegDist(p, p1, p2) {
var x = p1.x,
y = p1.y,
dx = p2.x - x,
dy = p2.y - y;
if (dx !== 0 || dy !== 0) {
var t = ((p.x - x) * dx + (p.y - y) * dy) / (dx * dx + dy * dy);
if (t > 1) {
x = p2.x;
y = p2.y;
} else if (t > 0) {
x += dx * t;
y += dy * t;
}
}
dx = p.x - x;
dy = p.y - y;
return dx * dx + dy * dy;
}
// rest of the code doesn't care about point format
// basic distance-based simplification
function simplifyRadialDist(points, sqTolerance) {
var prevPoint = points[0],
newPoints = [prevPoint],
point;
for (var i = 1, len = points.length; i < len; i++) {
point = points[i];
if (getSqDist(point, prevPoint) > sqTolerance) {
newPoints.push(point);
prevPoint = point;
}
}
if (prevPoint !== point) newPoints.push(point);
return newPoints;
}
function simplifyDPStep(points, first, last, sqTolerance, simplified) {
var maxSqDist = sqTolerance,
index;
for (var i = first + 1; i < last; i++) {
var sqDist = getSqSegDist(points[i], points[first], points[last]);
if (sqDist > maxSqDist) {
index = i;
maxSqDist = sqDist;
}
}
if (maxSqDist > sqTolerance) {
if (index - first > 1) simplifyDPStep(points, first, index, sqTolerance, simplified);
simplified.push(points[index]);
if (last - index > 1) simplifyDPStep(points, index, last, sqTolerance, simplified);
}
}
// simplification using Ramer-Douglas-Peucker algorithm
function simplifyDouglasPeucker(points, sqTolerance) {
var last = points.length - 1;
var simplified = [points[0]];
simplifyDPStep(points, 0, last, sqTolerance, simplified);
simplified.push(points[last]);
return simplified;
}
// both algorithms combined for awesome performance
function simplify(points, tolerance, highestQuality) {
if (points.length <= 2) return points;
var sqTolerance = tolerance !== undefined ? tolerance * tolerance : 1;
points = highestQuality ? points : simplifyRadialDist(points, sqTolerance);
points = simplifyDouglasPeucker(points, sqTolerance);
return points;
}
// export as AMD module / Node module / browser or worker variable
if (typeof define === 'function' && define.amd) define(function() { return simplify; });
else if (typeof module !== 'undefined') {
module.exports = simplify;
module.exports.default = simplify;
} else if (typeof self !== 'undefined') self.simplify = simplify;
else window.simplify = simplify;
})();

1
lib/simplify-js/test/fixtures/1k.json vendored Normal file

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,60 @@
var points = [
{x:224.55,y:250.15},{x:226.91,y:244.19},{x:233.31,y:241.45},{x:234.98,y:236.06},
{x:244.21,y:232.76},{x:262.59,y:215.31},{x:267.76,y:213.81},{x:273.57,y:201.84},
{x:273.12,y:192.16},{x:277.62,y:189.03},{x:280.36,y:181.41},{x:286.51,y:177.74},
{x:292.41,y:159.37},{x:296.91,y:155.64},{x:314.95,y:151.37},{x:319.75,y:145.16},
{x:330.33,y:137.57},{x:341.48,y:139.96},{x:369.98,y:137.89},{x:387.39,y:142.51},
{x:391.28,y:139.39},{x:409.52,y:141.14},{x:414.82,y:139.75},{x:427.72,y:127.30},
{x:439.60,y:119.74},{x:474.93,y:107.87},{x:486.51,y:106.75},{x:489.20,y:109.45},
{x:493.79,y:108.63},{x:504.74,y:119.66},{x:512.96,y:122.35},{x:518.63,y:120.89},
{x:524.09,y:126.88},{x:529.57,y:127.86},{x:534.21,y:140.93},{x:539.27,y:147.24},
{x:567.69,y:148.91},{x:575.25,y:157.26},{x:580.62,y:158.15},{x:601.53,y:156.85},
{x:617.74,y:159.86},{x:622.00,y:167.04},{x:629.55,y:194.60},{x:638.90,y:195.61},
{x:641.26,y:200.81},{x:651.77,y:204.56},{x:671.55,y:222.55},{x:683.68,y:217.45},
{x:695.25,y:219.15},{x:700.64,y:217.98},{x:703.12,y:214.36},{x:712.26,y:215.87},
{x:721.49,y:212.81},{x:727.81,y:213.36},{x:729.98,y:208.73},{x:735.32,y:208.20},
{x:739.94,y:204.77},{x:769.98,y:208.42},{x:779.60,y:216.87},{x:784.20,y:218.16},
{x:800.24,y:214.62},{x:810.53,y:219.73},{x:817.19,y:226.82},{x:820.77,y:236.17},
{x:827.23,y:236.16},{x:829.89,y:239.89},{x:851.00,y:248.94},{x:859.88,y:255.49},
{x:865.21,y:268.53},{x:857.95,y:280.30},{x:865.48,y:291.45},{x:866.81,y:298.66},
{x:864.68,y:302.71},{x:867.79,y:306.17},{x:859.87,y:311.37},{x:860.08,y:314.35},
{x:858.29,y:314.94},{x:858.10,y:327.60},{x:854.54,y:335.40},{x:860.92,y:343.00},
{x:856.43,y:350.15},{x:851.42,y:352.96},{x:849.84,y:359.59},{x:854.56,y:365.53},
{x:849.74,y:370.38},{x:844.09,y:371.89},{x:844.75,y:380.44},{x:841.52,y:383.67},
{x:839.57,y:390.40},{x:845.59,y:399.05},{x:848.40,y:407.55},{x:843.71,y:411.30},
{x:844.09,y:419.88},{x:839.51,y:432.76},{x:841.33,y:441.04},{x:847.62,y:449.22},
{x:847.16,y:458.44},{x:851.38,y:462.79},{x:853.97,y:471.15},{x:866.36,y:480.77}
];
var simplified = [
{x:224.55,y:250.15},{x:267.76,y:213.81},{x:296.91,y:155.64},{x:330.33,y:137.57},
{x:409.52,y:141.14},{x:439.60,y:119.74},{x:486.51,y:106.75},{x:529.57,y:127.86},
{x:539.27,y:147.24},{x:617.74,y:159.86},{x:629.55,y:194.60},{x:671.55,y:222.55},
{x:727.81,y:213.36},{x:739.94,y:204.77},{x:769.98,y:208.42},{x:779.60,y:216.87},
{x:800.24,y:214.62},{x:820.77,y:236.17},{x:859.88,y:255.49},{x:865.21,y:268.53},
{x:857.95,y:280.30},{x:867.79,y:306.17},{x:859.87,y:311.37},{x:854.54,y:335.40},
{x:860.92,y:343.00},{x:849.84,y:359.59},{x:854.56,y:365.53},{x:844.09,y:371.89},
{x:839.57,y:390.40},{x:848.40,y:407.55},{x:839.51,y:432.76},{x:853.97,y:471.15},
{x:866.36,y:480.77}
];
var simplify = require('../simplify'),
t = require('tape');
t('simplifies points correctly with the given tolerance', function (t) {
var result = simplify(points, 5);
t.same(result, simplified);
t.end();
});
t('just return the points if it has only one point', function(t){
var result = simplify([{x:1, y:2}]);
t.same(result, [{x:1, y:2}]);
t.end();
});
t('just return the points if it has no points', function(t){
var result = simplify([]);
t.same(result, []);
t.end();
});

View File

@ -0,0 +1,13 @@
OPTIMIZE="-O3"
simplify.wasm module.js: simplify.c
emcc \
${OPTIMIZE} \
--closure 1 \
-s WASM=1 \
-s ALLOW_MEMORY_GROWTH=1 \
-s MODULARIZE=1 \
-s EXPORT_ES6=1 \
-s EXPORTED_FUNCTIONS='["_simplify", "_malloc", "_free"]' \
-o simplify.js \
simplify.c

View File

@ -0,0 +1,32 @@
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div>Original array: <span id="src">Loading...</span></div>
<div>Simplified array: <span id="dest">Loading...</span></div>
<script type="module">
import moduleFactory from './simplify.js'
import { storeCoords, loadResultAndFreeMemory } from '../wasm-util/coordinates.js'
const module = moduleFactory()
const data = [[0, 0], [1, 1], [1, 2], [2, 2], [5, 5], [5, 0], [6, 10], [10, 10]]
document.getElementById('src').innerText = JSON.stringify(data)
module.onRuntimeInitialized = async _ => {
const buffer = storeCoords(module, data)
const result = module._simplify(buffer, data.length * 2, 2, true)
module._free(buffer)
const simplified = loadResultAndFreeMemory(module, result)
document.getElementById('dest').innerText = JSON.stringify(simplified)
}
</script>
</body>
</html>

View File

@ -0,0 +1,31 @@
/*
This file is meant to be processed in the context of an asset bundler.
Specifically the import of 'simplify.wasm' is meant to be resolved by the
corresponding path to that file. Configure a file loader to resolve .wasm
files (e.g. Webpack: file-loader) accordingly.
Otherwise you have to use the module factory 'simplify.js' manually and
reproduce the steps from below to fit your build context. See example.html.
Other than wrapping the memory handling for convenience this method also makes
sure the module is only loaded once.
*/
import wasmModuleFactory from './simplify.js'
import wasmUrl from './simplify.wasm'
import { initEmscriptenModule } from '../wasm-util/initEmscripten.js'
import { storeCoords, loadResultAndFreeMemory } from '../wasm-util/coordinates.js'
export async function simplifyWasm(coords, tolerance, highestQuality) {
const module = await getModule()
const buffer = storeCoords(module, coords)
const result = module._simplify(buffer, coords.length * 2, tolerance, highestQuality)
module._free(buffer)
return loadResultAndFreeMemory(module, result)
}
let emscriptenModule
export async function getModule () {
if (!emscriptenModule) emscriptenModule = initEmscriptenModule(wasmModuleFactory, wasmUrl)
return await emscriptenModule
}

View File

@ -0,0 +1,122 @@
#include <stdlib.h>
#define DIM 2
void copyCoordinate(double* from, double* to) {
for (int i = 0; i < DIM; i++) {
to[i] = from[i];
}
}
// extends array and copies point on the end. Returns new length
int push(double* array, int length, double* point) {
int newLength = length + DIM;
// realloc(array, newLength * sizeof(double));
copyCoordinate(point, array + length);
return newLength;
}
// square distance between 2 points
double getSqDist(double* p1, double* p2) {
double dx = p1[0] - p2[0],
dy = p1[1] - p2[1];
return dx * dx + dy * dy;
}
// square distance from a point to a segment
double getSqSegDist(double* p, double* p1, double* p2) {
double x = p1[0],
y = p1[1],
dx = p2[0] - x,
dy = p2[1] - y;
if (dx != 0 || dy != 0) {
double t = ((p[0] - x) * dx + (p[1] - y) * dy) / (dx * dx + dy * dy);
if (t > 1) {
x = p2[0];
y = p2[1];
} else if (t > 0) {
x += dx * t;
y += dy * t;
}
}
dx = p[0] - x;
dy = p[1] - y;
return dx * dx + dy * dy;
}
// basic distance-based simplification
int simplifyRadialDist(double* points, int length, double sqTolerance, double* newPoints) {
double* prevPoint = points;
double* point;
int sizeOfNewPoints = push(newPoints, 0, points);
for (int i = 1; i < length; i += DIM) {
point = points + i;
if (getSqDist(point, prevPoint) > sqTolerance) {
sizeOfNewPoints = push(newPoints, sizeOfNewPoints, point);
prevPoint = point;
}
}
if (prevPoint != point) {
sizeOfNewPoints = push(newPoints, sizeOfNewPoints, point);
}
return sizeOfNewPoints;
}
int simplifyDPStep(double* points, int first, int last, double sqTolerance, double* simplified, int lengthOfSimplified) {
double maxSqDist = sqTolerance;
int index;
for (int i = first + DIM; i < last; i += DIM) {
double sqDist = getSqSegDist(points + i, points + first, points + last);
if (sqDist > maxSqDist) {
index = i;
maxSqDist = sqDist;
}
}
if (maxSqDist > sqTolerance) {
if (index - first > DIM) lengthOfSimplified = simplifyDPStep(points, first, index, sqTolerance, simplified, lengthOfSimplified);
lengthOfSimplified = push(simplified, lengthOfSimplified, points + index);
if (last - index > DIM) lengthOfSimplified = simplifyDPStep(points, index, last, sqTolerance, simplified, lengthOfSimplified);
}
return lengthOfSimplified;
}
// simplification using Ramer-Douglas-Peucker algorithm
int simplifyDouglasPeucker(double* points, int length, double sqTolerance, double* simplified) {
int lengthOfSimplified;
lengthOfSimplified = push(simplified, 0, points);
lengthOfSimplified = simplifyDPStep(points, 0, length - DIM, sqTolerance, simplified, lengthOfSimplified);
lengthOfSimplified = push(simplified, lengthOfSimplified, points + length - DIM);
return lengthOfSimplified;
}
int* simplify(double * input, int length, double tolerance, int highestQuality) {
double sqTolerance = tolerance * tolerance;
double* points = input;
double* resultRdDistance = NULL;
double* result = malloc(length * sizeof(double));
if (!highestQuality) {
resultRdDistance = malloc(length * sizeof(double));
length = simplifyRadialDist(points, length, sqTolerance, resultRdDistance);
points = resultRdDistance;
}
int resultLength = simplifyDouglasPeucker(points, length, sqTolerance, result);
free(resultRdDistance);
int* resultInfo = malloc(2);
resultInfo[0] = (int) result;
resultInfo[1] = resultLength;
return resultInfo;
}

View File

@ -0,0 +1,31 @@
var Module = (function() {
var _scriptDir = typeof document !== 'undefined' && document.currentScript ? document.currentScript.src : undefined;
return (
function(Module) {
Module = Module || {};
var a;a||(a=typeof Module !== 'undefined' ? Module : {});var f={},g;for(g in a)a.hasOwnProperty(g)&&(f[g]=a[g]);a.arguments=[];a.thisProgram="./this.program";a.quit=function(b,c){throw c;};a.preRun=[];a.postRun=[];var h=!1,k=!1,l=!1,m=!1;h="object"===typeof window;k="function"===typeof importScripts;l="object"===typeof process&&"function"===typeof require&&!h&&!k;m=!h&&!l&&!k;var n="";
if(l){n=__dirname+"/";var p,q;a.read=function(b,c){p||(p=require("fs"));q||(q=require("path"));b=q.normalize(b);b=p.readFileSync(b);return c?b:b.toString()};a.readBinary=function(b){b=a.read(b,!0);b.buffer||(b=new Uint8Array(b));b.buffer||r("Assertion failed: undefined");return b};1<process.argv.length&&(a.thisProgram=process.argv[1].replace(/\\/g,"/"));a.arguments=process.argv.slice(2);process.on("uncaughtException",function(b){if(!(b instanceof t))throw b;});process.on("unhandledRejection",r);a.quit=
function(b){process.exit(b)};a.inspect=function(){return"[Emscripten Module object]"}}else if(m)"undefined"!=typeof read&&(a.read=function(b){return read(b)}),a.readBinary=function(b){if("function"===typeof readbuffer)return new Uint8Array(readbuffer(b));b=read(b,"binary");"object"===typeof b||r("Assertion failed: undefined");return b},"undefined"!=typeof scriptArgs?a.arguments=scriptArgs:"undefined"!=typeof arguments&&(a.arguments=arguments),"function"===typeof quit&&(a.quit=function(b){quit(b)});
else if(h||k)k?n=self.location.href:document.currentScript&&(n=document.currentScript.src),_scriptDir&&(n=_scriptDir),0!==n.indexOf("blob:")?n=n.substr(0,n.lastIndexOf("/")+1):n="",a.read=function(b){var c=new XMLHttpRequest;c.open("GET",b,!1);c.send(null);return c.responseText},k&&(a.readBinary=function(b){var c=new XMLHttpRequest;c.open("GET",b,!1);c.responseType="arraybuffer";c.send(null);return new Uint8Array(c.response)}),a.readAsync=function(b,c,d){var e=new XMLHttpRequest;e.open("GET",b,!0);
e.responseType="arraybuffer";e.onload=function(){200==e.status||0==e.status&&e.response?c(e.response):d()};e.onerror=d;e.send(null)},a.setWindowTitle=function(b){document.title=b};var u=a.print||("undefined"!==typeof console?console.log.bind(console):"undefined"!==typeof print?print:null),v=a.printErr||("undefined"!==typeof printErr?printErr:"undefined"!==typeof console&&console.warn.bind(console)||u);for(g in f)f.hasOwnProperty(g)&&(a[g]=f[g]);f=void 0;
var w={"f64-rem":function(b,c){return b%c},"debugger":function(){debugger}};"object"!==typeof WebAssembly&&v("no native wasm support detected");var x,y=!1;"undefined"!==typeof TextDecoder&&new TextDecoder("utf8");"undefined"!==typeof TextDecoder&&new TextDecoder("utf-16le");function z(b){0<b%65536&&(b+=65536-b%65536);return b}var buffer,A,B;
function C(){a.HEAP8=A=new Int8Array(buffer);a.HEAP16=new Int16Array(buffer);a.HEAP32=B=new Int32Array(buffer);a.HEAPU8=new Uint8Array(buffer);a.HEAPU16=new Uint16Array(buffer);a.HEAPU32=new Uint32Array(buffer);a.HEAPF32=new Float32Array(buffer);a.HEAPF64=new Float64Array(buffer)}var E=a.TOTAL_MEMORY||16777216;5242880>E&&v("TOTAL_MEMORY should be larger than TOTAL_STACK, was "+E+"! (TOTAL_STACK=5242880)");
a.buffer?buffer=a.buffer:"object"===typeof WebAssembly&&"function"===typeof WebAssembly.Memory?(x=new WebAssembly.Memory({initial:E/65536}),buffer=x.buffer):buffer=new ArrayBuffer(E);C();B[684]=5245648;function F(b){for(;0<b.length;){var c=b.shift();if("function"==typeof c)c();else{var d=c.l;"number"===typeof d?void 0===c.j?a.dynCall_v(d):a.dynCall_vi(d,c.j):d(void 0===c.j?null:c.j)}}}var G=[],H=[],I=[],J=[],K=!1;function L(){var b=a.preRun.shift();G.unshift(b)}var M=0,N=null,O=null;
a.preloadedImages={};a.preloadedAudios={};function P(){var b=Q;return String.prototype.startsWith?b.startsWith("data:application/octet-stream;base64,"):0===b.indexOf("data:application/octet-stream;base64,")}var Q="simplify.wasm";if(!P()){var R=Q;Q=a.locateFile?a.locateFile(R,n):n+R}function S(){try{if(a.wasmBinary)return new Uint8Array(a.wasmBinary);if(a.readBinary)return a.readBinary(Q);throw"both async and sync fetching of the wasm failed";}catch(b){r(b)}}
function T(){return a.wasmBinary||!h&&!k||"function"!==typeof fetch?new Promise(function(b){b(S())}):fetch(Q,{credentials:"same-origin"}).then(function(b){if(!b.ok)throw"failed to load wasm binary file at '"+Q+"'";return b.arrayBuffer()}).catch(function(){return S()})}
function U(b){function c(b){a.asm=b.exports;M--;a.monitorRunDependencies&&a.monitorRunDependencies(M);0==M&&(null!==N&&(clearInterval(N),N=null),O&&(b=O,O=null,b()))}function d(b){c(b.instance)}function e(b){T().then(function(b){return WebAssembly.instantiate(b,D)}).then(b,function(b){v("failed to asynchronously prepare wasm: "+b);r(b)})}var D={env:b,global:{NaN:NaN,Infinity:Infinity},"global.Math":Math,asm2wasm:w};M++;a.monitorRunDependencies&&a.monitorRunDependencies(M);if(a.instantiateWasm)try{return a.instantiateWasm(D,
c)}catch(Y){return v("Module.instantiateWasm callback failed with error: "+Y),!1}a.wasmBinary||"function"!==typeof WebAssembly.instantiateStreaming||P()||"function"!==typeof fetch?e(d):WebAssembly.instantiateStreaming(fetch(Q,{credentials:"same-origin"}),D).then(d,function(b){v("wasm streaming compile failed: "+b);v("falling back to ArrayBuffer instantiation");e(d)});return{}}
a.asm=function(b,c){c.memory=x;c.table=new WebAssembly.Table({initial:0,maximum:0,element:"anyfunc"});c.__memory_base=1024;c.__table_base=0;return U(c)};function V(){return A.length}function W(b){b=z(b);var c=buffer.byteLength;try{return-1!==x.grow((b-c)/65536)?(buffer=x.buffer,!0):!1}catch(d){return!1}}
var X=a.asm({},{b:function(b){a.___errno_location&&(B[a.___errno_location()>>2]=b);return b},e:V,d:function(b){if(2147418112<b)return!1;for(var c=Math.max(V(),16777216);c<b;)536870912>=c?c=z(2*c):c=Math.min(z((3*c+2147483648)/4),2147418112);if(!W(c))return!1;C();return!0},c:function(){r("OOM")},a:2736},buffer);a.asm=X;a.___errno_location=function(){return a.asm.f.apply(null,arguments)};a._free=function(){return a.asm.g.apply(null,arguments)};a._malloc=function(){return a.asm.h.apply(null,arguments)};
a._simplify=function(){return a.asm.i.apply(null,arguments)};a.asm=X;a.then=function(b){if(a.calledRun)b(a);else{var c=a.onRuntimeInitialized;a.onRuntimeInitialized=function(){c&&c();b(a)}}return a};function t(b){this.name="ExitStatus";this.message="Program terminated with exit("+b+")";this.status=b}t.prototype=Error();t.prototype.constructor=t;O=function aa(){a.calledRun||Z();a.calledRun||(O=aa)};
function Z(){function b(){if(!a.calledRun&&(a.calledRun=!0,!y)){K||(K=!0,F(H));F(I);if(a.onRuntimeInitialized)a.onRuntimeInitialized();if(a.postRun)for("function"==typeof a.postRun&&(a.postRun=[a.postRun]);a.postRun.length;){var b=a.postRun.shift();J.unshift(b)}F(J)}}if(!(0<M)){if(a.preRun)for("function"==typeof a.preRun&&(a.preRun=[a.preRun]);a.preRun.length;)L();F(G);0<M||a.calledRun||(a.setStatus?(a.setStatus("Running..."),setTimeout(function(){setTimeout(function(){a.setStatus("")},1);b()},1)):
b())}}a.run=Z;function r(b){if(a.onAbort)a.onAbort(b);void 0!==b?(u(b),v(b),b=JSON.stringify(b)):b="";y=!0;throw"abort("+b+"). Build with -s ASSERTIONS=1 for more info.";}a.abort=r;if(a.preInit)for("function"==typeof a.preInit&&(a.preInit=[a.preInit]);0<a.preInit.length;)a.preInit.pop()();a.noExitRuntime=!0;Z();
return Module
}
);
})();
export default Module;

Binary file not shown.

20
lib/turf-simplify/LICENSE Normal file
View File

@ -0,0 +1,20 @@
The MIT License (MIT)
Copyright (c) 2017 TurfJS
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@ -0,0 +1,87 @@
# @turf/simplify
<!-- Generated by documentation.js. Update this documentation by updating the source code. -->
## simplify
Takes a [GeoJSON][1] object and returns a simplified version. Internally uses
[simplify-js][2] to perform simplification using the Ramer-Douglas-Peucker algorithm.
**Parameters**
- `geojson` **[GeoJSON][3]** object to be simplified
- `options` **[Object][4]** Optional parameters (optional, default `{}`)
- `options.tolerance` **[number][5]** simplification tolerance (optional, default `1`)
- `options.highQuality` **[boolean][6]** whether or not to spend more time to create a higher-quality simplification with a different algorithm (optional, default `false`)
- `options.mutate` **[boolean][6]** allows GeoJSON input to be mutated (significant performance increase if true) (optional, default `false`)
**Examples**
```javascript
var geojson = turf.polygon([[
[-70.603637, -33.399918],
[-70.614624, -33.395332],
[-70.639343, -33.392466],
[-70.659942, -33.394759],
[-70.683975, -33.404504],
[-70.697021, -33.419406],
[-70.701141, -33.434306],
[-70.700454, -33.446339],
[-70.694274, -33.458369],
[-70.682601, -33.465816],
[-70.668869, -33.472117],
[-70.646209, -33.473835],
[-70.624923, -33.472117],
[-70.609817, -33.468107],
[-70.595397, -33.458369],
[-70.587158, -33.442901],
[-70.587158, -33.426283],
[-70.590591, -33.414248],
[-70.594711, -33.406224],
[-70.603637, -33.399918]
]]);
var options = {tolerance: 0.01, highQuality: false};
var simplified = turf.simplify(geojson, options);
//addToMap
var addToMap = [geojson, simplified]
```
Returns **[GeoJSON][3]** a simplified GeoJSON
[1]: https://tools.ietf.org/html/rfc7946#section-3
[2]: http://mourner.github.io/simplify-js/
[3]: https://tools.ietf.org/html/rfc7946#section-3
[4]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object
[5]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number
[6]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean
<!-- This file is automatically generated. Please don't edit it directly:
if you find an error, edit the source file (likely index.js), and re-run
./scripts/generate-readmes in the turf project. -->
---
This module is part of the [Turfjs project](http://turfjs.org/), an open source
module collection dedicated to geographic algorithms. It is maintained in the
[Turfjs/turf](https://github.com/Turfjs/turf) repository, where you can create
PRs and issues.
### Installation
Install this module individually:
```sh
$ npm install @turf/simplify
```
Or install the Turf module that includes it as a function:
```sh
$ npm install @turf/turf
```

View File

@ -0,0 +1,67 @@
import fs from 'fs';
import path from 'path';
import load from 'load-json-file';
import Benchmark from 'benchmark';
import simplify from './';
const directory = path.join(__dirname, 'test', 'in') + path.sep;
const fixtures = fs.readdirSync(directory).map(filename => {
return {
name: path.parse(filename).name,
geojson: load.sync(directory + filename)
};
});
/**
* Single Process Benchmark
*
* argentina: 4.695ms
* featurecollection: 1.647ms
* fiji-hiQ: 0.461ms
* geometrycollection: 3.332ms
* linestring: 0.460ms
* multilinestring: 0.657ms
* multipoint: 0.193ms
* multipolygon: 6.108ms
* point: 0.032ms
* poly-issue#555-5: 4.956ms
* polygon: 0.675ms
* simple-polygon: 2.735ms
*/
for (const {name, geojson} of fixtures) {
let {tolerance, highQuality} = geojson.properties || {};
tolerance = tolerance || 0.01;
highQuality = highQuality || false;
console.time(name);
simplify(geojson, tolerance, highQuality);
console.timeEnd(name);
}
/**
* Benchmark Results
*
* argentina x 13,380 ops/sec ±4.31% (72 runs sampled)
* featurecollection x 4,709 ops/sec ±2.24% (76 runs sampled)
* fiji-hiQ x 41,197 ops/sec ±1.96% (80 runs sampled)
* geometrycollection x 4,690 ops/sec ±2.25% (78 runs sampled)
* linestring x 29,737 ops/sec ±2.26% (77 runs sampled)
* multilinestring x 20,530 ops/sec ±2.08% (77 runs sampled)
* multipoint x 394,980 ops/sec ±2.35% (77 runs sampled)
* multipolygon x 809 ops/sec ±3.32% (70 runs sampled)
* point x 5,157,027 ops/sec ±8.79% (72 runs sampled)
* poly-issue#555-5 x 1,816 ops/sec ±2.43% (66 runs sampled)
* polygon x 2,996 ops/sec ±2.85% (74 runs sampled)
* simple-polygon x 369 ops/sec ±7.55% (66 runs sampled)
*/
const suite = new Benchmark.Suite('turf-transform-simplify');
for (const {name, geojson} of fixtures) {
let {tolerance, highQuality} = geojson.properties || {};
tolerance = tolerance || 0.01;
highQuality = highQuality || false;
suite.add(name, () => simplify(geojson, tolerance, highQuality));
}
suite
.on('cycle', e => console.log(String(e.target)))
.on('complete', () => {})
.run();

13
lib/turf-simplify/index.d.ts vendored Normal file
View File

@ -0,0 +1,13 @@
import { AllGeoJSON } from '@turf/helpers'
/**
* http://turfjs.org/docs/#simplify
*/
export default function simplify<T extends AllGeoJSON>(
geojson: T,
options?: {
tolerance?: number,
highQuality?: boolean,
mutate?: boolean
}
): T;

175
lib/turf-simplify/index.js Normal file
View File

@ -0,0 +1,175 @@
import cleanCoords from '@turf/clean-coords';
import clone from '@turf/clone';
import { geomEach } from '@turf/meta';
import { isObject } from '@turf/helpers';
import simplifyJS from './lib/simplify';
/**
* Takes a {@link GeoJSON} object and returns a simplified version. Internally uses
* [simplify-js](http://mourner.github.io/simplify-js/) to perform simplification using the Ramer-Douglas-Peucker algorithm.
*
* @name simplify
* @param {GeoJSON} geojson object to be simplified
* @param {Object} [options={}] Optional parameters
* @param {number} [options.tolerance=1] simplification tolerance
* @param {boolean} [options.highQuality=false] whether or not to spend more time to create a higher-quality simplification with a different algorithm
* @param {boolean} [options.mutate=false] allows GeoJSON input to be mutated (significant performance increase if true)
* @returns {GeoJSON} a simplified GeoJSON
* @example
* var geojson = turf.polygon([[
* [-70.603637, -33.399918],
* [-70.614624, -33.395332],
* [-70.639343, -33.392466],
* [-70.659942, -33.394759],
* [-70.683975, -33.404504],
* [-70.697021, -33.419406],
* [-70.701141, -33.434306],
* [-70.700454, -33.446339],
* [-70.694274, -33.458369],
* [-70.682601, -33.465816],
* [-70.668869, -33.472117],
* [-70.646209, -33.473835],
* [-70.624923, -33.472117],
* [-70.609817, -33.468107],
* [-70.595397, -33.458369],
* [-70.587158, -33.442901],
* [-70.587158, -33.426283],
* [-70.590591, -33.414248],
* [-70.594711, -33.406224],
* [-70.603637, -33.399918]
* ]]);
* var options = {tolerance: 0.01, highQuality: false};
* var simplified = turf.simplify(geojson, options);
*
* //addToMap
* var addToMap = [geojson, simplified]
*/
function simplify(geojson, options) {
// Optional parameters
options = options || {};
if (!isObject(options)) throw new Error('options is invalid');
var tolerance = options.tolerance !== undefined ? options.tolerance : 1;
var highQuality = options.highQuality || false;
var mutate = options.mutate || false;
if (!geojson) throw new Error('geojson is required');
if (tolerance && tolerance < 0) throw new Error('invalid tolerance');
// Clone geojson to avoid side effects
if (mutate !== true) geojson = clone(geojson);
geomEach(geojson, function (geom) {
simplifyGeom(geom, tolerance, highQuality);
});
return geojson;
}
/**
* Simplifies a feature's coordinates
*
* @private
* @param {Geometry} geometry to be simplified
* @param {number} [tolerance=1] simplification tolerance
* @param {boolean} [highQuality=false] whether or not to spend more time to create a higher-quality simplification with a different algorithm
* @returns {Geometry} output
*/
function simplifyGeom(geometry, tolerance, highQuality) {
var type = geometry.type;
// "unsimplyfiable" geometry types
if (type === 'Point' || type === 'MultiPoint') return geometry;
// Remove any extra coordinates
cleanCoords(geometry, true);
var coordinates = geometry.coordinates;
switch (type) {
case 'LineString':
geometry['coordinates'] = simplifyLine(coordinates, tolerance, highQuality);
break;
case 'MultiLineString':
geometry['coordinates'] = coordinates.map(function (lines) {
return simplifyLine(lines, tolerance, highQuality);
});
break;
case 'Polygon':
geometry['coordinates'] = simplifyPolygon(coordinates, tolerance, highQuality);
break;
case 'MultiPolygon':
geometry['coordinates'] = coordinates.map(function (rings) {
return simplifyPolygon(rings, tolerance, highQuality);
});
}
return geometry;
}
/**
* Simplifies the coordinates of a LineString with simplify-js
*
* @private
* @param {Array<number>} coordinates to be processed
* @param {number} tolerance simplification tolerance
* @param {boolean} highQuality whether or not to spend more time to create a higher-quality
* @returns {Array<Array<number>>} simplified coords
*/
function simplifyLine(coordinates, tolerance, highQuality) {
return simplifyJS(coordinates.map(function (coord) {
return {x: coord[0], y: coord[1], z: coord[2]};
}), tolerance, highQuality).map(function (coords) {
return (coords.z) ? [coords.x, coords.y, coords.z] : [coords.x, coords.y];
});
}
/**
* Simplifies the coordinates of a Polygon with simplify-js
*
* @private
* @param {Array<number>} coordinates to be processed
* @param {number} tolerance simplification tolerance
* @param {boolean} highQuality whether or not to spend more time to create a higher-quality
* @returns {Array<Array<Array<number>>>} simplified coords
*/
function simplifyPolygon(coordinates, tolerance, highQuality) {
return coordinates.map(function (ring) {
var pts = ring.map(function (coord) {
return {x: coord[0], y: coord[1]};
});
if (pts.length < 4) {
throw new Error('invalid polygon');
}
var simpleRing = simplifyJS(pts, tolerance, highQuality).map(function (coords) {
return [coords.x, coords.y];
});
//remove 1 percent of tolerance until enough points to make a triangle
while (!checkValidity(simpleRing)) {
tolerance -= tolerance * 0.01;
simpleRing = simplifyJS(pts, tolerance, highQuality).map(function (coords) {
return [coords.x, coords.y];
});
}
if (
(simpleRing[simpleRing.length - 1][0] !== simpleRing[0][0]) ||
(simpleRing[simpleRing.length - 1][1] !== simpleRing[0][1])) {
simpleRing.push(simpleRing[0]);
}
return simpleRing;
});
}
/**
* Returns true if ring has at least 3 coordinates and its first coordinate is the same as its last
*
* @private
* @param {Array<number>} ring coordinates to be checked
* @returns {boolean} true if valid
*/
function checkValidity(ring) {
if (ring.length < 3) return false;
//if the last point is the same as the first, it's not a triangle
return !(ring.length === 3 && ((ring[2][0] === ring[0][0]) && (ring[2][1] === ring[0][1])));
}
export default simplify;

View File

@ -0,0 +1,111 @@
/*
(c) 2013, Vladimir Agafonkin
Simplify.js, a high-performance JS polyline simplification library
mourner.github.io/simplify-js
*/
// to suit your point format, run search/replace for '.x' and '.y';
// for 3D version, see 3d branch (configurability would draw significant performance overhead)
// square distance between 2 points
function getSqDist(p1, p2) {
var dx = p1.x - p2.x,
dy = p1.y - p2.y;
return dx * dx + dy * dy;
}
// square distance from a point to a segment
function getSqSegDist(p, p1, p2) {
var x = p1.x,
y = p1.y,
dx = p2.x - x,
dy = p2.y - y;
if (dx !== 0 || dy !== 0) {
var t = ((p.x - x) * dx + (p.y - y) * dy) / (dx * dx + dy * dy);
if (t > 1) {
x = p2.x;
y = p2.y;
} else if (t > 0) {
x += dx * t;
y += dy * t;
}
}
dx = p.x - x;
dy = p.y - y;
return dx * dx + dy * dy;
}
// rest of the code doesn't care about point format
// basic distance-based simplification
function simplifyRadialDist(points, sqTolerance) {
var prevPoint = points[0],
newPoints = [prevPoint],
point;
for (var i = 1, len = points.length; i < len; i++) {
point = points[i];
if (getSqDist(point, prevPoint) > sqTolerance) {
newPoints.push(point);
prevPoint = point;
}
}
if (prevPoint !== point) newPoints.push(point);
return newPoints;
}
function simplifyDPStep(points, first, last, sqTolerance, simplified) {
var maxSqDist = sqTolerance,
index;
for (var i = first + 1; i < last; i++) {
var sqDist = getSqSegDist(points[i], points[first], points[last]);
if (sqDist > maxSqDist) {
index = i;
maxSqDist = sqDist;
}
}
if (maxSqDist > sqTolerance) {
if (index - first > 1) simplifyDPStep(points, first, index, sqTolerance, simplified);
simplified.push(points[index]);
if (last - index > 1) simplifyDPStep(points, index, last, sqTolerance, simplified);
}
}
// simplification using Ramer-Douglas-Peucker algorithm
function simplifyDouglasPeucker(points, sqTolerance) {
var last = points.length - 1;
var simplified = [points[0]];
simplifyDPStep(points, 0, last, sqTolerance, simplified);
simplified.push(points[last]);
return simplified;
}
// both algorithms combined for awesome performance
export default function simplify(points, tolerance, highestQuality) {
if (points.length <= 2) return points;
var sqTolerance = tolerance !== undefined ? tolerance * tolerance : 1;
points = highestQuality ? points : simplifyRadialDist(points, sqTolerance);
points = simplifyDouglasPeucker(points, sqTolerance);
return points;
}

View File

@ -0,0 +1,63 @@
{
"name": "@turf/simplify",
"version": "5.1.5",
"description": "turf simplify module",
"main": "main.js",
"module": "main.es.js",
"types": "index.d.ts",
"files": [
"index.js",
"index.d.ts",
"main.js",
"lib",
"main.es.js"
],
"scripts": {
"pretest": "rollup -c ../../rollup.config.js",
"test": "node -r @std/esm test.js",
"posttest": "node -r @std/esm ../../scripts/validate-es5-dependencies.js",
"bench": "node -r @std/esm bench.js",
"docs": "node ../../scripts/generate-readmes"
},
"repository": {
"type": "git",
"url": "git://github.com/Turfjs/turf.git"
},
"keywords": [
"turf",
"gis",
"simplify",
"Ramer-Douglas-Peucker",
"algorithm",
"peucker"
],
"author": "Turf Authors",
"contributors": [
"Vladimir Agafonkin <@mourner>",
"Stefano Borghi <@stebogit>"
],
"license": "MIT",
"bugs": {
"url": "https://github.com/Turfjs/turf/issues"
},
"homepage": "https://github.com/Turfjs/turf",
"devDependencies": {
"@std/esm": "*",
"@turf/truncate": "6.x",
"benchmark": "*",
"load-json-file": "*",
"rollup": "*",
"tape": "*",
"write-json-file": "*"
},
"dependencies": {
"@turf/clean-coords": "^5.1.5",
"@turf/clone": "6.x",
"@turf/helpers": "6.x",
"@turf/meta": "6.x"
},
"@std/esm": {
"esm": "js",
"cjs": true
}
}

86
lib/turf-simplify/test.js Normal file
View File

@ -0,0 +1,86 @@
import fs from 'fs';
import test from 'tape';
import path from 'path';
import load from 'load-json-file';
import write from 'write-json-file';
import truncate from '@turf/truncate';
import { polygon, multiPolygon } from '@turf/helpers';
import simplify from '.';
const directories = {
in: path.join(__dirname, 'test', 'in') + path.sep,
out: path.join(__dirname, 'test', 'out') + path.sep
};
let fixtures = fs.readdirSync(directories.in).map(filename => {
return {
filename,
name: path.parse(filename).name,
geojson: load.sync(directories.in + filename)
};
});
// fixtures = fixtures.filter(({name}) => name.includes('#555'));
test('simplify', t => {
for (const {filename, name, geojson} of fixtures) {
let {tolerance, highQuality} = geojson.properties || {};
tolerance = tolerance || 0.01;
highQuality = highQuality || false;
const simplified = truncate(simplify(geojson, {
tolerance: tolerance,
highQuality: highQuality
}));
if (process.env.REGEN) write.sync(directories.out + filename, simplified);
t.deepEqual(simplified, load.sync(directories.out + filename), name);
}
t.end();
});
test('simplify -- throw', t => {
const poly = polygon([[[0, 0], [2, 2], [2, 0], [0, 0]]]);
t.throws(() => simplify(null), /geojson is required/, 'missing geojson');
t.throws(() => simplify(poly, {tolerance: -1}), /invalid tolerance/, 'negative tolerance');
t.end();
});
test('simplify -- removes ID & BBox from properties', t => {
const properties = {foo: 'bar'};
const id = 12345;
const bbox = [0, 0, 2, 2];
const poly = polygon([[[0, 0], [2, 2], [2, 0], [0, 0]]], properties, {bbox, id});
const simple = simplify(poly, {tolerance: 0.1});
t.equal(simple.id, id);
t.deepEqual(simple.bbox, bbox);
t.deepEqual(simple.properties, properties);
t.end();
});
test('simplify -- issue #555', t => {
// polygons from issue #555
const poly1 = polygon([[[-75.693254, 45.431144], [-75.693335, 45.431109], [-75.693335, 45.431109], [-75.693254, 45.431144]]]);
const poly2 = polygon([[[-75.627178, 45.438106], [-75.627179, 45.438106], [-75.62718, 45.438106], [-75.627178, 45.438106]]]);
const poly3 = polygon([[[-75.684722, 45.410083], [-75.684641, 45.409989], [-75.684641, 45.409989], [-75.684722, 45.410083], [-75.684722, 45.410083]]]);
const poly4 = polygon([[[-75.885634, 45.272762], [-75.885482, 45.272641], [-75.885554, 45.272596], [-75.885534, 45.272581], [-75.885581, 45.272551], [-75.885703, 45.272647], [-75.885706, 45.272645], [-75.885709, 45.272647], [-75.885767, 45.272693], [-75.885759, 45.272698], [-75.885716, 45.272728], [-75.885716, 45.272728], [-75.885712, 45.272731], [-75.885712, 45.272731], [-75.885708, 45.272734], [-75.885684, 45.272749], [-75.885671, 45.272739], [-75.885634, 45.272762]], [[-75.885708, 45.27273], [-75.885708, 45.272729], [-75.885708, 45.272729], [-75.885708, 45.27273]]]);
const options = {tolerance: 0.000001, highQuality: true};
t.throws(() => simplify(poly1, options), /invalid polygon/);
t.throws(() => simplify(poly2, options), /invalid polygon/);
t.throws(() => simplify(poly3, options), /invalid polygon/);
t.throws(() => simplify(poly4, options), /invalid polygon/);
t.end();
});
test('simplify -- issue #918', t => {
// simplify hangs on this input #918
t.throws(() => simplify(multiPolygon([[[[0, 90], [0, 90], [0, 90], [0, 90], [0, 90], [0, 90], [0, 90], [0, 90], [0, 90], [0, 90], [0, 90]]]])), /invalid polygon/, 'invalid polygon');
t.throws(() => simplify(multiPolygon([[[[0, 1], [0, 2], [0, 3], [0, 2.5], [0, 1]]]])), /invalid polygon/, 'invalid polygon');
t.throws(() => simplify(multiPolygon([[[[0, 1], [0, 1], [1, 2], [0, 1]]]])), /invalid polygon/, 'invalid polygon');
t.end();
});

View File

@ -0,0 +1,455 @@
{
"type": "Feature",
"id": "ARG",
"properties": {
"tolerance": 0.1,
"name": "Argentina"
},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
-64.964892,
-22.075862
],
[
-64.377021,
-22.798091
],
[
-63.986838,
-21.993644
],
[
-62.846468,
-22.034985
],
[
-62.685057,
-22.249029
],
[
-60.846565,
-23.880713
],
[
-60.028966,
-24.032796
],
[
-58.807128,
-24.771459
],
[
-57.777217,
-25.16234
],
[
-57.63366,
-25.603657
],
[
-58.618174,
-27.123719
],
[
-57.60976,
-27.395899
],
[
-56.486702,
-27.548499
],
[
-55.695846,
-27.387837
],
[
-54.788795,
-26.621786
],
[
-54.625291,
-25.739255
],
[
-54.13005,
-25.547639
],
[
-53.628349,
-26.124865
],
[
-53.648735,
-26.923473
],
[
-54.490725,
-27.474757
],
[
-55.162286,
-27.881915
],
[
-56.2909,
-28.852761
],
[
-57.625133,
-30.216295
],
[
-57.874937,
-31.016556
],
[
-58.14244,
-32.044504
],
[
-58.132648,
-33.040567
],
[
-58.349611,
-33.263189
],
[
-58.427074,
-33.909454
],
[
-58.495442,
-34.43149
],
[
-57.22583,
-35.288027
],
[
-57.362359,
-35.97739
],
[
-56.737487,
-36.413126
],
[
-56.788285,
-36.901572
],
[
-57.749157,
-38.183871
],
[
-59.231857,
-38.72022
],
[
-61.237445,
-38.928425
],
[
-62.335957,
-38.827707
],
[
-62.125763,
-39.424105
],
[
-62.330531,
-40.172586
],
[
-62.145994,
-40.676897
],
[
-62.745803,
-41.028761
],
[
-63.770495,
-41.166789
],
[
-64.73209,
-40.802677
],
[
-65.118035,
-41.064315
],
[
-64.978561,
-42.058001
],
[
-64.303408,
-42.359016
],
[
-63.755948,
-42.043687
],
[
-63.458059,
-42.563138
],
[
-64.378804,
-42.873558
],
[
-65.181804,
-43.495381
],
[
-65.328823,
-44.501366
],
[
-65.565269,
-45.036786
],
[
-66.509966,
-45.039628
],
[
-67.293794,
-45.551896
],
[
-67.580546,
-46.301773
],
[
-66.597066,
-47.033925
],
[
-65.641027,
-47.236135
],
[
-65.985088,
-48.133289
],
[
-67.166179,
-48.697337
],
[
-67.816088,
-49.869669
],
[
-68.728745,
-50.264218
],
[
-69.138539,
-50.73251
],
[
-68.815561,
-51.771104
],
[
-68.149995,
-52.349983
],
[
-68.571545,
-52.299444
],
[
-69.498362,
-52.142761
],
[
-71.914804,
-52.009022
],
[
-72.329404,
-51.425956
],
[
-72.309974,
-50.67701
],
[
-72.975747,
-50.74145
],
[
-73.328051,
-50.378785
],
[
-73.415436,
-49.318436
],
[
-72.648247,
-48.878618
],
[
-72.331161,
-48.244238
],
[
-72.447355,
-47.738533
],
[
-71.917258,
-46.884838
],
[
-71.552009,
-45.560733
],
[
-71.659316,
-44.973689
],
[
-71.222779,
-44.784243
],
[
-71.329801,
-44.407522
],
[
-71.793623,
-44.207172
],
[
-71.464056,
-43.787611
],
[
-71.915424,
-43.408565
],
[
-72.148898,
-42.254888
],
[
-71.746804,
-42.051386
],
[
-71.915734,
-40.832339
],
[
-71.680761,
-39.808164
],
[
-71.413517,
-38.916022
],
[
-70.814664,
-38.552995
],
[
-71.118625,
-37.576827
],
[
-71.121881,
-36.658124
],
[
-70.364769,
-36.005089
],
[
-70.388049,
-35.169688
],
[
-69.817309,
-34.193571
],
[
-69.814777,
-33.273886
],
[
-70.074399,
-33.09121
],
[
-70.535069,
-31.36501
],
[
-69.919008,
-30.336339
],
[
-70.01355,
-29.367923
],
[
-69.65613,
-28.459141
],
[
-69.001235,
-27.521214
],
[
-68.295542,
-26.89934
],
[
-68.5948,
-26.506909
],
[
-68.386001,
-26.185016
],
[
-68.417653,
-24.518555
],
[
-67.328443,
-24.025303
],
[
-66.985234,
-22.986349
],
[
-67.106674,
-22.735925
],
[
-66.273339,
-21.83231
],
[
-64.964892,
-22.075862
]
]
]
}
}

View File

@ -0,0 +1,388 @@
{
"type": "FeatureCollection",
"properties": {
"tolerance": 0.01
},
"features": [
{
"type": "Feature",
"properties": {
"id": 1
},
"geometry": {
"type": "LineString",
"coordinates": [
[
27.977542877197266,
-26.17500493262446
],
[
27.975482940673828,
-26.17870225771557
],
[
27.969818115234375,
-26.177931991326645
],
[
27.967071533203125,
-26.177623883345735
],
[
27.966899871826172,
-26.1810130263384
],
[
27.967758178710938,
-26.1853263385099
],
[
27.97290802001953,
-26.1853263385099
],
[
27.97496795654297,
-26.18270756087535
],
[
27.97840118408203,
-26.1810130263384
],
[
27.98011779785156,
-26.183323749143113
],
[
27.98011779785156,
-26.18655868408986
],
[
27.978744506835938,
-26.18933141398614
],
[
27.97496795654297,
-26.19025564262006
],
[
27.97119140625,
-26.19040968001282
],
[
27.969303131103516,
-26.1899475672235
],
[
27.96741485595703,
-26.189639491012183
],
[
27.9656982421875,
-26.187945057286793
],
[
27.965354919433594,
-26.18563442612686
],
[
27.96432495117187,
-26.183015655416536
]
]
}
},
{
"type": "Feature",
"properties": {
"id": 2
},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
27.972049713134762,
-26.199035448897074
],
[
27.9741096496582,
-26.196108920345292
],
[
27.977371215820312,
-26.197495179879635
],
[
27.978572845458984,
-26.20042167359348
],
[
27.980976104736328,
-26.200729721284862
],
[
27.982349395751953,
-26.197803235312957
],
[
27.982177734375,
-26.194414580727656
],
[
27.982177734375,
-26.19256618212382
],
[
27.98406600952148,
-26.192258112838022
],
[
27.985267639160156,
-26.191950042737417
],
[
27.986125946044922,
-26.19426054863105
],
[
27.986984252929688,
-26.196416979445644
],
[
27.987327575683594,
-26.198881422912123
],
[
27.98715591430664,
-26.201345814222698
],
[
27.985095977783203,
-26.20381015337393
],
[
27.983036041259766,
-26.20550435628209
],
[
27.979946136474606,
-26.20550435628209
],
[
27.97719955444336,
-26.20488828535003
],
[
27.97445297241211,
-26.203656133705152
],
[
27.972564697265625,
-26.201961903900578
],
[
27.972049713134762,
-26.199035448897074
]
]
]
}
},
{
"type": "Feature",
"properties": {
"id": 3
},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
27.946643829345703,
-26.170845301716803
],
[
27.94269561767578,
-26.183631842055114
],
[
27.935657501220703,
-26.183323749143113
],
[
27.92741775512695,
-26.17685360983018
],
[
27.926902770996094,
-26.171153427614488
],
[
27.928619384765625,
-26.165298896316028
],
[
27.936859130859375,
-26.161292995018652
],
[
27.94509887695312,
-26.158981835530525
],
[
27.950420379638672,
-26.161601146157146
],
[
27.951793670654297,
-26.166223315536712
],
[
27.954025268554688,
-26.173464345889972
],
[
27.954025268554688,
-26.179626570662702
],
[
27.951278686523438,
-26.187945057286793
],
[
27.944583892822266,
-26.19395248382672
],
[
27.936172485351562,
-26.194876675795218
],
[
27.930850982666016,
-26.19379845111899
],
[
27.925701141357422,
-26.190563717201886
],
[
27.92278289794922,
-26.18655868408986
],
[
27.92072296142578,
-26.180858976522302
],
[
27.917118072509766,
-26.174080583026957
],
[
27.916603088378906,
-26.16683959094609
],
[
27.917118072509766,
-26.162987816205614
],
[
27.920207977294922,
-26.162987816205614
],
[
27.920894622802734,
-26.166069246175482
],
[
27.9217529296875,
-26.17146155269785
],
[
27.923297882080078,
-26.177469829049862
],
[
27.92673110961914,
-26.184248025435295
],
[
27.930335998535156,
-26.18856121785662
],
[
27.936687469482422,
-26.18871525748988
],
[
27.942352294921875,
-26.187945057286793
],
[
27.94647216796875,
-26.184248025435295
],
[
27.946815490722653,
-26.178548204845022
],
[
27.946643829345703,
-26.170845301716803
]
],
[
[
27.936859130859375,
-26.16591517661071
],
[
27.934799194335938,
-26.16945872510008
],
[
27.93497085571289,
-26.173926524048102
],
[
27.93874740600586,
-26.175621161617432
],
[
27.94149398803711,
-26.17007498340995
],
[
27.94321060180664,
-26.166223315536712
],
[
27.939090728759762,
-26.164528541367826
],
[
27.937545776367188,
-26.16406632595636
],
[
27.936859130859375,
-26.16591517661071
]
]
]
}
},
{
"type": "Feature",
"properties": {
"id": 4
},
"geometry": {
"type": "Point",
"coordinates": [
27.95642852783203,
-26.152510345365126
]
}
}
]
}

View File

@ -0,0 +1,258 @@
{
"type": "Feature",
"properties": {
"tolerance": 0.005,
"highQuality": true
},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
179.97528076171875,
-16.514770282237
],
[
179.97665405273438,
-16.519707611417825
],
[
179.97390747070312,
-16.523986527973733
],
[
179.98043060302734,
-16.539126548282127
],
[
179.985237121582,
-16.536822708755626
],
[
179.98695373535156,
-16.531227555400562
],
[
179.99073028564453,
-16.531556686558297
],
[
180.00205993652344,
-16.525632239869275
],
[
180.00686645507812,
-16.525961380565427
],
[
180.01029968261716,
-16.523328239288848
],
[
180.01304626464844,
-16.524644814414863
],
[
180.01235961914062,
-16.526619660274722
],
[
180.00995635986328,
-16.52694879928784
],
[
180.00823974609372,
-16.532873205577378
],
[
180.00755310058594,
-16.534847967269407
],
[
180.01819610595703,
-16.539126548282127
],
[
180.02334594726562,
-16.537810071920884
],
[
180.02437591552734,
-16.534189715617043
],
[
180.03707885742188,
-16.534189715617043
],
[
180.04188537597656,
-16.526619660274722
],
[
180.0487518310547,
-16.52826534972986
],
[
180.0497817993164,
-16.525632239869275
],
[
180.054931640625,
-16.52727793773992
],
[
180.05939483642578,
-16.52497395679397
],
[
180.06145477294922,
-16.525632239869275
],
[
180.06488800048825,
-16.515757758166256
],
[
180.0666046142578,
-16.513124477808333
],
[
180.0655746459961,
-16.5108203280625
],
[
180.06454467773438,
-16.507528637922594
],
[
180.05596160888672,
-16.490410945973114
],
[
180.0542449951172,
-16.485802077854263
],
[
180.0494384765625,
-16.484814448981634
],
[
180.04669189453125,
-16.482839176122972
],
[
180.04634857177734,
-16.479547009916406
],
[
180.05390167236328,
-16.47460865568325
],
[
180.05596160888672,
-16.47526711018803
],
[
180.0597381591797,
-16.470987115907786
],
[
180.0600814819336,
-16.467365508451035
],
[
180.06282806396482,
-16.46110984528612
],
[
180.07347106933594,
-16.455183241385555
],
[
180.07930755615232,
-16.45057353538345
],
[
180.08686065673828,
-16.44761009512282
],
[
180.08411407470703,
-16.441353794870704
],
[
180.06832122802734,
-16.437402343465862
],
[
180.05561828613278,
-16.439707366557357
],
[
180.04806518554688,
-16.448597913571174
],
[
180.0398254394531,
-16.45057353538345
],
[
180.02609252929688,
-16.46473156961583
],
[
180.02094268798828,
-16.4624268437789
],
[
180.01441955566406,
-16.464073079315213
],
[
180.00961303710935,
-16.468682464447188
],
[
180.00446319580078,
-16.476584012483762
],
[
179.99725341796875,
-16.48250996202084
],
[
179.99553680419922,
-16.487118908513903
],
[
179.99176025390625,
-16.48975254296043
],
[
179.99038696289062,
-16.49271533887906
],
[
179.9883270263672,
-16.49403212250543
],
[
179.98661041259763,
-16.50226181712924
],
[
179.98111724853516,
-16.50489524545779
],
[
179.97940063476562,
-16.50719946582597
],
[
179.97528076171875,
-16.514770282237
]
]
]
}
}

View File

@ -0,0 +1,364 @@
{
"type": "GeometryCollection",
"properties": {
"tolerance": 0.01
},
"geometries": [
{
"type": "LineString",
"coordinates": [
[
27.977542877197266,
-26.17500493262446
],
[
27.975482940673828,
-26.17870225771557
],
[
27.969818115234375,
-26.177931991326645
],
[
27.967071533203125,
-26.177623883345735
],
[
27.966899871826172,
-26.1810130263384
],
[
27.967758178710938,
-26.1853263385099
],
[
27.97290802001953,
-26.1853263385099
],
[
27.97496795654297,
-26.18270756087535
],
[
27.97840118408203,
-26.1810130263384
],
[
27.98011779785156,
-26.183323749143113
],
[
27.98011779785156,
-26.18655868408986
],
[
27.978744506835938,
-26.18933141398614
],
[
27.97496795654297,
-26.19025564262006
],
[
27.97119140625,
-26.19040968001282
],
[
27.969303131103516,
-26.1899475672235
],
[
27.96741485595703,
-26.189639491012183
],
[
27.9656982421875,
-26.187945057286793
],
[
27.965354919433594,
-26.18563442612686
],
[
27.96432495117187,
-26.183015655416536
]
]
},
{
"type": "Polygon",
"coordinates": [
[
[
27.972049713134762,
-26.199035448897074
],
[
27.9741096496582,
-26.196108920345292
],
[
27.977371215820312,
-26.197495179879635
],
[
27.978572845458984,
-26.20042167359348
],
[
27.980976104736328,
-26.200729721284862
],
[
27.982349395751953,
-26.197803235312957
],
[
27.982177734375,
-26.194414580727656
],
[
27.982177734375,
-26.19256618212382
],
[
27.98406600952148,
-26.192258112838022
],
[
27.985267639160156,
-26.191950042737417
],
[
27.986125946044922,
-26.19426054863105
],
[
27.986984252929688,
-26.196416979445644
],
[
27.987327575683594,
-26.198881422912123
],
[
27.98715591430664,
-26.201345814222698
],
[
27.985095977783203,
-26.20381015337393
],
[
27.983036041259766,
-26.20550435628209
],
[
27.979946136474606,
-26.20550435628209
],
[
27.97719955444336,
-26.20488828535003
],
[
27.97445297241211,
-26.203656133705152
],
[
27.972564697265625,
-26.201961903900578
],
[
27.972049713134762,
-26.199035448897074
]
]
]
},
{
"type": "Polygon",
"coordinates": [
[
[
27.946643829345703,
-26.170845301716803
],
[
27.94269561767578,
-26.183631842055114
],
[
27.935657501220703,
-26.183323749143113
],
[
27.92741775512695,
-26.17685360983018
],
[
27.926902770996094,
-26.171153427614488
],
[
27.928619384765625,
-26.165298896316028
],
[
27.936859130859375,
-26.161292995018652
],
[
27.94509887695312,
-26.158981835530525
],
[
27.950420379638672,
-26.161601146157146
],
[
27.951793670654297,
-26.166223315536712
],
[
27.954025268554688,
-26.173464345889972
],
[
27.954025268554688,
-26.179626570662702
],
[
27.951278686523438,
-26.187945057286793
],
[
27.944583892822266,
-26.19395248382672
],
[
27.936172485351562,
-26.194876675795218
],
[
27.930850982666016,
-26.19379845111899
],
[
27.925701141357422,
-26.190563717201886
],
[
27.92278289794922,
-26.18655868408986
],
[
27.92072296142578,
-26.180858976522302
],
[
27.917118072509766,
-26.174080583026957
],
[
27.916603088378906,
-26.16683959094609
],
[
27.917118072509766,
-26.162987816205614
],
[
27.920207977294922,
-26.162987816205614
],
[
27.920894622802734,
-26.166069246175482
],
[
27.9217529296875,
-26.17146155269785
],
[
27.923297882080078,
-26.177469829049862
],
[
27.92673110961914,
-26.184248025435295
],
[
27.930335998535156,
-26.18856121785662
],
[
27.936687469482422,
-26.18871525748988
],
[
27.942352294921875,
-26.187945057286793
],
[
27.94647216796875,
-26.184248025435295
],
[
27.946815490722653,
-26.178548204845022
],
[
27.946643829345703,
-26.170845301716803
]
],
[
[
27.936859130859375,
-26.16591517661071
],
[
27.934799194335938,
-26.16945872510008
],
[
27.93497085571289,
-26.173926524048102
],
[
27.93874740600586,
-26.175621161617432
],
[
27.94149398803711,
-26.17007498340995
],
[
27.94321060180664,
-26.166223315536712
],
[
27.939090728759762,
-26.164528541367826
],
[
27.937545776367188,
-26.16406632595636
],
[
27.936859130859375,
-26.16591517661071
]
]
]
},
{
"type": "Point",
"coordinates": [
27.95642852783203,
-26.152510345365126
]
}
]
}

View File

@ -0,0 +1,91 @@
{
"type": "Feature",
"properties": {},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
-70.603637,
-33.399918
],
[
-70.614624,
-33.395332
],
[
-70.639343,
-33.392466
],
[
-70.659942,
-33.394759
],
[
-70.683975,
-33.404504
],
[
-70.697021,
-33.419406
],
[
-70.701141,
-33.434306
],
[
-70.700454,
-33.446339
],
[
-70.694274,
-33.458369
],
[
-70.682601,
-33.465816
],
[
-70.668869,
-33.472117
],
[
-70.646209,
-33.473835
],
[
-70.624923,
-33.472117
],
[
-70.609817,
-33.468107
],
[
-70.595397,
-33.458369
],
[
-70.587158,
-33.442901
],
[
-70.587158,
-33.426283
],
[
-70.590591,
-33.414248
],
[
-70.594711,
-33.406224
],
[
-70.603637,
-33.399918
]
]
]
}
}

View File

@ -0,0 +1,329 @@
{
"type": "Feature",
"properties": {},
"geometry": {
"type": "LineString",
"coordinates": [
[
-80.51399230957031,
28.069556808283608
],
[
-80.51193237304688,
28.057438520876673
],
[
-80.49819946289062,
28.05622661698537
],
[
-80.5023193359375,
28.04471284867091
],
[
-80.48583984375,
28.042288740362853
],
[
-80.50575256347656,
28.028349057505775
],
[
-80.50163269042969,
28.02168161433489
],
[
-80.49476623535156,
28.021075462659883
],
[
-80.48652648925781,
28.021075462659883
],
[
-80.47691345214844,
28.021075462659883
],
[
-80.46936035156249,
28.015619944017807
],
[
-80.47760009765624,
28.007133032319448
],
[
-80.49201965332031,
27.998039170620494
],
[
-80.46730041503906,
27.962262536875905
],
[
-80.46524047851562,
27.91980029694533
],
[
-80.40550231933594,
27.930114089618602
],
[
-80.39657592773438,
27.980455528671527
],
[
-80.41305541992188,
27.982274659104082
],
[
-80.42953491210938,
27.990763528690582
],
[
-80.4144287109375,
28.00955793247135
],
[
-80.3594970703125,
27.972572275562527
],
[
-80.36224365234375,
27.948919060105453
],
[
-80.38215637207031,
27.913732900444284
],
[
-80.41786193847656,
27.881570017022806
],
[
-80.40550231933594,
27.860932192608534
],
[
-80.39382934570312,
27.85425440786446
],
[
-80.37803649902344,
27.86336037597851
],
[
-80.38215637207031,
27.880963078302393
],
[
-80.36842346191405,
27.888246118437756
],
[
-80.35743713378906,
27.882176952341734
],
[
-80.35469055175781,
27.86882358965466
],
[
-80.3594970703125,
27.8421119273228
],
[
-80.37940979003906,
27.83300417483936
],
[
-80.39932250976561,
27.82511017099003
],
[
-80.40069580078125,
27.79352841586229
],
[
-80.36155700683594,
27.786846483587688
],
[
-80.35537719726562,
27.794743268514615
],
[
-80.36705017089844,
27.800209937418252
],
[
-80.36889553070068,
27.801918215058347
],
[
-80.3690242767334,
27.803930152059845
],
[
-80.36713600158691,
27.805942051806845
],
[
-80.36584854125977,
27.805524490772143
],
[
-80.36563396453857,
27.80465140342285
],
[
-80.36619186401367,
27.803095012921272
],
[
-80.36623477935791,
27.801842292177923
],
[
-80.36524772644043,
27.80127286888392
],
[
-80.36224365234375,
27.801158983867033
],
[
-80.36065578460693,
27.802639479776524
],
[
-80.36138534545898,
27.803740348273823
],
[
-80.36220073699951,
27.804803245204976
],
[
-80.36190032958984,
27.806625330038287
],
[
-80.3609561920166,
27.80742248254359
],
[
-80.35932540893555,
27.806853088493792
],
[
-80.35889625549315,
27.806321651354835
],
[
-80.35902500152588,
27.805448570411585
],
[
-80.35863876342773,
27.804461600896783
],
[
-80.35739421844482,
27.804461600896783
],
[
-80.35700798034668,
27.805334689771293
],
[
-80.35696506500244,
27.80673920932572
],
[
-80.35726547241211,
27.80772615814989
],
[
-80.35808086395264,
27.808295547623707
],
[
-80.3585958480835,
27.80928248230861
],
[
-80.35653591156006,
27.80943431761813
],
[
-80.35572052001953,
27.808637179875486
],
[
-80.3555917739868,
27.80772615814989
],
[
-80.3555917739868,
27.806055931810487
],
[
-80.35572052001953,
27.803778309057556
],
[
-80.35537719726562,
27.801804330717825
],
[
-80.3554630279541,
27.799564581098746
],
[
-80.35670757293701,
27.799564581098746
],
[
-80.35499095916748,
27.796831264786892
],
[
-80.34610748291016,
27.79478123244122
],
[
-80.34404754638672,
27.802070060660014
],
[
-80.34748077392578,
27.804955086774896
],
[
-80.3433609008789,
27.805790211616266
],
[
-80.34353256225586,
27.8101555324401
],
[
-80.33499240875244,
27.810079615315917
],
[
-80.33383369445801,
27.805676331334084
],
[
-80.33022880554199,
27.801652484744796
],
[
-80.32872676849365,
27.80848534345178
]
]
}
}

View File

@ -0,0 +1,413 @@
{
"type": "Feature",
"properties": {},
"geometry": {
"type": "MultiLineString",
"coordinates": [
[
[
-80.51399230957031,
28.069556808283608
],
[
-80.51193237304688,
28.057438520876673
],
[
-80.49819946289062,
28.05622661698537
],
[
-80.5023193359375,
28.04471284867091
],
[
-80.48583984375,
28.042288740362853
],
[
-80.50575256347656,
28.028349057505775
],
[
-80.50163269042969,
28.02168161433489
],
[
-80.49476623535156,
28.021075462659883
],
[
-80.48652648925781,
28.021075462659883
],
[
-80.47691345214844,
28.021075462659883
],
[
-80.46936035156249,
28.015619944017807
],
[
-80.47760009765624,
28.007133032319448
],
[
-80.49201965332031,
27.998039170620494
],
[
-80.46730041503906,
27.962262536875905
],
[
-80.46524047851562,
27.91980029694533
],
[
-80.40550231933594,
27.930114089618602
],
[
-80.39657592773438,
27.980455528671527
],
[
-80.41305541992188,
27.982274659104082
],
[
-80.42953491210938,
27.990763528690582
],
[
-80.4144287109375,
28.00955793247135
],
[
-80.3594970703125,
27.972572275562527
],
[
-80.36224365234375,
27.948919060105453
],
[
-80.38215637207031,
27.913732900444284
],
[
-80.41786193847656,
27.881570017022806
],
[
-80.40550231933594,
27.860932192608534
],
[
-80.39382934570312,
27.85425440786446
],
[
-80.37803649902344,
27.86336037597851
],
[
-80.38215637207031,
27.880963078302393
],
[
-80.36842346191405,
27.888246118437756
],
[
-80.35743713378906,
27.882176952341734
],
[
-80.35469055175781,
27.86882358965466
],
[
-80.3594970703125,
27.8421119273228
],
[
-80.37940979003906,
27.83300417483936
],
[
-80.39932250976561,
27.82511017099003
],
[
-80.40069580078125,
27.79352841586229
],
[
-80.36155700683594,
27.786846483587688
],
[
-80.35537719726562,
27.794743268514615
],
[
-80.36705017089844,
27.800209937418252
],
[
-80.36889553070068,
27.801918215058347
],
[
-80.3690242767334,
27.803930152059845
],
[
-80.36713600158691,
27.805942051806845
],
[
-80.36584854125977,
27.805524490772143
],
[
-80.36563396453857,
27.80465140342285
],
[
-80.36619186401367,
27.803095012921272
],
[
-80.36623477935791,
27.801842292177923
],
[
-80.36524772644043,
27.80127286888392
],
[
-80.36224365234375,
27.801158983867033
],
[
-80.36065578460693,
27.802639479776524
],
[
-80.36138534545898,
27.803740348273823
],
[
-80.36220073699951,
27.804803245204976
],
[
-80.36190032958984,
27.806625330038287
],
[
-80.3609561920166,
27.80742248254359
],
[
-80.35932540893555,
27.806853088493792
],
[
-80.35889625549315,
27.806321651354835
],
[
-80.35902500152588,
27.805448570411585
],
[
-80.35863876342773,
27.804461600896783
],
[
-80.35739421844482,
27.804461600896783
],
[
-80.35700798034668,
27.805334689771293
],
[
-80.35696506500244,
27.80673920932572
],
[
-80.35726547241211,
27.80772615814989
],
[
-80.35808086395264,
27.808295547623707
],
[
-80.3585958480835,
27.80928248230861
],
[
-80.35653591156006,
27.80943431761813
],
[
-80.35572052001953,
27.808637179875486
],
[
-80.3555917739868,
27.80772615814989
],
[
-80.3555917739868,
27.806055931810487
],
[
-80.35572052001953,
27.803778309057556
],
[
-80.35537719726562,
27.801804330717825
],
[
-80.3554630279541,
27.799564581098746
],
[
-80.35670757293701,
27.799564581098746
],
[
-80.35499095916748,
27.796831264786892
],
[
-80.34610748291016,
27.79478123244122
],
[
-80.34404754638672,
27.802070060660014
],
[
-80.34748077392578,
27.804955086774896
],
[
-80.3433609008789,
27.805790211616266
],
[
-80.34353256225586,
27.8101555324401
],
[
-80.33499240875244,
27.810079615315917
],
[
-80.33383369445801,
27.805676331334084
],
[
-80.33022880554199,
27.801652484744796
],
[
-80.32872676849365,
27.80848534345178
]
],
[
[
-80.51193237304688,
28.091366281406945
],
[
-80.47760009765624,
28.074403740607135
],
[
-80.47210693359375,
28.058650411105386
],
[
-80.46936035156249,
28.01016414897993
],
[
-80.45425415039061,
27.99682659773872
],
[
-80.44464111328125,
28.02956127552927
],
[
-80.43228149414062,
28.024712321517228
],
[
-80.40069580078125,
28.01743848094423
],
[
-80.3704833984375,
28.004101830368654
],
[
-80.35537719726562,
27.991976169784156
],
[
-80.3485107421875,
27.947099367319762
],
[
-80.32379150390625,
27.937393821330247
],
[
-80.34027099609375,
27.879142241732627
],
[
-80.35263061523436,
27.90948552034696
],
[
-80.36773681640625,
27.858503954841247
],
[
-80.34027099609375,
27.822073862795612
],
[
-80.29220581054688,
27.853647316127383
],
[
-80.30319213867188,
27.860932192608534
],
[
-80.30319213867188,
27.88278388425912
],
[
-80.2935791015625,
27.894921808206057
]
]
]
}
}

View File

@ -0,0 +1,11 @@
{
"type": "Feature",
"properties": {},
"geometry": {
"type": "MultiPoint",
"coordinates":[[
0,
0
],[ 1,2]]
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,11 @@
{
"type": "Feature",
"properties": {},
"geometry": {
"type": "Point",
"coordinates": [
5,
1
]
}
}

View File

@ -0,0 +1,183 @@
{
"type": "Feature",
"properties": {
"tolerance": 0.00005
},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
-75.788024,
45.345283
],
[
-75.788012,
45.345262
],
[
-75.787966,
45.345274
],
[
-75.787959,
45.345262
],
[
-75.787947,
45.345266
],
[
-75.787931,
45.345237
],
[
-75.787943,
45.345234
],
[
-75.787928,
45.345207
],
[
-75.787999,
45.345187
],
[
-75.787975,
45.345143
],
[
-75.787906,
45.345162
],
[
-75.7879,
45.345151
],
[
-75.787897,
45.345152
],
[
-75.787882,
45.345125
],
[
-75.787872,
45.345128
],
[
-75.787855,
45.345099
],
[
-75.787866,
45.345096
],
[
-75.787862,
45.345088
],
[
-75.787855,
45.34509
],
[
-75.787832,
45.345086
],
[
-75.787825,
45.345069
],
[
-75.787842,
45.345056
],
[
-75.787867,
45.34506
],
[
-75.787872,
45.345081
],
[
-75.787903,
45.345073
],
[
-75.787897,
45.345052
],
[
-75.787913,
45.345048
],
[
-75.78792,
45.345059
],
[
-75.787928,
45.345056
],
[
-75.787928,
45.345055
],
[
-75.788023,
45.345028
],
[
-75.78814,
45.345236
],
[
-75.788044,
45.345263
],
[
-75.788043,
45.345262
],
[
-75.78804,
45.345263
],
[
-75.788032,
45.345265
],
[
-75.78804,
45.345279
],
[
-75.788024,
45.345283
]
],
[
[
-75.787933,
45.345065
],
[
-75.78793,
45.34506
],
[
-75.78793,
45.345066
],
[
-75.787933,
45.345065
]
]
]
}
}

View File

@ -0,0 +1,734 @@
{
"type": "Feature",
"properties": {
"tolerance": 1,
"elevation": 25
},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
-75.51527029981442,
39.11245
],
[
-75.39282224024916,
39.12823474024917
],
[
-75.3770375,
39.135447305104925
],
[
-75.35235519043113,
39.13713230956888
],
[
-75.34721355956887,
39.13713230956888
],
[
-75.32253125,
39.139083755473514
],
[
-75.29670096335326,
39.141125963353275
],
[
-75.29326540004632,
39.14171584995367
],
[
-75.268025,
39.14408623760705
],
[
-75.25277832507136,
39.15170957507138
],
[
-75.24515498760704,
39.166956250000005
],
[
-75.23985410433178,
39.1932916043318
],
[
-75.23985410433178,
39.19512714566821
],
[
-75.23607469121049,
39.2214625
],
[
-75.23324391324394,
39.24118766324395
],
[
-75.23324391324394,
39.25624358675606
],
[
-75.23104443417348,
39.27596875
],
[
-75.22621125895654,
39.28866125895655
],
[
-75.21351874999999,
39.30405720540773
],
[
-75.19590688693847,
39.31286313693849
],
[
-75.18710095540773,
39.33047500000001
],
[
-75.18476066926435,
39.35622316926436
],
[
-75.18476066926435,
39.359233080735656
],
[
-75.1827803677246,
39.38498125
],
[
-75.18108292305178,
39.407051673051775
],
[
-75.18108292305178,
39.41741707694823
],
[
-75.17961177196392,
39.439487500000006
],
[
-75.17842510611122,
39.4589001061112
],
[
-75.17842510611122,
39.474581143888805
],
[
-75.1773677140917,
39.49399375
],
[
-75.17806096906195,
39.513042219061944
],
[
-75.17806096906195,
39.52945153093805
],
[
-75.17880864635877,
39.548500000000004
],
[
-75.17436569692443,
39.56385319692442
],
[
-75.1590125,
39.57861883514683
],
[
-75.14275422343123,
39.586747973431216
],
[
-75.13462508514682,
39.60300625000001
],
[
-75.13199158752832,
39.630027162471684
],
[
-75.13192154096123,
39.63042154096124
],
[
-75.12971192190646,
39.6575125
],
[
-75.12958254641065,
39.68258879641065
],
[
-75.12958254641065,
39.68694245358936
],
[
-75.12945449224796,
39.712018750000006
],
[
-75.13075282512311,
39.73826532512311
],
[
-75.13075282512311,
39.74027842487689
],
[
-75.13219370977114,
39.766525
],
[
-75.13492951020307,
39.79060798979694
],
[
-75.13711471606355,
39.799133466063545
],
[
-75.14033360353974,
39.821031250000004
],
[
-75.1408737447648,
39.839170005235225
],
[
-75.14206588619443,
39.85859088619443
],
[
-75.14260248550531,
39.87553750000001
],
[
-75.14807249033687,
39.88647750966314
],
[
-75.1590125,
39.8919475144947
],
[
-75.17435420501783,
39.89087920501784
],
[
-75.20237093707816,
39.886685312921855
],
[
-75.21351874999999,
39.88578343964871
],
[
-75.22299781995783,
39.88501656995784
],
[
-75.26614108689465,
39.87742141310536
],
[
-75.268025,
39.877239581040996
],
[
-75.26957725960418,
39.87708975960419
],
[
-75.27684240189953,
39.87553750000001
],
[
-75.28419540106952,
39.85936709893049
],
[
-75.29112392832597,
39.84413017832599
],
[
-75.30162746500874,
39.821031250000004
],
[
-75.30816161875036,
39.806661618750354
],
[
-75.32253125,
39.77506054072003
],
[
-75.32519930917472,
39.76919305917473
],
[
-75.32641252811797,
39.766525
],
[
-75.3296491997708,
39.75940705022919
],
[
-75.34223699959911,
39.73172449959911
],
[
-75.35119759122719,
39.712018750000006
],
[
-75.36046052535204,
39.69544177535203
],
[
-75.3754130206531,
39.659136979346904
],
[
-75.37616437518106,
39.6575125
],
[
-75.3766762492428,
39.65715124924281
],
[
-75.3770375,
39.65615200822954
],
[
-75.39832547007784,
39.62429422007785
],
[
-75.4082395514723,
39.60300625000001
],
[
-75.4215797545908,
39.5930422545908
],
[
-75.43154375,
39.56834216367474
],
[
-75.45835566060614,
39.57531191060614
],
[
-75.45895426960922,
39.5755957303908
],
[
-75.48605,
39.57947734440668
],
[
-75.48898805047145,
39.60006819952855
],
[
-75.48994051537133,
39.60300625
],
[
-75.49123821601205,
39.60819446601205
],
[
-75.49220788576012,
39.651354614239885
],
[
-75.49509104207014,
39.6575125
],
[
-75.50305100880664,
39.67451350880663
],
[
-75.50416029911807,
39.69390845088193
],
[
-75.52933401544658,
39.70079651544659
],
[
-75.54055625,
39.707797525000004
],
[
-75.5417414003631,
39.71083359963691
],
[
-75.54210361986804,
39.71201875000001
],
[
-75.5424789600527,
39.71394146005272
],
[
-75.5438968233805,
39.76318442661949
],
[
-75.54488896795854,
39.766525
],
[
-75.54664835702378,
39.77261710702379
],
[
-75.54776976280363,
39.81381773719638
],
[
-75.55227698676161,
39.821031250000004
],
[
-75.56289470095811,
39.84336970095812
],
[
-75.56358754189749,
39.852506208102504
],
[
-75.57539756961809,
39.8558725696181
],
[
-75.59506249999998,
39.868174228685255
],
[
-75.59931300492002,
39.871286995079984
],
[
-75.60432992735852,
39.87553750000001
],
[
-75.63504292712292,
39.89006332287709
],
[
-75.64956874999999,
39.89284139354837
],
[
-75.66838020678718,
39.89434895678719
],
[
-75.68308195946902,
39.896530540530996
],
[
-75.704075,
39.89798053092993
],
[
-75.72818318448331,
39.89964568448332
],
[
-75.73375331940231,
39.9003654305977
],
[
-75.75858125,
39.901872157624666
],
[
-75.78514101585267,
39.90348398414733
],
[
-75.78652773414733,
39.90348398414733
],
[
-75.8130875,
39.904921352207175
],
[
-75.83722610887358,
39.905905141126446
],
[
-75.84345514112644,
39.905905141126446
],
[
-75.86759375,
39.906814783587755
],
[
-75.88844527239183,
39.89638902239184
],
[
-75.89887103358774,
39.87553750000001
],
[
-75.89854841478977,
39.85198591478977
],
[
-75.89854841478977,
39.84458283521024
],
[
-75.89821670830216,
39.821031250000004
],
[
-75.89787552465965,
39.79680677465965
],
[
-75.89787552465965,
39.79074947534036
],
[
-75.89752445181962,
39.766525
],
[
-75.89716305350223,
39.74158805350222
],
[
-75.89716305350223,
39.73695569649778
],
[
-75.89679086738143,
39.712018750000006
],
[
-75.89640740311208,
39.686326153112084
],
[
-75.89640740311208,
39.683205096887924
],
[
-75.89601214017446,
39.6575125
],
[
-75.89560452551711,
39.63101702551712
],
[
-75.89560452551711,
39.6295017244829
],
[
-75.8951839709748,
39.60300625000001
],
[
-75.89475288239396,
39.57584711760604
],
[
-75.8947466163539,
39.57565286635391
],
[
-75.89430149673764,
39.548500000000004
],
[
-75.89387073552223,
39.52222301447779
],
[
-75.89380341704393,
39.520203417043916
],
[
-75.8933591950366,
39.49399375
],
[
-75.89292978011362,
39.468657719886366
],
[
-75.89279284789451,
39.46468659789453
],
[
-75.89235076838531,
39.439487500000006
],
[
-75.8913260472361,
39.4157552027639
],
[
-75.89062746202809,
39.408014962028105
],
[
-75.88953890003162,
39.38498125
],
[
-75.88715925199065,
39.365415748009355
],
[
-75.88127062628152,
39.34415187628153
],
[
-75.87907248368842,
39.33047500000001
],
[
-75.87748307496805,
39.32058567503195
],
[
-75.86759375,
39.29476457315633
],
[
-75.85538716547042,
39.288175334529576
],
[
-75.8282870350059,
39.275968750000004
],
[
-75.8173286270748,
39.27172762292521
],
[
-75.8130875,
39.25578472660005
],
[
-75.79794874486377,
39.236601255136236
],
[
-75.79760439720079,
39.2214625
],
[
-75.7676722437337,
39.2123715062663
],
[
-75.75858125,
39.21117295929072
],
[
-75.74836987958975,
39.21125112958973
],
[
-75.7137522708571,
39.21178522914291
],
[
-75.704075,
39.21186046264999
],
[
-75.67996146438593,
39.19734896438593
],
[
-75.66694581884633,
39.20408543115368
],
[
-75.67566107970288,
39.193048579702875
],
[
-75.67054949218115,
39.166956250000005
],
[
-75.6635559114541,
39.15296908854591
],
[
-75.64956874999999,
39.145975507818854
],
[
-75.62914609464218,
39.14653359464219
],
[
-75.61467186011258,
39.14734688988742
],
[
-75.5950625,
39.14791373192817
],
[
-75.57631446045869,
39.148208210458705
],
[
-75.5587435012753,
39.148768998724705
],
[
-75.54055625,
39.14906393405724
],
[
-75.52104203854152,
39.13196421145847
],
[
-75.51527029981442,
39.11245
]
]
]
}
}

View File

@ -0,0 +1,325 @@
{
"type": "Feature",
"properties": {
"tolerance": 100
},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
26.148429528000065,
-28.29755210099995
],
[
26.148582685000065,
-28.29778390599995
],
[
26.149207731000047,
-28.29773837299996
],
[
26.14925541100007,
-28.297771688999944
],
[
26.149255844000038,
-28.297773261999964
],
[
26.149276505000046,
-28.29784835099997
],
[
26.14928482700003,
-28.29787859399994
],
[
26.14928916200006,
-28.29800647199994
],
[
26.14931069800008,
-28.298641791999955
],
[
26.149339971000074,
-28.298641232999955
],
[
26.151298488000066,
-28.29860385099994
],
[
26.151290002000053,
-28.298628995999934
],
[
26.151417002000073,
-28.299308003999954
],
[
26.15159000400007,
-28.299739003999946
],
[
26.151951998000072,
-28.30051100299994
],
[
26.15206407200003,
-28.30076885099993
],
[
26.152066543000046,
-28.30077453499996
],
[
26.151987021000025,
-28.300799009999935
],
[
26.149896693000073,
-28.301442350999935
],
[
26.150354333000053,
-28.30260575099993
],
[
26.14914131000006,
-28.302975170999957
],
[
26.14836387300005,
-28.302853868999932
],
[
26.147575408000023,
-28.30269948399996
],
[
26.146257624000043,
-28.302462392999928
],
[
26.14557943400007,
-28.302181192999967
],
[
26.145492669000078,
-28.302154609999945
],
[
26.144921243000056,
-28.303395982999973
],
[
26.14482272200007,
-28.30455853999996
],
[
26.14431040900007,
-28.30451913099995
],
[
26.14429070400007,
-28.304144747999942
],
[
26.143837504000032,
-28.304144747999942
],
[
26.143613499000026,
-28.304592757999956
],
[
26.14346312200007,
-28.304893512999968
],
[
26.143260178000048,
-28.304893512999968
],
[
26.143246374000057,
-28.304893512999968
],
[
26.143147852000027,
-28.304893512999968
],
[
26.14295080900007,
-28.304834399999947
],
[
26.14200500000004,
-28.30449942699994
],
[
26.14198529600003,
-28.304420608999976
],
[
26.141525339000054,
-28.304298579999966
],
[
26.141019783000047,
-28.30416445299994
],
[
26.141118305000077,
-28.304637356999933
],
[
26.140940966000073,
-28.30512996599998
],
[
26.140376789000072,
-28.306172836999963
],
[
26.140476282000066,
-28.30621363399996
],
[
26.14041675800007,
-28.306326533999936
],
[
26.140146555000058,
-28.30640398099996
],
[
26.140073975000064,
-28.306410747999962
],
[
26.137315367000042,
-28.305189078999945
],
[
26.136645419000047,
-28.304854104999947
],
[
26.135719315000074,
-28.30451913099995
],
[
26.135515376000058,
-28.304330879999952
],
[
26.13546315800005,
-28.304282678999982
],
[
26.13558800000004,
-28.30419999999998
],
[
26.137463000000025,
-28.30242899999996
],
[
26.13794500000006,
-28.30202799999995
],
[
26.13796479100006,
-28.30201049699997
],
[
26.13798299700005,
-28.302025000999947
],
[
26.139450004000025,
-28.30074499999995
],
[
26.141302000000053,
-28.29914199999996
],
[
26.141913997000074,
-28.29862600399997
],
[
26.14212216900006,
-28.29845037299998
],
[
26.144304360000035,
-28.296499429999983
],
[
26.144799071000023,
-28.29614006399993
],
[
26.145209090000037,
-28.295759748999956
],
[
26.145465732000048,
-28.295507246999932
],
[
26.14575028200005,
-28.295352539999953
],
[
26.14589208800004,
-28.295275441999934
],
[
26.146584820000044,
-28.295135245999973
],
[
26.146587504000024,
-28.295134702999974
],
[
26.146827588000065,
-28.295606591999956
],
[
26.14685742000006,
-28.29565372899998
],
[
26.14691261200005,
-28.29574093599996
],
[
26.147077344000024,
-28.296001226999977
],
[
26.147117344000037,
-28.296041226999932
],
[
26.147907966000048,
-28.29696016899993
],
[
26.147913396000035,
-28.296966331999954
],
[
26.148429528000065,
-28.29755210099995
]
]
]
}
}

View File

@ -0,0 +1,419 @@
{
"type": "Feature",
"id": "ARG",
"properties": {
"tolerance": 0.1,
"name": "Argentina"
},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
-64.964892,
-22.075862
],
[
-64.377021,
-22.798091
],
[
-63.986838,
-21.993644
],
[
-62.846468,
-22.034985
],
[
-60.846565,
-23.880713
],
[
-60.028966,
-24.032796
],
[
-58.807128,
-24.771459
],
[
-57.777217,
-25.16234
],
[
-57.63366,
-25.603657
],
[
-58.618174,
-27.123719
],
[
-56.486702,
-27.548499
],
[
-55.695846,
-27.387837
],
[
-54.788795,
-26.621786
],
[
-54.625291,
-25.739255
],
[
-54.13005,
-25.547639
],
[
-53.628349,
-26.124865
],
[
-53.648735,
-26.923473
],
[
-55.162286,
-27.881915
],
[
-57.625133,
-30.216295
],
[
-58.14244,
-32.044504
],
[
-58.132648,
-33.040567
],
[
-58.349611,
-33.263189
],
[
-58.495442,
-34.43149
],
[
-57.22583,
-35.288027
],
[
-57.362359,
-35.97739
],
[
-56.737487,
-36.413126
],
[
-56.788285,
-36.901572
],
[
-57.749157,
-38.183871
],
[
-59.231857,
-38.72022
],
[
-61.237445,
-38.928425
],
[
-62.335957,
-38.827707
],
[
-62.125763,
-39.424105
],
[
-62.330531,
-40.172586
],
[
-62.145994,
-40.676897
],
[
-62.745803,
-41.028761
],
[
-63.770495,
-41.166789
],
[
-64.73209,
-40.802677
],
[
-65.118035,
-41.064315
],
[
-64.978561,
-42.058001
],
[
-64.303408,
-42.359016
],
[
-63.755948,
-42.043687
],
[
-63.458059,
-42.563138
],
[
-64.378804,
-42.873558
],
[
-65.181804,
-43.495381
],
[
-65.328823,
-44.501366
],
[
-65.565269,
-45.036786
],
[
-66.509966,
-45.039628
],
[
-67.293794,
-45.551896
],
[
-67.580546,
-46.301773
],
[
-66.597066,
-47.033925
],
[
-65.641027,
-47.236135
],
[
-65.985088,
-48.133289
],
[
-67.166179,
-48.697337
],
[
-67.816088,
-49.869669
],
[
-68.728745,
-50.264218
],
[
-69.138539,
-50.73251
],
[
-68.815561,
-51.771104
],
[
-68.149995,
-52.349983
],
[
-71.914804,
-52.009022
],
[
-72.329404,
-51.425956
],
[
-72.309974,
-50.67701
],
[
-72.975747,
-50.74145
],
[
-73.328051,
-50.378785
],
[
-73.415436,
-49.318436
],
[
-72.648247,
-48.878618
],
[
-72.331161,
-48.244238
],
[
-72.447355,
-47.738533
],
[
-71.917258,
-46.884838
],
[
-71.552009,
-45.560733
],
[
-71.659316,
-44.973689
],
[
-71.222779,
-44.784243
],
[
-71.329801,
-44.407522
],
[
-71.793623,
-44.207172
],
[
-71.464056,
-43.787611
],
[
-71.915424,
-43.408565
],
[
-72.148898,
-42.254888
],
[
-71.746804,
-42.051386
],
[
-71.915734,
-40.832339
],
[
-71.413517,
-38.916022
],
[
-70.814664,
-38.552995
],
[
-71.118625,
-37.576827
],
[
-71.121881,
-36.658124
],
[
-70.364769,
-36.005089
],
[
-70.388049,
-35.169688
],
[
-69.817309,
-34.193571
],
[
-69.814777,
-33.273886
],
[
-70.074399,
-33.09121
],
[
-70.535069,
-31.36501
],
[
-69.919008,
-30.336339
],
[
-70.01355,
-29.367923
],
[
-69.65613,
-28.459141
],
[
-69.001235,
-27.521214
],
[
-68.295542,
-26.89934
],
[
-68.5948,
-26.506909
],
[
-68.386001,
-26.185016
],
[
-68.417653,
-24.518555
],
[
-67.328443,
-24.025303
],
[
-66.985234,
-22.986349
],
[
-67.106674,
-22.735925
],
[
-66.273339,
-21.83231
],
[
-64.964892,
-22.075862
]
]
]
}
}

View File

@ -0,0 +1,136 @@
{
"type": "FeatureCollection",
"properties": {
"tolerance": 0.01
},
"features": [
{
"type": "Feature",
"properties": {
"id": 1
},
"geometry": {
"type": "LineString",
"coordinates": [
[
27.977543,
-26.175005
],
[
27.964325,
-26.183016
]
]
}
},
{
"type": "Feature",
"properties": {
"id": 2
},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
27.97205,
-26.199035
],
[
27.984066,
-26.192258
],
[
27.987156,
-26.201346
],
[
27.97205,
-26.199035
]
]
]
}
},
{
"type": "Feature",
"properties": {
"id": 3
},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
27.946644,
-26.170845
],
[
27.942696,
-26.183632
],
[
27.928619,
-26.165299
],
[
27.945099,
-26.158982
],
[
27.954025,
-26.173464
],
[
27.936172,
-26.194877
],
[
27.916603,
-26.16684
],
[
27.930336,
-26.188561
],
[
27.946644,
-26.170845
]
],
[
[
27.936859,
-26.165915
],
[
27.934971,
-26.173927
],
[
27.941494,
-26.170075
],
[
27.936859,
-26.165915
]
]
]
}
},
{
"type": "Feature",
"properties": {
"id": 4
},
"geometry": {
"type": "Point",
"coordinates": [
27.956429,
-26.15251
]
}
}
]
}

View File

@ -0,0 +1,70 @@
{
"type": "Feature",
"properties": {
"tolerance": 0.005,
"highQuality": true
},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
179.975281,
-16.51477
],
[
179.980431,
-16.539127
],
[
180.0103,
-16.523328
],
[
180.007553,
-16.534848
],
[
180.018196,
-16.539127
],
[
180.061455,
-16.525632
],
[
180.066605,
-16.513124
],
[
180.046349,
-16.479547
],
[
180.086861,
-16.44761
],
[
180.084114,
-16.441354
],
[
180.055618,
-16.439707
],
[
180.026093,
-16.464732
],
[
180.01442,
-16.464073
],
[
179.975281,
-16.51477
]
]
]
}
}

View File

@ -0,0 +1,109 @@
{
"type": "GeometryCollection",
"geometries": [
{
"type": "LineString",
"coordinates": [
[
27.977543,
-26.175005
],
[
27.964325,
-26.183016
]
]
},
{
"type": "Polygon",
"coordinates": [
[
[
27.97205,
-26.199035
],
[
27.984066,
-26.192258
],
[
27.987156,
-26.201346
],
[
27.97205,
-26.199035
]
]
]
},
{
"type": "Polygon",
"coordinates": [
[
[
27.946644,
-26.170845
],
[
27.942696,
-26.183632
],
[
27.928619,
-26.165299
],
[
27.945099,
-26.158982
],
[
27.954025,
-26.173464
],
[
27.936172,
-26.194877
],
[
27.916603,
-26.16684
],
[
27.930336,
-26.188561
],
[
27.946644,
-26.170845
]
],
[
[
27.936859,
-26.165915
],
[
27.934971,
-26.173927
],
[
27.941494,
-26.170075
],
[
27.936859,
-26.165915
]
]
]
},
{
"type": "Point",
"coordinates": [
27.956429,
-26.15251
]
}
]
}

View File

@ -0,0 +1,43 @@
{
"type": "Feature",
"properties": {},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
-70.603637,
-33.399918
],
[
-70.683975,
-33.404504
],
[
-70.701141,
-33.434306
],
[
-70.694274,
-33.458369
],
[
-70.668869,
-33.472117
],
[
-70.609817,
-33.468107
],
[
-70.587158,
-33.442901
],
[
-70.603637,
-33.399918
]
]
]
}
}

View File

@ -0,0 +1,105 @@
{
"type": "Feature",
"properties": {},
"geometry": {
"type": "LineString",
"coordinates": [
[
-80.513992,
28.069557
],
[
-80.48584,
28.042289
],
[
-80.505753,
28.028349
],
[
-80.476913,
28.021075
],
[
-80.49202,
27.998039
],
[
-80.4673,
27.962263
],
[
-80.46524,
27.9198
],
[
-80.405502,
27.930114
],
[
-80.396576,
27.980456
],
[
-80.429535,
27.990764
],
[
-80.414429,
28.009558
],
[
-80.359497,
27.972572
],
[
-80.382156,
27.913733
],
[
-80.417862,
27.88157
],
[
-80.393829,
27.854254
],
[
-80.368423,
27.888246
],
[
-80.354691,
27.868824
],
[
-80.359497,
27.842112
],
[
-80.399323,
27.82511
],
[
-80.400696,
27.793528
],
[
-80.361557,
27.786846
],
[
-80.359325,
27.806853
],
[
-80.354991,
27.796831
],
[
-80.328727,
27.808485
]
]
}
}

View File

@ -0,0 +1,169 @@
{
"type": "Feature",
"properties": {},
"geometry": {
"type": "MultiLineString",
"coordinates": [
[
[
-80.513992,
28.069557
],
[
-80.48584,
28.042289
],
[
-80.505753,
28.028349
],
[
-80.476913,
28.021075
],
[
-80.49202,
27.998039
],
[
-80.4673,
27.962263
],
[
-80.46524,
27.9198
],
[
-80.405502,
27.930114
],
[
-80.396576,
27.980456
],
[
-80.429535,
27.990764
],
[
-80.414429,
28.009558
],
[
-80.359497,
27.972572
],
[
-80.382156,
27.913733
],
[
-80.417862,
27.88157
],
[
-80.393829,
27.854254
],
[
-80.368423,
27.888246
],
[
-80.354691,
27.868824
],
[
-80.359497,
27.842112
],
[
-80.399323,
27.82511
],
[
-80.400696,
27.793528
],
[
-80.361557,
27.786846
],
[
-80.359325,
27.806853
],
[
-80.354991,
27.796831
],
[
-80.328727,
27.808485
]
],
[
[
-80.511932,
28.091366
],
[
-80.4776,
28.074404
],
[
-80.46936,
28.010164
],
[
-80.454254,
27.996827
],
[
-80.444641,
28.029561
],
[
-80.355377,
27.991976
],
[
-80.348511,
27.947099
],
[
-80.323792,
27.937394
],
[
-80.340271,
27.879142
],
[
-80.352631,
27.909486
],
[
-80.367737,
27.858504
],
[
-80.340271,
27.822074
],
[
-80.292206,
27.853647
],
[
-80.303192,
27.860932
],
[
-80.293579,
27.894922
]
]
]
}
}

View File

@ -0,0 +1,17 @@
{
"type": "Feature",
"properties": {},
"geometry": {
"type": "MultiPoint",
"coordinates": [
[
0,
0
],
[
1,
2
]
]
}
}

View File

@ -0,0 +1,88 @@
{
"type": "Feature",
"properties": {
"country": "South Africa",
"tolerance": 0.01
},
"geometry": {
"type": "MultiPolygon",
"coordinates": [
[
[
[
19.41807,
-34.68668
],
[
19.41455,
-34.68997
],
[
19.40993,
-34.68798
],
[
19.41807,
-34.68668
]
]
],
[
[
[
19.4188,
-34.67816
],
[
19.42342,
-34.68024
],
[
19.41508,
-34.68598
],
[
19.4188,
-34.67816
]
]
],
[
[
[
19.45629,
-34.39274
],
[
19.55599,
-34.38974
],
[
19.68811,
-34.76532
],
[
19.67762,
-34.78188
],
[
19.63818,
-34.77916
],
[
19.59412,
-34.73309
],
[
19.49554,
-34.67162
],
[
19.45629,
-34.39274
]
]
]
]
}
}

View File

@ -0,0 +1,11 @@
{
"type": "Feature",
"properties": {},
"geometry": {
"type": "Point",
"coordinates": [
5,
1
]
}
}

View File

@ -0,0 +1,59 @@
{
"type": "Feature",
"properties": {
"tolerance": 0.00005
},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
-75.788024,
45.345283
],
[
-75.787931,
45.345237
],
[
-75.787975,
45.345143
],
[
-75.787855,
45.345099
],
[
-75.788023,
45.345028
],
[
-75.78814,
45.345236
],
[
-75.788024,
45.345283
]
],
[
[
-75.787933,
45.345065
],
[
-75.78793,
45.34506
],
[
-75.78793,
45.345066
],
[
-75.787933,
45.345065
]
]
]
}
}

View File

@ -0,0 +1,30 @@
{
"type": "Feature",
"properties": {
"tolerance": 1,
"elevation": 25
},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
-75.51527,
39.11245
],
[
-75.142602,
39.875538
],
[
-75.813087,
39.904921
],
[
-75.51527,
39.11245
]
]
]
}
}

View File

@ -0,0 +1,29 @@
{
"type": "Feature",
"properties": {
"tolerance": 100
},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
26.14843,
-28.297552
],
[
26.150354,
-28.302606
],
[
26.135463,
-28.304283
],
[
26.14843,
-28.297552
]
]
]
}
}

View File

@ -0,0 +1,11 @@
import {polygon, Feature, Polygon} from '@turf/helpers'
import simplify from './'
const poly = polygon([[[0, 0], [10, 10], [20, 20], [0, 0]]]);
// Output type is the same as Input type
const simple: Feature<Polygon> = simplify(poly);
// Extra params
simplify(poly, {tolerance: 1});
simplify(poly, {tolerance: 1, highQuality: true});

1
lib/wasm-util/README.md Normal file
View File

@ -0,0 +1 @@
Utility function for handling emscripten modules and transfering arrays to and from module memory.

View File

@ -0,0 +1,62 @@
/*
Utility functions to store and load coordinates to and from module memory
Coordinates are assumed to be an array of coordinate pairs ([[x1,y1], [x2,y2], [x3,y3]])
*/
/**
* Allocate memory for coordinates and stores them in a flat representation.
* Returns a pointer to the buffer. The length of the buffer is coords.length * 2
* @param {*} module
* @param {Array} coords - An array of coordinate pairs
*/
export function storeCoords(module, coords) {
const buffer = module._malloc(coords.length * 2 * 8)
const heap = new Float64Array(module.HEAPF64.buffer, buffer, coords.length * 2)
for (let i = 0; i < coords.length; i++) {
heap[2*i] = coords[i][0]
heap[2*i + 1] = coords[i][1]
}
return buffer
}
/**
* Loads coordinates from the memory by the result pointer.
* Frees the resultpointer and the result before returning
* @param {*} module
* @param {*} result - pointer to Uint32 array of length 2. Stores the resultPointer and resultLength
*/
export function loadResultAndFreeMemory(module, result) {
const [resultPointer, resultLength] = new Uint32Array(module.HEAPU32.buffer, result, 2)
const simplified = new Float64Array(module.HEAPF64.buffer, resultPointer, resultLength)
const coords = unflattenCoords(simplified)
module._free(result)
module._free(resultPointer)
return coords
}
/**
* Loads coordinates from the memory by the result pointer without freeing memory.
* For benchmarking purposes
* @param {*} module
* @param {*} result - pointer to Uint32 array of length 2. Stores the resultPointer and resultLength
*/
export function loadResult(module, result) {
const [resultPointer, resultLength] = new Uint32Array(module.HEAPU32.buffer, result, 2)
const simplified = new Float64Array(module.HEAPF64.buffer, resultPointer, resultLength)
return unflattenCoords(simplified)
}
/**
* Transforms a flat array to an array coordinate pairs
* @param {Array} flattened - length must be even
*/
export function unflattenCoords (flattened) {
const coords = []
let x, y
for (let i = 0; i < flattened.length; i += 2) {
x = flattened[i]
y = flattened[i + 1]
coords.push([x, y])
}
return coords
}

View File

@ -0,0 +1,28 @@
/**
* Promisify emscripten modules
*
* idea taken from squoosh app: https://raw.githubusercontent.com/GoogleChromeLabs/squoosh/master/src/codecs/util.ts
*
* usage:
* // create a global variable to store the initialized module once
* let emscriptenModule
*
* // inside an async function:
* // use the global as cache to the module or initialize it
* if (!emscriptenModule) emscriptenModule = initEmscriptenModule(importedGlueCode, urlToWasmFile)
* const module = await emscriptenModule
*/
export function initEmscriptenModule(moduleFactory, wasmUrl) {
return new Promise (resolve => {
const module = moduleFactory({
noInitialRun: true,
locateFile: (url) => wasmUrl ? wasmUrl : url,
onRuntimeInitialized () {
// hack: deleting then breaks an infinite loop
// https://github.com/emscripten-core/emscripten/issues/5820
delete module.then
resolve(module)
}
})
})
}

26
scripts/bundle-size.sh Executable file
View File

@ -0,0 +1,26 @@
#!/usr/bin/env bash
# Prints the size of a file + gzipped size
human_print(){
while read B dummy; do
[ $B -lt 1024 ] && echo ${B} bytes && break
KB=$(((B+512)/1024))
[ $KB -lt 1024 ] && echo ${KB} kilobytes && break
MB=$(((KB+512)/1024))
[ $MB -lt 1024 ] && echo ${MB} megabytes && break
GB=$(((MB+512)/1024))
[ $GB -lt 1024 ] && echo ${GB} gigabytes && break
echo $(((GB+512)/1024)) terabytes
done
}
export FILE_NAME=$1
export UNCOMPRESSED_FILE_SIZE=`wc -c < $FILE_NAME`
export GZIPPED_FILE_SIZE=`gzip -c < $FILE_NAME | wc -c`
echo "Bundle size: $(echo $UNCOMPRESSED_FILE_SIZE | human_print)"
echo "gzipped size: $(echo $GZIPPED_FILE_SIZE | human_print)"
echo
echo "Machine readable:"
echo "BUNDLE_SIZE: $UNCOMPRESSED_FILE_SIZE,$GZIPPED_FILE_SIZE"

Some files were not shown because too many files have changed in this diff Show More