From ed0377b3de14d90f3c807027afd6c8972f68b853 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Rivi=C3=A8re?= Date: Tue, 26 Nov 2024 10:58:57 +0100 Subject: [PATCH 1/5] a volcano test --- package.json | 1 + test/data/volcano.json | 1 + test/snapshots/index.js | 34 +++++++++++++++++++++++++++++----- yarn.lock | 10 +++++++++- 4 files changed, 40 insertions(+), 6 deletions(-) create mode 100644 test/data/volcano.json diff --git a/package.json b/package.json index 4197216..6c63963 100644 --- a/package.json +++ b/package.json @@ -45,6 +45,7 @@ "d3-geo": "3", "d3-polygon": "3", "d3-scale": "4", + "d3-scale-chromatic": "^3.1.0", "d3-selection": "3", "eslint": "8", "htl": "^0.3.1", diff --git a/test/data/volcano.json b/test/data/volcano.json new file mode 100644 index 0000000..270f6c9 --- /dev/null +++ b/test/data/volcano.json @@ -0,0 +1 @@ +{"width":87,"height":61,"values":[103,104,104,105,105,106,106,106,107,107,106,106,105,105,104,104,104,104,105,107,107,106,105,105,107,108,109,110,110,110,110,110,110,109,109,109,109,109,109,108,107,107,107,107,106,106,105,104,104,104,104,104,104,104,103,103,103,103,102,102,101,101,100,100,100,100,100,99,98,97,97,96,96,96,96,96,96,96,95,95,95,94,94,94,94,94,94,104,104,105,105,106,106,107,107,107,107,107,107,107,106,106,106,106,106,106,108,108,108,106,106,108,109,110,110,112,112,113,112,111,110,110,110,110,109,109,109,108,107,107,107,107,106,106,105,104,104,104,104,104,104,104,103,103,103,103,102,102,101,101,100,100,100,100,99,99,98,97,97,96,96,96,96,96,96,96,95,95,95,94,94,94,94,94,104,105,105,106,106,107,107,108,108,108,108,108,108,108,108,108,108,108,108,108,110,110,110,110,110,110,110,111,113,115,116,115,113,112,110,110,110,110,110,110,109,108,108,108,108,107,106,105,105,105,105,105,105,104,104,104,104,103,103,103,102,102,102,101,100,100,100,99,99,98,97,97,96,96,96,96,96,96,96,96,95,95,94,94,94,94,94,105,105,106,106,107,107,108,108,109,109,109,109,109,110,110,110,110,110,110,110,111,112,115,115,115,115,115,116,116,117,119,118,117,116,114,113,112,110,110,110,110,110,110,109,109,108,107,106,106,106,106,106,105,105,105,104,104,104,103,103,103,102,102,102,101,100,100,99,99,98,97,97,96,96,96,96,96,96,96,96,95,95,94,94,94,94,94,105,106,106,107,107,108,108,109,109,110,110,110,110,111,110,110,110,110,111,114,115,116,121,121,121,121,121,122,123,124,124,123,121,119,118,117,115,114,112,111,110,110,110,110,110,110,109,109,108,109,107,107,106,106,105,105,104,104,104,104,103,103,102,102,102,101,100,100,99,99,98,97,96,96,96,96,96,96,96,96,95,95,94,94,94,94,94,106,106,107,107,107,108,109,109,110,110,111,111,112,113,112,111,111,112,115,118,118,119,126,128,128,127,128,128,129,130,129,128,127,125,122,120,118,117,115,114,112,110,110,110,110,110,111,110,110,110,109,109,108,107,106,105,105,105,104,104,104,103,103,102,102,102,101,100,99,99,98,97,96,96,96,96,96,96,96,96,95,95,94,94,94,94,94,106,107,107,108,108,108,109,110,110,111,112,113,114,115,114,115,116,116,119,123,125,130,133,134,134,134,134,135,135,136,135,134,132,130,128,124,121,119,118,116,114,112,111,111,111,112,112,111,110,110,110,109,108,108,107,108,107,106,105,104,104,104,103,103,103,102,101,100,99,99,98,97,96,96,96,96,96,96,96,96,95,95,95,94,94,94,94,107,107,108,108,109,109,110,110,112,113,114,115,116,117,117,120,120,121,123,129,134,136,138,139,139,139,140,142,142,141,141,140,137,134,131,127,124,122,120,118,117,115,113,114,113,114,114,113,112,111,110,110,109,108,107,106,105,105,105,104,104,104,103,103,103,101,100,100,99,99,98,97,96,96,96,96,96,96,96,96,96,95,95,94,94,94,94,107,108,108,109,109,110,111,112,114,115,116,117,118,119,121,125,125,127,131,136,140,141,142,144,144,145,148,149,148,147,146,144,140,138,136,130,127,125,123,121,119,118,117,117,116,116,116,115,114,113,113,111,110,109,108,107,106,105,105,103,103,102,102,102,103,101,100,100,100,99,98,98,97,96,96,96,96,96,96,96,96,95,95,95,94,94,94,107,108,109,109,110,110,110,113,115,117,118,119,120,123,126,129,131,134,139,142,144,145,147,148,150,152,154,154,153,154,151,149,146,143,140,136,130,128,126,124,122,121,120,119,118,117,117,117,116,116,115,113,112,110,109,108,107,106,106,105,104,103,102,101,101,100,100,100,100,99,99,98,97,96,96,96,96,96,96,96,96,95,95,95,94,94,94,107,108,109,109,110,110,110,112,115,117,119,122,125,127,130,133,137,141,143,145,148,149,152,155,157,159,160,160,161,162,159,156,153,149,146,142,139,134,130,128,126,125,122,120,120,120,119,119,119,118,117,115,113,111,110,110,109,108,107,106,106,105,104,104,103,102,100,100,100,99,99,98,97,96,96,96,96,96,96,96,96,95,95,95,95,94,94,108,108,109,109,110,110,110,112,115,118,121,125,128,131,134,138,141,145,147,149,152,157,160,161,163,166,169,170,170,171,168,162,158,155,152,148,144,140,136,132,129,127,124,122,121,120,120,120,120,120,119,117,115,113,110,110,110,110,109,108,108,107,107,106,105,104,102,100,100,100,99,98,97,96,96,96,96,96,96,96,96,96,95,95,95,94,94,108,109,109,110,110,111,112,114,117,120,124,128,131,135,138,142,145,149,152,155,158,163,166,167,170,173,175,175,175,173,171,169,164,160,156,153,149,144,140,136,131,129,126,124,123,123,122,121,120,120,120,119,117,115,111,110,110,110,110,110,109,109,110,109,108,106,103,101,100,100,100,98,97,96,96,96,96,96,96,96,96,96,95,95,95,95,94,108,109,110,110,110,113,114,116,119,122,126,131,134,138,141,145,149,152,156,160,164,169,171,174,177,175,178,179,177,175,174,172,168,163,160,157,151,147,143,138,133,130,128,125,125,124,123,122,121,121,120,120,118,116,115,111,110,110,110,110,113,114,113,112,110,107,105,102,100,100,100,98,97,96,96,96,96,96,96,96,96,96,96,95,95,95,94,108,109,110,110,112,115,116,118,122,125,129,133,137,140,144,149,152,157,161,165,169,173,176,179,179,180,180,180,178,178,176,175,171,165,163,160,153,148,143,139,135,132,129,128,127,125,124,124,123,123,122,122,120,118,117,118,115,117,118,118,119,117,116,115,112,109,107,105,100,100,100,100,97,96,96,96,96,96,96,96,96,96,96,95,95,95,95,108,109,110,111,114,116,118,122,127,130,133,136,140,144,148,153,157,161,165,169,173,177,180,180,180,180,181,180,180,180,179,178,173,168,165,161,156,149,143,139,136,133,130,129,128,126,126,125,125,125,125,124,122,121,120,120,120,120,121,122,123,122,120,117,114,111,108,106,105,100,100,100,100,96,96,96,96,96,96,96,96,96,96,96,95,95,95,107,108,110,113,115,118,121,126,131,134,137,140,143,148,152,157,162,165,169,173,177,181,181,181,180,181,181,181,180,180,180,178,176,170,167,163,158,152,145,140,137,134,132,130,129,127,127,126,127,128,128,126,125,125,125,123,126,128,129,130,130,125,124,119,116,114,112,110,107,106,105,100,100,100,96,96,96,96,96,96,96,96,96,96,96,95,95,107,109,111,116,119,122,125,130,135,137,140,144,148,152,156,161,165,168,172,177,181,184,181,181,181,180,180,180,180,180,180,178,178,173,168,163,158,152,146,141,138,136,134,132,130,129,128,128,130,130,130,129,128,129,129,130,132,133,133,134,134,132,128,122,119,116,114,112,108,106,105,105,100,100,100,97,97,97,97,97,97,97,96,96,96,96,95,108,110,112,117,122,126,129,135,139,141,144,149,153,156,160,165,168,171,177,181,184,185,182,180,180,179,178,178,180,179,179,178,176,173,168,163,157,152,148,143,139,137,135,133,131,130,130,131,132,132,132,131,132,132,133,134,136,137,137,137,136,134,131,124,121,118,116,114,111,109,107,106,105,100,100,100,97,97,97,97,97,97,97,96,96,96,96,108,110,114,120,126,129,134,139,142,144,146,152,158,161,164,168,171,175,181,184,186,186,183,179,178,178,177,175,178,177,177,176,175,173,168,162,156,153,149,145,142,140,138,136,133,132,132,132,134,134,134,134,135,136,137,138,140,140,140,140,139,137,133,127,123,120,118,115,112,108,108,106,106,105,100,100,100,98,98,98,98,98,98,97,96,96,96,108,110,116,122,128,133,137,141,143,146,149,154,161,165,168,172,175,180,184,188,189,187,182,178,176,176,175,173,174,173,175,174,173,171,168,161,157,154,150,148,145,143,141,138,135,135,134,135,135,136,136,137,138,139,140,140,140,140,140,140,140,139,135,130,126,123,120,117,114,111,109,108,107,106,105,100,100,100,99,99,98,98,98,98,97,97,96,110,112,118,124,130,135,139,142,145,148,151,157,163,169,172,176,179,183,187,190,190,186,180,177,175,173,170,169,169,170,171,172,170,170,167,163,160,157,154,152,149,147,144,140,137,137,136,137,138,138,139,140,141,140,140,140,140,140,140,140,140,138,134,131,128,124,121,118,115,112,110,109,108,107,106,105,100,100,100,99,99,99,98,98,98,97,97,110,114,120,126,131,136,140,143,146,149,154,159,166,171,177,180,182,186,190,190,190,185,179,174,171,168,166,163,164,163,166,169,170,170,168,164,162,161,158,155,153,150,147,143,139,139,139,139,140,141,141,142,142,141,140,140,140,140,140,140,140,137,134,131,128,125,122,119,116,114,112,110,109,109,108,107,105,100,100,100,99,99,99,98,98,97,97,110,115,121,127,132,136,140,144,148,151,157,162,169,174,178,181,186,188,190,191,190,184,177,172,168,165,162,159,158,158,159,161,166,167,169,166,164,163,161,159,156,153,149,146,142,142,141,142,143,143,143,143,144,142,141,140,140,140,140,140,140,138,134,131,128,125,123,120,117,116,114,112,110,109,108,107,106,105,102,101,100,99,99,99,98,98,97,110,116,121,127,132,136,140,144,148,154,160,166,171,176,180,184,189,190,191,191,191,183,176,170,166,163,159,156,154,155,155,158,161,165,170,167,166,165,163,161,158,155,152,150,146,145,145,145,146,146,144,145,145,144,142,141,140,140,140,140,138,136,134,131,128,125,123,121,119,117,115,113,112,111,111,110,108,106,105,102,100,100,99,99,99,98,98,110,114,119,126,131,135,140,144,149,158,164,168,172,176,183,184,189,190,191,191,190,183,174,169,165,161,158,154,150,151,152,155,159,164,168,168,168,167,165,163,160,158,155,153,150,148,148,148,148,148,147,146,146,145,143,142,141,140,139,138,136,134,132,131,128,126,124,122,120,118,116,114,113,113,112,111,108,107,106,105,104,102,100,99,99,99,99,110,113,119,125,131,136,141,145,150,158,164,168,172,177,183,187,189,191,192,191,190,183,174,168,164,160,157,153,150,149,150,154,158,162,166,170,170,168,166,164,162,160,158,155,152,151,151,151,151,151,149,148,147,146,145,143,142,140,139,137,135,134,132,131,129,127,125,123,121,119,117,116,114,114,113,112,110,108,107,105,103,100,100,100,100,99,99,110,112,118,124,130,136,142,146,151,157,163,168,174,178,183,187,189,190,191,192,189,182,174,168,164,160,157,153,149,148,149,153,157,161,167,170,170,170,168,166,165,163,159,156,154,153,155,155,155,155,152,150,149,147,145,143,141,140,139,138,136,134,133,131,130,128,126,124,122,120,119,117,116,115,114,113,111,110,107,106,105,105,102,101,100,100,100,110,111,116,122,129,137,142,146,151,158,164,168,172,179,183,186,189,190,192,193,188,182,174,168,164,161,157,154,151,149,151,154,158,161,167,170,170,170,170,169,168,166,160,157,156,156,157,158,159,159,156,153,150,148,146,144,141,140,140,138,136,135,134,133,131,129,127,125,123,122,120,118,117,116,115,114,112,111,110,108,107,106,105,104,102,100,100,108,110,115,121,131,137,142,147,152,159,163,167,170,177,182,184,187,189,192,194,189,183,174,169,165,161,158,156,154,153,154,157,160,164,167,171,172,174,174,173,171,168,161,159,158,158,159,161,161,160,158,155,151,149,147,144,142,141,140,138,137,136,135,134,132,130,128,126,125,123,121,119,118,117,116,115,113,112,112,111,110,109,108,107,105,101,100,108,110,114,120,128,134,140,146,152,158,162,166,169,175,180,183,186,189,193,195,190,184,176,171,167,163,160,158,157,156,157,159,163,166,170,174,176,178,178,176,172,167,164,161,161,160,161,163,163,163,160,157,153,150,148,146,144,142,141,140,139,138,136,135,134,133,129,127,126,124,122,121,119,118,117,116,114,113,112,111,110,110,109,109,107,104,100,107,110,115,119,123,129,135,141,146,156,161,165,168,173,179,182,186,189,193,194,191,184,179,175,170,166,162,161,160,160,161,162,165,169,172,176,178,179,179,176,172,168,165,163,163,163,163,165,166,164,161,158,155,152,150,147,146,144,143,142,141,139,139,138,137,135,131,128,127,125,124,122,121,119,118,116,115,113,112,111,111,110,110,109,109,105,100,107,110,114,117,121,126,130,135,142,151,159,163,167,171,177,182,185,189,192,193,191,187,183,179,174,169,167,166,164,164,165,166,169,171,174,178,179,180,180,178,173,169,166,165,165,166,165,168,169,166,163,159,157,154,152,149,148,147,146,145,143,142,141,140,139,138,133,130,128,127,125,124,122,120,118,117,115,112,111,111,111,111,110,109,108,106,100,107,109,113,118,122,126,129,134,139,150,156,160,165,170,175,181,184,188,191,192,192,189,185,181,177,173,171,169,168,167,169,170,172,174,176,178,179,180,180,179,175,170,168,166,166,168,168,170,170,168,164,160,158,155,152,151,150,149,149,148,147,145,144,143,142,141,136,133,130,129,127,125,123,120,119,118,115,112,111,111,111,110,109,109,109,105,100,105,107,111,117,121,124,127,131,137,148,154,159,164,168,174,181,184,187,190,191,191,190,187,184,180,178,175,174,172,171,173,173,173,176,178,179,180,180,180,179,175,170,168,166,168,169,170,170,170,170,166,161,158,156,154,153,151,150,150,150,150,148,147,146,145,143,139,135,133,131,129,126,124,121,120,118,114,111,111,111,110,110,109,107,106,104,100,104,106,110,114,118,121,125,129,135,142,150,157,162,167,173,180,183,186,188,190,190,190,189,184,183,181,180,179,179,176,177,176,176,177,178,179,180,180,179,177,173,169,167,166,167,169,170,170,170,170,167,161,159,157,155,153,151,150,150,150,150,150,150,149,147,145,141,138,135,133,130,127,125,123,121,118,113,111,110,110,109,109,107,106,105,103,100,104,106,108,111,115,119,123,128,134,141,148,154,161,166,172,179,182,184,186,189,190,190,190,187,185,183,180,180,180,179,179,177,176,177,178,178,178,177,176,174,171,168,166,164,166,168,170,170,170,170,168,162,159,157,155,153,151,150,150,150,150,150,150,150,150,148,144,140,137,134,132,129,127,125,122,117,111,110,107,107,106,105,104,103,102,101,100,103,105,107,110,114,118,122,127,132,140,146,153,159,165,171,176,180,183,185,186,189,190,188,187,184,182,180,180,180,179,178,176,176,176,176,174,174,173,172,170,168,167,165,163,164,165,169,170,170,170,166,162,159,157,155,153,151,150,150,150,150,150,150,150,150,150,146,142,139,136,133,131,128,125,122,117,110,108,106,105,104,103,103,101,101,101,101,102,103,106,108,112,116,121,125,130,138,145,151,157,163,170,174,178,181,181,184,186,186,187,186,184,181,180,180,180,179,178,174,173,173,171,170,170,169,168,167,166,164,163,162,161,164,167,169,170,168,164,160,158,157,155,153,151,150,150,150,150,150,150,150,150,150,147,144,141,138,135,133,128,125,122,116,109,107,104,104,103,102,101,101,101,101,101,101,102,105,107,110,115,120,124,129,136,143,149,155,162,168,170,174,176,178,179,181,182,184,184,183,181,180,180,179,177,174,172,170,168,166,165,164,164,164,164,162,160,159,159,158,160,162,164,166,166,163,159,157,156,155,153,151,150,150,150,150,150,150,150,150,150,149,146,143,140,137,133,129,124,119,112,108,105,103,103,102,101,101,101,101,100,100,101,102,104,106,109,113,118,122,127,133,141,149,155,161,165,168,170,172,175,176,177,179,181,181,181,180,180,179,177,174,171,167,165,163,161,160,160,160,160,160,157,155,155,154,154,155,157,159,161,161,161,159,156,154,154,153,151,150,150,150,150,150,150,150,150,150,149,147,144,141,137,133,129,123,116,110,107,104,102,102,101,101,101,100,100,100,100,102,103,104,106,108,112,116,120,125,129,137,146,154,161,163,165,166,169,172,173,174,175,177,178,178,178,178,177,174,171,168,164,160,158,157,157,156,156,156,155,152,151,150,150,151,151,152,154,156,157,157,156,155,153,152,152,151,150,150,150,150,150,150,150,150,150,150,147,144,141,138,133,127,120,113,109,106,103,101,101,101,100,100,100,100,100,100,103,104,105,106,108,110,114,118,123,127,133,143,150,156,160,160,161,162,167,170,171,172,173,175,175,174,174,173,171,168,164,160,156,155,154,153,153,152,152,150,149,148,148,148,148,148,149,149,150,152,152,152,152,151,150,150,150,150,150,150,150,150,150,150,150,150,149,147,144,141,138,132,125,118,111,108,105,103,102,101,101,101,100,100,100,100,100,104,105,106,107,108,110,113,117,120,125,129,138,145,151,156,156,157,158,160,164,166,168,170,171,172,171,171,169,166,163,160,156,153,151,150,150,149,149,149,148,146,146,146,146,146,146,146,147,148,148,149,149,149,148,148,148,148,149,149,150,150,150,150,150,150,150,148,146,143,141,136,129,123,117,110,108,105,104,103,102,102,101,101,100,100,100,100,103,104,105,106,107,109,111,115,118,122,127,133,140,143,150,152,153,155,157,159,162,164,167,168,168,168,167,166,163,160,157,153,150,148,148,147,147,147,145,145,144,143,143,143,144,144,144,144,145,145,145,145,146,146,146,146,146,147,147,148,149,150,150,150,150,149,147,145,143,141,134,127,123,117,111,108,105,105,104,104,103,103,102,101,100,100,100,102,103,104,105,106,107,109,113,116,120,125,129,133,137,143,147,149,151,152,154,158,161,164,165,164,164,163,163,160,157,154,151,149,147,145,145,144,143,141,140,141,141,141,141,141,142,142,142,142,142,142,142,143,143,143,144,144,145,146,146,146,147,148,148,148,148,145,143,142,140,134,128,123,117,112,108,106,105,105,104,104,103,102,101,100,100,99,102,103,104,105,105,106,108,110,113,118,123,127,129,132,137,141,142,142,145,150,154,157,161,161,160,160,160,159,157,154,151,148,146,145,143,142,142,139,137,136,137,137,138,138,139,139,139,139,139,139,139,139,140,140,141,142,142,143,144,144,144,145,145,145,145,145,144,142,140,139,136,129,124,119,113,109,106,106,105,104,103,102,101,101,100,99,99,102,103,104,104,105,106,107,108,111,116,121,124,126,128,131,134,135,137,139,143,147,152,156,157,157,157,156,155,153,151,148,146,143,142,141,140,138,135,133,132,132,133,133,133,134,135,135,135,135,136,136,137,137,138,138,139,140,141,141,142,142,143,142,142,141,141,140,139,137,134,133,129,125,121,114,110,107,106,106,104,103,102,101,100,99,99,99,102,103,104,104,105,105,106,108,110,113,118,121,124,126,128,130,132,134,136,139,143,147,150,154,154,154,153,151,149,148,146,143,141,139,137,136,132,130,128,128,128,129,129,130,130,131,132,132,132,133,134,134,135,135,136,137,138,139,139,140,140,140,139,139,138,137,137,135,132,130,129,127,124,120,116,112,109,106,105,103,102,101,101,100,99,99,99,101,102,103,104,104,105,106,107,108,110,114,119,121,124,126,128,129,132,134,137,140,143,147,149,151,151,151,149,147,145,143,141,138,136,134,131,128,126,124,125,125,126,126,127,128,128,129,129,130,130,131,131,132,132,133,134,135,135,136,136,137,137,136,136,135,134,133,131,129,128,127,126,123,119,115,111,109,107,105,104,103,102,101,100,100,100,99,101,102,103,103,104,104,105,106,108,110,112,116,119,121,124,125,127,130,132,135,137,140,143,147,149,149,149,147,145,143,141,139,136,133,131,128,125,122,121,122,122,122,123,125,125,126,127,127,127,128,128,128,129,129,130,131,131,132,132,133,133,133,132,132,131,131,130,129,128,126,125,124,121,117,111,109,108,106,105,104,103,102,101,101,100,100,100,100,101,102,103,103,104,105,106,107,108,110,114,117,119,121,123,126,128,130,133,136,139,141,144,146,147,146,145,143,141,138,136,133,130,127,124,121,120,120,120,120,120,121,122,123,124,124,125,125,126,126,125,126,126,126,125,126,127,128,128,129,129,128,128,128,128,128,128,126,125,123,122,119,114,109,108,107,106,105,104,103,103,102,102,101,100,100,100,101,102,103,104,105,106,107,108,109,110,112,115,117,120,122,125,127,130,132,135,137,139,142,144,144,144,142,140,138,136,132,129,126,123,120,120,119,119,118,119,119,120,120,120,121,122,122,123,123,123,123,122,123,122,122,121,122,122,122,123,123,123,124,125,125,126,126,125,124,122,120,116,113,109,107,106,105,104,104,103,102,102,101,101,100,100,100,101,102,103,104,105,106,107,108,109,110,112,114,117,119,122,124,127,129,131,134,136,138,140,142,142,142,140,138,136,133,129,125,122,120,119,118,118,117,116,117,117,118,119,119,120,120,120,121,121,121,122,121,120,120,120,119,119,120,120,120,120,120,120,123,123,124,124,124,123,121,119,114,112,108,106,106,104,104,103,102,102,101,101,100,100,99,101,102,103,104,105,106,107,108,109,110,111,113,114,116,119,121,124,126,128,130,133,135,137,138,140,140,139,137,135,133,131,127,122,120,118,118,117,117,116,115,116,116,117,118,118,118,119,119,120,120,121,121,120,119,119,118,117,117,118,119,118,118,118,119,120,122,123,123,123,122,120,117,113,110,108,106,105,104,103,103,102,101,101,100,100,99,99,101,102,103,104,105,106,107,108,109,110,111,111,113,115,118,121,123,125,127,129,131,133,135,137,138,138,137,134,132,130,127,122,120,118,116,116,116,116,115,113,114,115,116,117,117,118,118,119,119,119,120,120,119,118,117,117,116,116,117,117,117,118,119,119,119,120,121,121,121,121,119,116,113,110,107,105,105,103,103,103,102,101,100,100,99,99,99,101,102,103,104,105,106,107,108,109,110,111,112,114,116,117,120,122,124,126,129,130,132,133,135,136,136,134,132,129,126,122,120,118,116,114,114,114,114,114,113,113,114,115,116,116,117,117,117,118,118,119,119,118,117,116,116,115,115,116,116,116,117,117,118,118,119,120,120,120,120,119,116,113,109,106,104,104,103,102,102,101,101,100,99,99,99,98,101,102,103,104,105,106,107,108,109,110,111,113,115,117,117,118,121,123,126,128,130,130,131,132,133,134,131,129,125,122,120,118,116,114,113,112,112,113,112,112,111,112,113,113,114,115,116,116,117,117,118,118,116,116,115,115,115,114,114,115,116,116,117,117,118,118,119,119,120,120,117,115,112,108,106,104,103,102,102,102,101,100,99,99,99,98,98,101,102,103,104,105,105,106,107,108,109,110,111,113,115,117,118,120,122,125,126,127,128,129,130,131,131,128,125,121,120,118,116,114,113,113,111,111,111,111,110,109,110,111,112,113,113,114,115,115,116,117,117,116,115,114,114,113,113,114,114,115,115,116,116,117,118,118,119,119,118,116,114,112,108,105,103,103,102,101,101,100,100,99,99,98,98,97,100,101,102,103,104,105,106,107,108,109,110,110,111,113,115,118,120,121,122,124,125,125,126,127,128,127,124,121,120,118,116,114,113,112,112,110,109,109,108,108,108,109,110,111,112,112,113,114,114,115,116,116,115,114,113,112,112,113,113,114,114,115,115,116,116,117,117,118,118,117,115,113,111,107,105,103,102,101,101,100,100,100,99,99,98,98,97,100,101,102,103,104,105,105,106,107,108,109,110,110,111,114,116,118,120,120,121,122,122,123,124,123,123,120,118,117,115,114,115,113,111,110,109,108,108,107,107,107,108,109,110,111,111,112,113,113,114,115,115,114,113,112,111,111,112,112,112,113,114,114,115,115,116,116,117,117,116,114,112,109,106,104,102,101,100,100,99,99,99,99,98,98,97,97]} diff --git a/test/snapshots/index.js b/test/snapshots/index.js index 53a663c..dd50e1c 100644 --- a/test/snapshots/index.js +++ b/test/snapshots/index.js @@ -1,12 +1,13 @@ import {extent, ticks} from "d3-array"; import {axisBottom, axisLeft} from "d3-axis"; import {autoType} from "d3-dsv"; -import {tsv} from "d3-fetch"; -import {geoPath} from "d3-geo"; -import {scaleLinear} from "d3-scale"; -import {select} from "d3-selection"; +import {tsv, json} from "d3-fetch"; +import {geoIdentity, geoPath} from "d3-geo"; +import {scaleLinear, scaleSequential} from "d3-scale"; +import {interpolateTurbo} from "d3-scale-chromatic"; +import {create, select} from "d3-selection"; import {svg} from "htl"; -import {contourDensity} from "d3-contour"; +import {contours, contourDensity} from "d3-contour"; export async function faithfulContours() { const faithful = await tsv("data/faithful.tsv", autoType); @@ -80,3 +81,26 @@ export async function faithfulContour() { ${thresholds.map(t => svg``)} `; } + +export async function volcanoContours() { + const data = await json("data/volcano.json"); + const n = data.width; + const m = data.height; + const width = 928; + const height = Math.round(m / n * width); + const path = geoPath().projection(geoIdentity().scale(width / n)); + const color = scaleSequential(interpolateTurbo).domain(extent(data.values)).nice(); + const svg = create("svg") + .attr("width", width) + .attr("height", height) + .attr("viewBox", [0, 0, width, height]) + .attr("style", "max-width: 100%; height: auto;"); + svg.append("g") + .attr("stroke", "black") + .selectAll() + .data(color.ticks(20)) + .join("path") + .attr("d", d => path(contours().size([n, m]).contour(data.values, d))) + .attr("fill", color); + return svg.node(); +} diff --git a/yarn.lock b/yarn.lock index 9ef1fc1..fe4efe9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -438,7 +438,7 @@ d3-geo@3: dependencies: d3-array "2.5.0 - 3" -"d3-interpolate@1.2.0 - 3": +"d3-interpolate@1 - 3", "d3-interpolate@1.2.0 - 3": version "3.0.1" resolved "https://registry.yarnpkg.com/d3-interpolate/-/d3-interpolate-3.0.1.tgz#3c47aa5b32c5b3dfb56ef3fd4342078a632b400d" integrity sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g== @@ -450,6 +450,14 @@ d3-polygon@3: resolved "https://registry.yarnpkg.com/d3-polygon/-/d3-polygon-3.0.1.tgz#0b45d3dd1c48a29c8e057e6135693ec80bf16398" integrity sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg== +d3-scale-chromatic@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz#34c39da298b23c20e02f1a4b239bd0f22e7f1314" + integrity sha512-A3s5PWiZ9YCXFye1o246KoscMWqf8BsD9eRiJ3He7C9OBaxKhAd5TFCdEx/7VbKtxxTsu//1mMJFrEt572cEyQ== + dependencies: + d3-color "1 - 3" + d3-interpolate "1 - 3" + d3-scale@4: version "4.0.2" resolved "https://registry.yarnpkg.com/d3-scale/-/d3-scale-4.0.2.tgz#82b38e8e8ff7080764f8dcec77bd4be393689396" From 9fc65d5e4f3baa6b92b51147a350e349dd93a9b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Rivi=C3=A8re?= Date: Tue, 26 Nov 2024 11:00:02 +0100 Subject: [PATCH 2/5] a volcano with rounded corners --- test/output/volcanoContours.svg | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 test/output/volcanoContours.svg diff --git a/test/output/volcanoContours.svg b/test/output/volcanoContours.svg new file mode 100644 index 0000000..2a1826d --- /dev/null +++ b/test/output/volcanoContours.svg @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From 11ae1ab85d25dc9f214a7d0736fbceed6d3326c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Rivi=C3=A8re?= Date: Tue, 26 Nov 2024 11:15:12 +0100 Subject: [PATCH 3/5] expand the matrix on the edges (with blurred values), then contract the contour back to the frame closes #72 --- src/contours.js | 134 ++++++++++++++++---------- test/contours-test.js | 2 +- test/output/volcanoContours.svg | 42 ++++---- test/output/volcanoContoursRugged.svg | 27 ++++++ test/snapshots/index.js | 23 +++++ 5 files changed, 155 insertions(+), 73 deletions(-) create mode 100644 test/output/volcanoContoursRugged.svg diff --git a/src/contours.js b/src/contours.js index 90faf82..88b7171 100644 --- a/src/contours.js +++ b/src/contours.js @@ -1,4 +1,4 @@ -import {extent, nice, thresholdSturges, ticks} from "d3-array"; +import {blur, extent, nice, thresholdSturges, ticks} from "d3-array"; import {slice} from "./array.js"; import ascending from "./ascending.js"; import area from "./area.js"; @@ -6,7 +6,7 @@ import constant from "./constant.js"; import contains from "./contains.js"; import noop from "./noop.js"; -var cases = [ +const cases = [ [], [[[1.0, 1.5], [0.5, 1.0]]], [[[1.5, 1.0], [1.0, 1.5]]], @@ -25,14 +25,20 @@ var cases = [ [] ]; +const blurEdges = 0.5; + +function clamp(x, lo, hi) { + return x < lo ? lo : x > hi ? hi : x; +} + export default function() { - var dx = 1, - dy = 1, - threshold = thresholdSturges, - smooth = smoothLinear; + let dx = 1; + let dy = 1; + let threshold = thresholdSturges; + let smooth = smoothLinear; function contours(values) { - var tz = threshold(values); + let tz = threshold(values); // Convert number of thresholds into uniform thresholds. if (!Array.isArray(tz)) { @@ -53,17 +59,45 @@ export default function() { const v = value == null ? NaN : +value; if (isNaN(v)) throw new Error(`invalid value: ${value}`); - var polygons = [], - holes = []; + // Don’t round the corners by clamping values on the edge. + const bottom = values.slice(0, dx); + const top = values.slice(-dx); + const left = Array.from({length: dy}, (_, i) => values[i * dx]); + const right = Array.from({length: dy}, (_, i) => values[i * dx + dx - 1]); + blur(bottom, blurEdges); + blur(top, blurEdges); + blur(left, blurEdges); + blur(right, blurEdges); + + function get(x, y) { + const x0 = clamp(x, 0, dx - 1); + const y0 = clamp(y, 0, dy - 1); + if (y < 0) return bottom[x0]; + if (y >= dy) return top[x0]; + if (x < 0) return left[y0]; + if (x >= dx) return right[y0]; + return values[x0 + y0 * dx]; + } - isorings(values, v, function(ring) { - smooth(ring, values, v); - if (area(ring) > 0) polygons.push([ring]); - else holes.push(ring); + const polygons = []; + const holes = []; + + isorings(get, value, function(ring) { + smooth(ring, get, value); + const r = []; + let x0, y0; + for (const point of ring) { + const x = clamp(point[0], 0, dx); + const y = clamp(point[1], 0, dy); + if (x !== x0 || y !== y0) r.push([(x0 = x), (y0 = y)]); + } + const a = area(r); + if (a > 0) polygons.push([r]); + else if (a < 0) holes.push(r); }); holes.forEach(function(hole) { - for (var i = 0, n = polygons.length, polygon; i < n; ++i) { + for (let i = 0, n = polygons.length, polygon; i < n; ++i) { if (contains((polygon = polygons[i])[0], hole) !== -1) { polygon.push(hole); return; @@ -80,51 +114,52 @@ export default function() { // Marching squares with isolines stitched into rings. // Based on https://github.com/topojson/topojson-client/blob/v3.0.0/src/stitch.js - function isorings(values, value, callback) { - var fragmentByStart = new Array, - fragmentByEnd = new Array, - x, y, t0, t1, t2, t3; + function isorings(get, value, callback) { + const test = (x, y) => above(get(x, y), value); + const fragmentByStart = new Array; + const fragmentByEnd = new Array; + let x, y, t0, t1, t2, t3; // Special case for the first row (y = -1, t2 = t3 = 0). - x = y = -1; - t1 = above(values[0], value); + x = y = -2; + t1 = test(-1, -1); cases[t1 << 1].forEach(stitch); - while (++x < dx - 1) { - t0 = t1, t1 = above(values[x + 1], value); + while (++x < dx) { + t0 = t1, t1 = test(x + 1, -1); cases[t0 | t1 << 1].forEach(stitch); } cases[t1 << 0].forEach(stitch); // General case for the intermediate rows. - while (++y < dy - 1) { - x = -1; - t1 = above(values[y * dx + dx], value); - t2 = above(values[y * dx], value); + while (++y < dy) { + x = -2; + t1 = test(x + 1, y + 1); + t2 = test(x + 1, y); cases[t1 << 1 | t2 << 2].forEach(stitch); - while (++x < dx - 1) { - t0 = t1, t1 = above(values[y * dx + dx + x + 1], value); - t3 = t2, t2 = above(values[y * dx + x + 1], value); + while (++x < dx) { + t0 = t1, t1 = test(x + 1, y + 1); + t3 = t2, t2 = test(x + 1, y); cases[t0 | t1 << 1 | t2 << 2 | t3 << 3].forEach(stitch); } cases[t1 | t2 << 3].forEach(stitch); } // Special case for the last row (y = dy - 1, t0 = t1 = 0). - x = -1; - t2 = values[y * dx] >= value; + x = -2; + t2 = test(x, y); cases[t2 << 2].forEach(stitch); - while (++x < dx - 1) { - t3 = t2, t2 = above(values[y * dx + x + 1], value); + while (++x < dx) { + t3 = t2, t2 = test(x + 1, y); cases[t2 << 2 | t3 << 3].forEach(stitch); } cases[t2 << 3].forEach(stitch); function stitch(line) { - var start = [line[0][0] + x, line[0][1] + y], - end = [line[1][0] + x, line[1][1] + y], - startIndex = index(start), - endIndex = index(end), - f, g; + const start = [line[0][0] + x, line[0][1] + y]; + const end = [line[1][0] + x, line[1][1] + y]; + const startIndex = index(start); + const endIndex = index(end); + let f, g; if (f = fragmentByEnd[startIndex]) { if (g = fragmentByStart[endIndex]) { delete fragmentByEnd[f.end]; @@ -165,19 +200,15 @@ export default function() { return point[0] * 2 + point[1] * (dx + 1) * 4; } - function smoothLinear(ring, values, value) { + function smoothLinear(ring, get, value) { ring.forEach(function(point) { - var x = point[0], - y = point[1], - xt = x | 0, - yt = y | 0, - v1 = valid(values[yt * dx + xt]); - if (x > 0 && x < dx && xt === x) { - point[0] = smooth1(x, valid(values[yt * dx + xt - 1]), v1, value); - } - if (y > 0 && y < dy && yt === y) { - point[1] = smooth1(y, valid(values[(yt - 1) * dx + xt]), v1, value); - } + const x = point[0]; + const y = point[1]; + const xt = x | 0; + const yt = y | 0; + const v1 = valid(get(xt, yt)); + if (x > 0 && x < dx && xt === x) point[0] = smooth1(x, valid(get(xt - 1, yt)), v1, value); + if (y > 0 && y < dy && yt === y) point[1] = smooth1(y, valid(get(xt, yt - 1)), v1, value); }); } @@ -185,7 +216,8 @@ export default function() { contours.size = function(_) { if (!arguments.length) return [dx, dy]; - var _0 = Math.floor(_[0]), _1 = Math.floor(_[1]); + const _0 = Math.floor(_[0]); + const _1 = Math.floor(_[1]); if (!(_0 >= 0 && _1 >= 0)) throw new Error("invalid size"); return dx = _0, dy = _1, contours; }; diff --git a/test/contours-test.js b/test/contours-test.js index 6cfaa31..d7306be 100644 --- a/test/contours-test.js +++ b/test/contours-test.js @@ -252,7 +252,7 @@ it("contours(values) treats null, undefined, NaN and -Infinity as holes", () => 1, 1, NaN, 1, 1, 1, 2, -Infinity, 2, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 - ], 0), {"type":"MultiPolygon","value":0,"coordinates":[[[[10,9.5],[10,8.5],[10,7.5],[10,6.5],[10,5.5],[10,4.5],[10,3.5],[10,2.5],[10,1.5],[10,0.5],[9.5,0],[8.5,0],[7.5,0],[6.5,0],[5.5,0],[4.5,0],[3.5,0],[2.5,0],[1.5,0],[0.5,0],[0,0.5],[0,1.5],[0,2.5],[0,3.5],[0,4.5],[0,5.5],[0,6.5],[0,7.5],[0,8.5],[0,9.5],[0.5,10],[1.5,10],[2.5,10],[3.5,10],[4.5,10],[5.5,10],[6.5,10],[7.5,10],[8.5,10],[9.5,10],[10,9.5]],[[1.5,2.5],[0.5,1.5],[1.5,0.5],[2.5,1.5],[1.5,2.5]],[[3.5,5.5],[2.5,4.5],[3.5,3.5],[4.5,4.5],[3.5,5.5]],[[2.5,8.5],[1.5,7.5],[2.5,6.5],[3.5,7.5],[2.5,8.5]],[[7.5,8.5],[6.5,7.5],[7.5,6.5],[8.5,7.5],[7.5,8.5]]]]}); + ], 0), {"type":"MultiPolygon","value":0,"coordinates":[[[[10,10],[10,9.5],[10,8.5],[10,7.5],[10,6.5],[10,5.5],[10,4.5],[10,3.5],[10,2.5],[10,1.5],[10,0.5],[10,0],[9.5,0],[8.5,0],[7.5,0],[6.5,0],[5.5,0],[4.5,0],[3.5,0],[2.5,0],[1.5,0],[0.5,0],[0,0],[0,0.5],[0,1.5],[0,2.5],[0,3.5],[0,4.5],[0,5.5],[0,6.5],[0,7.5],[0,8.5],[0,9.5],[0,10],[0.5,10],[1.5,10],[2.5,10],[3.5,10],[4.5,10],[5.5,10],[6.5,10],[7.5,10],[8.5,10],[9.5,10],[10,10]],[[1.5,2.5],[0.5,1.5],[1.5,0.5],[2.5,1.5],[1.5,2.5]],[[3.5,5.5],[2.5,4.5],[3.5,3.5],[4.5,4.5],[3.5,5.5]],[[2.5,8.5],[1.5,7.5],[2.5,6.5],[3.5,7.5],[2.5,8.5]],[[7.5,8.5],[6.5,7.5],[7.5,6.5],[8.5,7.5],[7.5,8.5]]]]}); }); it("contours(values) returns the expected result for a +Infinity value", () => { diff --git a/test/output/volcanoContours.svg b/test/output/volcanoContours.svg index 2a1826d..a6edd49 100644 --- a/test/output/volcanoContours.svg +++ b/test/output/volcanoContours.svg @@ -1,26 +1,26 @@ - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + diff --git a/test/output/volcanoContoursRugged.svg b/test/output/volcanoContoursRugged.svg new file mode 100644 index 0000000..815c7bd --- /dev/null +++ b/test/output/volcanoContoursRugged.svg @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/test/snapshots/index.js b/test/snapshots/index.js index dd50e1c..ea0de69 100644 --- a/test/snapshots/index.js +++ b/test/snapshots/index.js @@ -104,3 +104,26 @@ export async function volcanoContours() { .attr("fill", color); return svg.node(); } + +export async function volcanoContoursRugged() { + const data = await json("data/volcano.json"); + const n = data.width; + const m = data.height; + const width = 928; + const height = Math.round(m / n * width); + const path = geoPath().projection(geoIdentity().scale(width / n)); + const color = scaleSequential(interpolateTurbo).domain(extent(data.values)).nice(); + const svg = create("svg") + .attr("width", width) + .attr("height", height) + .attr("viewBox", [0, 0, width, height]) + .attr("style", "max-width: 100%; height: auto;"); + svg.append("g") + .attr("stroke", "black") + .selectAll() + .data(color.ticks(20)) + .join("path") + .attr("d", d => path(contours().smooth(false).size([n, m]).contour(data.values, d))) + .attr("fill", color); + return svg.node(); +} From 6c21a1eecde1ace03d15040609ed0836ace86fb2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Rivi=C3=A8re?= Date: Tue, 26 Nov 2024 11:36:42 +0100 Subject: [PATCH 4/5] support UintArray data, add more tests --- src/contours.js | 11 +++-- test/output/matrixContours.svg | 29 +++++++++++ test/output/matrixContours1.svg | 29 +++++++++++ test/output/matrixContours2.svg | 20 ++++++++ test/output/matrixContours3.svg | 23 +++++++++ test/output/matrixContours4Holes.svg | 25 ++++++++++ test/snapshots/index.js | 73 ++++++++++++++++++---------- 7 files changed, 180 insertions(+), 30 deletions(-) create mode 100644 test/output/matrixContours.svg create mode 100644 test/output/matrixContours1.svg create mode 100644 test/output/matrixContours2.svg create mode 100644 test/output/matrixContours3.svg create mode 100644 test/output/matrixContours4Holes.svg diff --git a/src/contours.js b/src/contours.js index 88b7171..dfe3580 100644 --- a/src/contours.js +++ b/src/contours.js @@ -59,11 +59,12 @@ export default function() { const v = value == null ? NaN : +value; if (isNaN(v)) throw new Error(`invalid value: ${value}`); - // Don’t round the corners by clamping values on the edge. - const bottom = values.slice(0, dx); - const top = values.slice(-dx); - const left = Array.from({length: dy}, (_, i) => values[i * dx]); - const right = Array.from({length: dy}, (_, i) => values[i * dx + dx - 1]); + // Don’t round the corners by clamping values on the edge. Note: to blur, we + // need to ensure that the values are valid numbers. + const bottom = Array.from(values.slice(0, dx), valid); + const top = Array.from(values.slice(-dx), valid); + const left = Array.from({length: dy}, (_, i) => valid(values[i * dx])); + const right = Array.from({length: dy}, (_, i) => valid(values[i * dx + dx - 1])); blur(bottom, blurEdges); blur(top, blurEdges); blur(left, blurEdges); diff --git a/test/output/matrixContours.svg b/test/output/matrixContours.svg new file mode 100644 index 0000000..f900e1e --- /dev/null +++ b/test/output/matrixContours.svg @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/test/output/matrixContours1.svg b/test/output/matrixContours1.svg new file mode 100644 index 0000000..f900e1e --- /dev/null +++ b/test/output/matrixContours1.svg @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/test/output/matrixContours2.svg b/test/output/matrixContours2.svg new file mode 100644 index 0000000..79a9bd9 --- /dev/null +++ b/test/output/matrixContours2.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/test/output/matrixContours3.svg b/test/output/matrixContours3.svg new file mode 100644 index 0000000..a86f09e --- /dev/null +++ b/test/output/matrixContours3.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/test/output/matrixContours4Holes.svg b/test/output/matrixContours4Holes.svg new file mode 100644 index 0000000..0954799 --- /dev/null +++ b/test/output/matrixContours4Holes.svg @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/test/snapshots/index.js b/test/snapshots/index.js index ea0de69..6ded72c 100644 --- a/test/snapshots/index.js +++ b/test/snapshots/index.js @@ -82,14 +82,12 @@ export async function faithfulContour() { `; } -export async function volcanoContours() { - const data = await json("data/volcano.json"); +function svgContours(data, {width = 500, smooth = true} = {}) { const n = data.width; const m = data.height; - const width = 928; const height = Math.round(m / n * width); const path = geoPath().projection(geoIdentity().scale(width / n)); - const color = scaleSequential(interpolateTurbo).domain(extent(data.values)).nice(); + const color = scaleSequential(interpolateTurbo).domain(extent(data.values, d => isFinite(d) ? d : NaN)).nice(); const svg = create("svg") .attr("width", width) .attr("height", height) @@ -100,30 +98,55 @@ export async function volcanoContours() { .selectAll() .data(color.ticks(20)) .join("path") - .attr("d", d => path(contours().size([n, m]).contour(data.values, d))) + .attr("d", d => path(contours().smooth(smooth).size([n, m]).contour(data.values, d))) .attr("fill", color); return svg.node(); } +export async function volcanoContours() { + return svgContours(await json("data/volcano.json"), {width: 928}); +} + export async function volcanoContoursRugged() { - const data = await json("data/volcano.json"); - const n = data.width; - const m = data.height; - const width = 928; - const height = Math.round(m / n * width); - const path = geoPath().projection(geoIdentity().scale(width / n)); - const color = scaleSequential(interpolateTurbo).domain(extent(data.values)).nice(); - const svg = create("svg") - .attr("width", width) - .attr("height", height) - .attr("viewBox", [0, 0, width, height]) - .attr("style", "max-width: 100%; height: auto;"); - svg.append("g") - .attr("stroke", "black") - .selectAll() - .data(color.ticks(20)) - .join("path") - .attr("d", d => path(contours().smooth(false).size([n, m]).contour(data.values, d))) - .attr("fill", color); - return svg.node(); + return svgContours(await json("data/volcano.json"), {width: 928, smooth: false}); +} + +export function matrixContours1() { + const n = 16; + const data = {values: new Uint32Array(n * n), width: n, height: n}; + for (let i = 0; i < n; ++i) + for (let j = 0; j < n; ++j) + data.values[i + n * j] = i * j; + return svgContours(data); +} + +export function matrixContours2() { + const n = 16; + const data = {values: new Float32Array(n * n), width: n, height: n}; + for (let i = 0; i < n; ++i) + for (let j = 0; j < n; ++j) + data.values[i + n * j] = i + j; + return svgContours(data); +} + +export function matrixContours3() { + const n = 200; + const data = {values: new Float32Array(n * n), width: n, height: n}; + for (let i = 0; i < n; ++i) + for (let j = 0; j < n; ++j) + data.values[i + n * j] = Math.sin(2 * i / n + 2 * (j / n)**2); + return svgContours(data); +} + + +export function matrixContours4Holes() { + const n = 200; + const data = {values: new Float32Array(n * n), width: n, height: n}; + for (let i = 0; i < n; ++i) + for (let j = 0; j < n; ++j) + data.values[i + n * j] = Math.cos(2 * i / n + 2 * (j / n)**2); + data.values[1256] = NaN; + data.values[6900] = -Infinity; + data.values[18700] = +Infinity; + return svgContours(data); } From 82226773a0a6acef337c26dc4c5a8f86d0187cfe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Rivi=C3=A8re?= Date: Tue, 26 Nov 2024 11:42:59 +0100 Subject: [PATCH 5/5] add the grid2 test --- test/output/grid2.svg | 29 +++++++++++++ test/snapshots/index.js | 95 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 122 insertions(+), 2 deletions(-) create mode 100644 test/output/grid2.svg diff --git a/test/output/grid2.svg b/test/output/grid2.svg new file mode 100644 index 0000000..470fdf5 --- /dev/null +++ b/test/output/grid2.svg @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/test/snapshots/index.js b/test/snapshots/index.js index 6ded72c..3a225fb 100644 --- a/test/snapshots/index.js +++ b/test/snapshots/index.js @@ -87,7 +87,7 @@ function svgContours(data, {width = 500, smooth = true} = {}) { const m = data.height; const height = Math.round(m / n * width); const path = geoPath().projection(geoIdentity().scale(width / n)); - const color = scaleSequential(interpolateTurbo).domain(extent(data.values, d => isFinite(d) ? d : NaN)).nice(); + const color = scaleSequential(interpolateTurbo).domain(extent(data.values, (d) => isFinite(d) ? d : NaN)).nice(); const svg = create("svg") .attr("width", width) .attr("height", height) @@ -98,7 +98,7 @@ function svgContours(data, {width = 500, smooth = true} = {}) { .selectAll() .data(color.ticks(20)) .join("path") - .attr("d", d => path(contours().smooth(smooth).size([n, m]).contour(data.values, d))) + .attr("d", (d) => path(contours().smooth(smooth).size([n, m]).contour(data.values, d))) .attr("fill", color); return svg.node(); } @@ -150,3 +150,94 @@ export function matrixContours4Holes() { data.values[18700] = +Infinity; return svgContours(data); } + +export function grid2() { + return svgContours({ + values: [ + [ + 3.931884, 3.949764, 3.967644, 3.985524, 4.003405, 4.021285, + 4.039165, 4.057045, 4.074925, 4.092805, 4.110685, 4.128565, + 4.146446, 4.164326, 4.182206, 4.200086 + ], + [ + 3.890766, 3.910306, 3.929845, 3.949385, 3.968925, 3.988464, + 4.008004, 4.027544, 4.047084, 4.066623, 4.086163, 4.105703, + 4.125243, 4.144782, 4.164322, 4.183862 + ], + [ + 3.849648, 3.870847, 3.892046, 3.913245, 3.934445, 3.955644, + 3.976844, 3.998043, 4.019242, 4.040442, 4.061641, 4.08284, 4.10404, + 4.125239, 4.146438, 4.167637 + ], + [ + 3.808529, 3.831388, 3.854247, 3.877106, 3.899965, 3.922824, + 3.945683, 3.968542, 3.991401, 4.014259, 4.037118, 4.059978, + 4.082836, 4.105695, 4.128554, 4.151413 + ], + [ + 3.767411, 3.791929, 3.816448, 3.840966, 3.865485, 3.890004, + 3.914522, 3.939041, 3.963559, 3.988078, 4.012596, 4.037115, + 4.061633, 4.086152, 4.11067, 4.135189 + ], + [ + 3.726293, 3.752471, 3.778649, 3.804827, 3.831005, 3.857183, + 3.883361, 3.909539, 3.935718, 3.961896, 3.988074, 4.014252, 4.04043, + 4.066608, 4.092786, 4.118965 + ], + [ + 3.685174, 3.713012, 3.74085, 3.768687, 3.796525, 3.824363, 3.852201, + 3.880038, 3.907876, 3.935714, 3.963552, 3.991389, 4.019227, + 4.047065, 4.074903, 4.10274 + ], + [ + 3.644056, 3.673553, 3.703051, 3.732548, 3.762045, 3.791543, 3.82104, + 3.850537, 3.880035, 3.909532, 3.939029, 3.968527, 3.998024, + 4.027521, 4.057019, 4.086516 + ], + [ + 3.602938, 3.634095, 3.665252, 3.696409, 3.727566, 3.758723, + 3.789879, 3.821036, 3.852193, 3.88335, 3.914507, 3.945664, 3.976821, + 4.007978, 4.039135, 4.070292 + ], + [ + 3.56182, 3.594636, 3.627453, 3.660269, 3.693086, 3.725902, 3.758719, + 3.791535, 3.824352, 3.857168, 3.889985, 3.922801, 3.955618, + 3.988434, 4.021251, 4.054067 + ], + [ + 3.520701, 3.555177, 3.589653, 3.62413, 3.658606, 3.693082, 3.727558, + 3.762034, 3.79651, 3.830986, 3.865462, 3.899939, 3.934415, 3.968891, + 4.003367, 4.037843 + ], + [ + 3.479583, 3.515719, 3.551854, 3.58799, 3.624126, 3.660262, 3.696397, + 3.732533, 3.768669, 3.804804, 3.84094, 3.877076, 3.913212, 3.949347, + 3.985483, 4.021619 + ], + [ + 3.438465, 3.47626, 3.514055, 3.551851, 3.589646, 3.627441, 3.665237, + 3.703032, 3.740827, 3.778623, 3.816418, 3.854213, 3.892009, + 3.929804, 3.967599, 4.005394 + ], + [ + 3.397346, 3.436801, 3.476256, 3.515711, 3.555166, 3.594621, + 3.634076, 3.673531, 3.712986, 3.752441, 3.791896, 3.83135, 3.870805, + 3.91026, 3.949715, 3.98917 + ], + [ + 3.356228, 3.397343, 3.438457, 3.479572, 3.520686, 3.561801, + 3.602915, 3.64403, 3.685144, 3.726259, 3.767373, 3.808488, 3.849602, + 3.890717, 3.931831, 3.972946 + ], + [ + 3.31511, 3.357884, 3.400658, 3.443432, 3.486206, 3.52898, 3.571754, + 3.614529, 3.657303, 3.700077, 3.742851, 3.785625, 3.828399, + 3.871173, 3.913947, 3.956722 + ] + ] + .flat() + .map((d) => 5 * d), + width: 16, + height: 16 + }); +} \ No newline at end of file