drizzle 2.1.0__tar.gz → 2.1.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of drizzle might be problematic. Click here for more details.
- {drizzle-2.1.0 → drizzle-2.1.1}/.github/workflows/build.yml +1 -1
- {drizzle-2.1.0 → drizzle-2.1.1}/.github/workflows/ci.yml +1 -1
- {drizzle-2.1.0 → drizzle-2.1.1}/CHANGES.rst +25 -1
- {drizzle-2.1.0/drizzle.egg-info → drizzle-2.1.1}/PKG-INFO +1 -1
- {drizzle-2.1.0 → drizzle-2.1.1}/drizzle/tests/test_overlap_calc.py +24 -0
- {drizzle-2.1.0 → drizzle-2.1.1}/drizzle/tests/test_resample.py +130 -5
- {drizzle-2.1.0 → drizzle-2.1.1/drizzle.egg-info}/PKG-INFO +1 -1
- {drizzle-2.1.0 → drizzle-2.1.1}/src/cdrizzleapi.c +17 -7
- {drizzle-2.1.0 → drizzle-2.1.1}/src/cdrizzlebox.c +151 -144
- {drizzle-2.1.0 → drizzle-2.1.1}/src/cdrizzlebox.h +1 -3
- {drizzle-2.1.0 → drizzle-2.1.1}/src/cdrizzlemap.c +80 -29
- {drizzle-2.1.0 → drizzle-2.1.1}/.clang-format +0 -0
- {drizzle-2.1.0 → drizzle-2.1.1}/.coveragerc +0 -0
- {drizzle-2.1.0 → drizzle-2.1.1}/.flake8 +0 -0
- {drizzle-2.1.0 → drizzle-2.1.1}/.github/CODEOWNERS +0 -0
- {drizzle-2.1.0 → drizzle-2.1.1}/.github/dependabot.yml +0 -0
- {drizzle-2.1.0 → drizzle-2.1.1}/.gitignore +0 -0
- {drizzle-2.1.0 → drizzle-2.1.1}/.readthedocs.yaml +0 -0
- {drizzle-2.1.0 → drizzle-2.1.1}/.ruff.toml +0 -0
- {drizzle-2.1.0 → drizzle-2.1.1}/CODE_OF_CONDUCT.md +0 -0
- {drizzle-2.1.0 → drizzle-2.1.1}/LICENSE.rst +0 -0
- {drizzle-2.1.0 → drizzle-2.1.1}/MANIFEST.in +0 -0
- {drizzle-2.1.0 → drizzle-2.1.1}/README.rst +0 -0
- {drizzle-2.1.0 → drizzle-2.1.1}/docs/Makefile +0 -0
- {drizzle-2.1.0 → drizzle-2.1.1}/docs/_templates/autosummary/base.rst +0 -0
- {drizzle-2.1.0 → drizzle-2.1.1}/docs/_templates/autosummary/class.rst +0 -0
- {drizzle-2.1.0 → drizzle-2.1.1}/docs/_templates/autosummary/module.rst +0 -0
- {drizzle-2.1.0 → drizzle-2.1.1}/docs/conf.py +0 -0
- {drizzle-2.1.0 → drizzle-2.1.1}/docs/drizzle/api.rst +0 -0
- {drizzle-2.1.0 → drizzle-2.1.1}/docs/drizzle/index.rst +0 -0
- {drizzle-2.1.0 → drizzle-2.1.1}/docs/drizzle/user.rst +0 -0
- {drizzle-2.1.0 → drizzle-2.1.1}/docs/exts/numfig.py +0 -0
- {drizzle-2.1.0 → drizzle-2.1.1}/docs/index.rst +0 -0
- {drizzle-2.1.0 → drizzle-2.1.1}/docs/make.bat +0 -0
- {drizzle-2.1.0 → drizzle-2.1.1}/docs/rtd_environment.yaml +0 -0
- {drizzle-2.1.0 → drizzle-2.1.1}/drizzle/__init__.py +0 -0
- {drizzle-2.1.0 → drizzle-2.1.1}/drizzle/resample.py +0 -0
- {drizzle-2.1.0 → drizzle-2.1.1}/drizzle/tests/__init__.py +0 -0
- {drizzle-2.1.0 → drizzle-2.1.1}/drizzle/tests/helpers.py +0 -0
- {drizzle-2.1.0 → drizzle-2.1.1}/drizzle/tests/test_cdrizzle.py +0 -0
- {drizzle-2.1.0 → drizzle-2.1.1}/drizzle/tests/test_utils.py +0 -0
- {drizzle-2.1.0 → drizzle-2.1.1}/drizzle/util.py +0 -0
- {drizzle-2.1.0 → drizzle-2.1.1}/drizzle/utils.py +0 -0
- {drizzle-2.1.0 → drizzle-2.1.1}/drizzle.egg-info/SOURCES.txt +0 -0
- {drizzle-2.1.0 → drizzle-2.1.1}/drizzle.egg-info/dependency_links.txt +0 -0
- {drizzle-2.1.0 → drizzle-2.1.1}/drizzle.egg-info/not-zip-safe +0 -0
- {drizzle-2.1.0 → drizzle-2.1.1}/drizzle.egg-info/requires.txt +0 -0
- {drizzle-2.1.0 → drizzle-2.1.1}/drizzle.egg-info/top_level.txt +0 -0
- {drizzle-2.1.0 → drizzle-2.1.1}/pyproject.toml +0 -0
- {drizzle-2.1.0 → drizzle-2.1.1}/setup.cfg +0 -0
- {drizzle-2.1.0 → drizzle-2.1.1}/setup.py +0 -0
- {drizzle-2.1.0 → drizzle-2.1.1}/src/cdrizzleblot.c +0 -0
- {drizzle-2.1.0 → drizzle-2.1.1}/src/cdrizzleblot.h +0 -0
- {drizzle-2.1.0 → drizzle-2.1.1}/src/cdrizzlemap.h +0 -0
- {drizzle-2.1.0 → drizzle-2.1.1}/src/cdrizzleutil.c +0 -0
- {drizzle-2.1.0 → drizzle-2.1.1}/src/cdrizzleutil.h +0 -0
- {drizzle-2.1.0 → drizzle-2.1.1}/src/driz_portability.h +0 -0
- {drizzle-2.1.0 → drizzle-2.1.1}/src/tests/.clang-format +0 -0
- {drizzle-2.1.0 → drizzle-2.1.1}/src/tests/drizzletest.h +0 -0
- {drizzle-2.1.0 → drizzle-2.1.1}/src/tests/fct.h +0 -0
- {drizzle-2.1.0 → drizzle-2.1.1}/src/tests/pandokia_fct.h +0 -0
- {drizzle-2.1.0 → drizzle-2.1.1}/src/tests/utest_cdrizzle.c +0 -0
- {drizzle-2.1.0 → drizzle-2.1.1}/tox.ini +0 -0
|
@@ -8,7 +8,7 @@ on:
|
|
|
8
8
|
|
|
9
9
|
jobs:
|
|
10
10
|
build:
|
|
11
|
-
uses: OpenAstronomy/github-actions-workflows/.github/workflows/publish.yml@
|
|
11
|
+
uses: OpenAstronomy/github-actions-workflows/.github/workflows/publish.yml@v2
|
|
12
12
|
with:
|
|
13
13
|
upload_to_pypi: ${{ (github.event_name == 'release') && (github.event.action == 'released') }}
|
|
14
14
|
targets: |
|
|
@@ -5,10 +5,34 @@ Release Notes
|
|
|
5
5
|
=============
|
|
6
6
|
|
|
7
7
|
|
|
8
|
+
2.1.1 (2025-08-14)
|
|
9
|
+
==================
|
|
10
|
+
|
|
11
|
+
- Fix a bug in the Cython code for ``tdriz()`` due to which the code would
|
|
12
|
+
raise an error for sub-second exposure times. [#192]
|
|
13
|
+
|
|
14
|
+
- Fixed a numerical instability in the new and old "boxer" algorithm in #175
|
|
15
|
+
(withdrawn release 2.1.0). [#191]
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
2.1.0 (2025-02-20; withdrawn)
|
|
19
|
+
=============================
|
|
20
|
+
|
|
21
|
+
- Restored faster "boxer" overlap for square kernel, improving resample speed;
|
|
22
|
+
optimized and simplified related code. [#175]
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
2.1.1 (unreleased)
|
|
26
|
+
==================
|
|
27
|
+
|
|
28
|
+
- Fixed a bug in polygon intersection algorithm that could result in
|
|
29
|
+
incorrect output when the input polygons have nearly collinear edges. [#194]
|
|
30
|
+
|
|
31
|
+
|
|
8
32
|
2.0.2 (unreleased)
|
|
9
33
|
==================
|
|
10
34
|
|
|
11
|
-
-
|
|
35
|
+
- Fixed a bug in ``resample.Drizzle`` due to which initially, before adding
|
|
12
36
|
the first image, ``Drizzle.output_img`` is not filled with ``NaN`` when
|
|
13
37
|
``fillval`` is either ``INDEF``, ``NAN``, ``None`` *and* the ``Drizzle``
|
|
14
38
|
object was initialized with ``out_img=None``. [#170]
|
|
@@ -260,3 +260,27 @@ def test_intersection_case01():
|
|
|
260
260
|
cp = clip_polygon(p, wnd)
|
|
261
261
|
|
|
262
262
|
assert _is_poly_eq(cp, cp_ref)
|
|
263
|
+
|
|
264
|
+
|
|
265
|
+
def test_intersection_case02():
|
|
266
|
+
# a real case of failure reported in #189
|
|
267
|
+
p = [
|
|
268
|
+
(-0.04000000000000009104, 1.5),
|
|
269
|
+
(2.73499999999999943157, 1.5),
|
|
270
|
+
(1.83500000000000018652, -0.5),
|
|
271
|
+
(-0.03999999999999998002, -0.5),
|
|
272
|
+
]
|
|
273
|
+
wnd = [
|
|
274
|
+
(-0.5, -0.5), (3.5, -0.5), (3.5, 3.5), (-0.5, 3.5)
|
|
275
|
+
]
|
|
276
|
+
|
|
277
|
+
cp_ref = [
|
|
278
|
+
(-0.04, 1.5),
|
|
279
|
+
(-0.04, -0.5),
|
|
280
|
+
(1.835, -0.5),
|
|
281
|
+
(2.735, 1.5),
|
|
282
|
+
]
|
|
283
|
+
|
|
284
|
+
cp = clip_polygon(p, wnd)
|
|
285
|
+
|
|
286
|
+
assert _is_poly_eq(cp, cp_ref)
|
|
@@ -286,6 +286,7 @@ def test_drizzle_defaults():
|
|
|
286
286
|
assert driz.out_img[1, 2] == 1
|
|
287
287
|
assert (driz.out_img[2, 1] - 2.0) < 1.0e-14
|
|
288
288
|
|
|
289
|
+
|
|
289
290
|
@pytest.mark.parametrize(
|
|
290
291
|
'kernel,test_image_type,max_diff_atol',
|
|
291
292
|
[
|
|
@@ -355,7 +356,10 @@ def test_resample_kernel(tmpdir, kernel, test_image_type, max_diff_atol):
|
|
|
355
356
|
scale=pscale_ratio,
|
|
356
357
|
)
|
|
357
358
|
else:
|
|
358
|
-
with pytest.warns(
|
|
359
|
+
with pytest.warns(
|
|
360
|
+
Warning,
|
|
361
|
+
match=f"Kernel '{kernel}' is not a flux-conserving kernel"
|
|
362
|
+
):
|
|
359
363
|
driz.add_image(
|
|
360
364
|
insci,
|
|
361
365
|
exptime=1.0,
|
|
@@ -486,7 +490,10 @@ def test_zero_input_weight(kernel, fc):
|
|
|
486
490
|
fillstr='INDEF',
|
|
487
491
|
)
|
|
488
492
|
else:
|
|
489
|
-
with pytest.warns(
|
|
493
|
+
with pytest.warns(
|
|
494
|
+
Warning,
|
|
495
|
+
match=f"Kernel '{kernel}' is not a flux-conserving kernel"
|
|
496
|
+
):
|
|
490
497
|
cdrizzle.tdriz(
|
|
491
498
|
insci,
|
|
492
499
|
inwht,
|
|
@@ -760,7 +767,10 @@ def test_flux_conservation_nondistorted(kernel, fc):
|
|
|
760
767
|
wtscale=1.0,
|
|
761
768
|
)
|
|
762
769
|
else:
|
|
763
|
-
with pytest.warns(
|
|
770
|
+
with pytest.warns(
|
|
771
|
+
Warning,
|
|
772
|
+
match=f"Kernel '{kernel}' is not a flux-conserving kernel"
|
|
773
|
+
):
|
|
764
774
|
cdrizzle.tdriz(
|
|
765
775
|
in_sci,
|
|
766
776
|
in_wht,
|
|
@@ -848,7 +858,10 @@ def test_flux_conservation_distorted(kernel, fc):
|
|
|
848
858
|
wtscale=1.0,
|
|
849
859
|
)
|
|
850
860
|
else:
|
|
851
|
-
with pytest.warns(
|
|
861
|
+
with pytest.warns(
|
|
862
|
+
Warning,
|
|
863
|
+
match=f"Kernel '{kernel}' is not a flux-conserving kernel"
|
|
864
|
+
):
|
|
852
865
|
cdrizzle.tdriz(
|
|
853
866
|
in_sci,
|
|
854
867
|
in_wht,
|
|
@@ -1138,7 +1151,7 @@ def test_resample_get_shape_from_pixmap():
|
|
|
1138
1151
|
exptime=0.0,
|
|
1139
1152
|
)
|
|
1140
1153
|
|
|
1141
|
-
driz.add_image(in_sci, weight_map=in_wht, exptime=1
|
|
1154
|
+
driz.add_image(in_sci, weight_map=in_wht, exptime=0.1, pixmap=pixmap)
|
|
1142
1155
|
assert driz.out_img.shape == in_shape
|
|
1143
1156
|
|
|
1144
1157
|
|
|
@@ -1223,3 +1236,115 @@ def test_nan_fillval(fillval):
|
|
|
1223
1236
|
)
|
|
1224
1237
|
|
|
1225
1238
|
assert np.all(np.isnan(driz.out_img))
|
|
1239
|
+
|
|
1240
|
+
|
|
1241
|
+
def test_resample_edge_sgarea_bug():
|
|
1242
|
+
"""
|
|
1243
|
+
Test from https://github.com/spacetelescope/drizzle/issues/187
|
|
1244
|
+
|
|
1245
|
+
"""
|
|
1246
|
+
pixmap = (np.array([
|
|
1247
|
+
[
|
|
1248
|
+
[0.31887051, 1.],
|
|
1249
|
+
[1.01898591, 1.],
|
|
1250
|
+
[1.71909665, 1.],
|
|
1251
|
+
],
|
|
1252
|
+
[
|
|
1253
|
+
[0.31591881, 0.],
|
|
1254
|
+
[1.0160342312345672, 0.],
|
|
1255
|
+
[1.716145, 0.],
|
|
1256
|
+
]
|
|
1257
|
+
], dtype="f8"))
|
|
1258
|
+
|
|
1259
|
+
in_shape = pixmap.shape[:2]
|
|
1260
|
+
img = np.full(in_shape, 42, dtype=np.float32)
|
|
1261
|
+
out_shape = (4, 4)
|
|
1262
|
+
|
|
1263
|
+
driz = resample.Drizzle(
|
|
1264
|
+
kernel='square',
|
|
1265
|
+
fillval='nan',
|
|
1266
|
+
out_shape=out_shape,
|
|
1267
|
+
disable_ctx=True,
|
|
1268
|
+
)
|
|
1269
|
+
|
|
1270
|
+
driz.add_image(
|
|
1271
|
+
img,
|
|
1272
|
+
exptime=11.776,
|
|
1273
|
+
in_units='cps',
|
|
1274
|
+
pixfrac=1.0,
|
|
1275
|
+
pixmap=pixmap,
|
|
1276
|
+
scale=1.0,
|
|
1277
|
+
wht_scale=1.0,
|
|
1278
|
+
)
|
|
1279
|
+
# expected pixels should be close to 42
|
|
1280
|
+
np.testing.assert_allclose(driz.out_img[:2, :3], img[0, 0], rtol=1e-6)
|
|
1281
|
+
|
|
1282
|
+
# other values should be nan
|
|
1283
|
+
np.testing.assert_equal(driz.out_img[:, 3:], np.nan)
|
|
1284
|
+
np.testing.assert_equal(driz.out_img[2:], np.nan)
|
|
1285
|
+
|
|
1286
|
+
|
|
1287
|
+
def test_resample_edge_collinear():
|
|
1288
|
+
"""
|
|
1289
|
+
Test that resample does not crash when the input image is smaller than the
|
|
1290
|
+
output image, and the edges of the two images are nearly collinear.
|
|
1291
|
+
|
|
1292
|
+
Test based on the example from
|
|
1293
|
+
https://github.com/spacetelescope/drizzle/issues/189#issue-3196294879
|
|
1294
|
+
|
|
1295
|
+
"""
|
|
1296
|
+
pixmap = (np.array([
|
|
1297
|
+
[
|
|
1298
|
+
[0.31, 1.0],
|
|
1299
|
+
[1.01, 1.0],
|
|
1300
|
+
[2.01, 1.0],
|
|
1301
|
+
],
|
|
1302
|
+
[
|
|
1303
|
+
[0.31, 0.],
|
|
1304
|
+
[1.01, 0.],
|
|
1305
|
+
[1.71, 0.],
|
|
1306
|
+
]
|
|
1307
|
+
], dtype="f8"))
|
|
1308
|
+
|
|
1309
|
+
in_shape = pixmap.shape[:2]
|
|
1310
|
+
img = np.full(in_shape, np.pi, dtype=np.float32)
|
|
1311
|
+
in_flux = np.sum(img)
|
|
1312
|
+
out_shape = (4, 4)
|
|
1313
|
+
|
|
1314
|
+
driz = resample.Drizzle(
|
|
1315
|
+
kernel='square',
|
|
1316
|
+
fillval='nan',
|
|
1317
|
+
out_shape=out_shape,
|
|
1318
|
+
disable_ctx=True,
|
|
1319
|
+
)
|
|
1320
|
+
|
|
1321
|
+
driz.add_image(
|
|
1322
|
+
img,
|
|
1323
|
+
exptime=11.776,
|
|
1324
|
+
in_units='cps',
|
|
1325
|
+
pixfrac=1.0,
|
|
1326
|
+
pixmap=pixmap,
|
|
1327
|
+
scale=1.0,
|
|
1328
|
+
wht_scale=1.0,
|
|
1329
|
+
)
|
|
1330
|
+
|
|
1331
|
+
out_flux = np.nansum(driz.out_img * driz.out_wht)
|
|
1332
|
+
|
|
1333
|
+
# Given this pixmap, the entire input image should fit within the output
|
|
1334
|
+
# image. There should be at least 7 pixels with finite values in the output
|
|
1335
|
+
# image. We can get more than 7 pixels with finite values due to rounding
|
|
1336
|
+
# errors when computing polygon intersections (those "extra" pixels should)
|
|
1337
|
+
# have very small weights.
|
|
1338
|
+
assert np.sum(driz.out_wht > 1e-30) == 7
|
|
1339
|
+
assert np.sum(np.isfinite(driz.out_img)) >= 7
|
|
1340
|
+
# output image intensity must be equal to the input image intensity:
|
|
1341
|
+
assert np.allclose(
|
|
1342
|
+
driz.out_img[np.isfinite(driz.out_img)],
|
|
1343
|
+
img[0, 0],
|
|
1344
|
+
rtol=0,
|
|
1345
|
+
atol=1e-6
|
|
1346
|
+
)
|
|
1347
|
+
# flux in the output image should be equal to the flux in the input image:
|
|
1348
|
+
assert np.allclose(out_flux, in_flux, rtol=1e-6, atol=0.0)
|
|
1349
|
+
# area of the signal in the input image:
|
|
1350
|
+
assert np.allclose(np.sum(driz.out_wht), 6.0, rtol=0, atol=1.0e-6)
|
|
@@ -230,19 +230,29 @@ tdriz(PyObject *obj UNUSED_PARAM, PyObject *args, PyObject *keywords) {
|
|
|
230
230
|
p.fill_value = fill_value;
|
|
231
231
|
p.error = &error;
|
|
232
232
|
|
|
233
|
-
if (driz_error_check(&error, "xmin must be >= 0", p.xmin >= 0))
|
|
234
|
-
if (driz_error_check(&error, "ymin must be >= 0", p.ymin >= 0)) goto _exit;
|
|
235
|
-
if (driz_error_check(&error, "xmax must be > xmin", p.xmax > p.xmin))
|
|
233
|
+
if (driz_error_check(&error, "xmin must be >= 0", p.xmin >= 0)) {
|
|
236
234
|
goto _exit;
|
|
237
|
-
|
|
235
|
+
}
|
|
236
|
+
if (driz_error_check(&error, "ymin must be >= 0", p.ymin >= 0)) {
|
|
238
237
|
goto _exit;
|
|
239
|
-
|
|
238
|
+
}
|
|
239
|
+
if (driz_error_check(&error, "xmax must be > xmin", p.xmax > p.xmin)) {
|
|
240
240
|
goto _exit;
|
|
241
|
-
|
|
241
|
+
}
|
|
242
|
+
if (driz_error_check(&error, "ymax must be > ymin", p.ymax > p.ymin)) {
|
|
243
|
+
goto _exit;
|
|
244
|
+
}
|
|
245
|
+
if (driz_error_check(&error, "scale must be > 0", p.scale > 0.0f)) {
|
|
242
246
|
goto _exit;
|
|
247
|
+
}
|
|
248
|
+
if (driz_error_check(&error, "exposure time must be > 0",
|
|
249
|
+
p.exposure_time > 0.0f)) {
|
|
250
|
+
goto _exit;
|
|
251
|
+
}
|
|
243
252
|
if (driz_error_check(&error, "weight scale must be > 0",
|
|
244
|
-
p.weight_scale > 0.
|
|
253
|
+
p.weight_scale > 0.0f)) {
|
|
245
254
|
goto _exit;
|
|
255
|
+
}
|
|
246
256
|
|
|
247
257
|
get_dimensions(p.pixmap, psize);
|
|
248
258
|
if (psize[0] != isize[0] || psize[1] != isize[1]) {
|
|
@@ -88,75 +88,98 @@ This is used by BOXER.
|
|
|
88
88
|
*/
|
|
89
89
|
|
|
90
90
|
static inline_macro double
|
|
91
|
-
sgarea(const double x1, const double y1, const double x2, const double y2
|
|
92
|
-
|
|
93
|
-
|
|
91
|
+
sgarea(const double x1, const double y1, const double x2, const double y2) {
|
|
92
|
+
double xlo, xhi, ylo, yhi, xtop;
|
|
93
|
+
double dx, dy, det, sgn_dx;
|
|
94
94
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
return 0.0;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
if (sgn_dx < 0) {
|
|
101
|
-
xlo = x2;
|
|
102
|
-
xhi = x1;
|
|
103
|
-
} else {
|
|
104
|
-
xlo = x1;
|
|
105
|
-
xhi = x2;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
/* And determine the bounds ignoring y for now */
|
|
109
|
-
if (xlo >= 1.0 || xhi <= 0.0) {
|
|
110
|
-
return 0.0;
|
|
111
|
-
}
|
|
95
|
+
dx = x2 - x1;
|
|
96
|
+
dy = y2 - y1;
|
|
112
97
|
|
|
113
|
-
|
|
114
|
-
|
|
98
|
+
/* Trap vertical line */
|
|
99
|
+
if (dx == 0) {
|
|
100
|
+
return 0.0;
|
|
101
|
+
}
|
|
115
102
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
103
|
+
if (dx < 0) {
|
|
104
|
+
sgn_dx = -1.0;
|
|
105
|
+
xlo = x2;
|
|
106
|
+
xhi = x1;
|
|
107
|
+
} else {
|
|
108
|
+
sgn_dx = 1.0;
|
|
109
|
+
xlo = x1;
|
|
110
|
+
xhi = x2;
|
|
111
|
+
}
|
|
120
112
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
/*
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
113
|
+
/* And determine the bounds ignoring y for now */
|
|
114
|
+
if (xlo >= 1.0 || xhi <= 0.0) {
|
|
115
|
+
return 0.0;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
xlo = MAX(xlo, 0.0);
|
|
119
|
+
xhi = MIN(xhi, 1.0);
|
|
120
|
+
|
|
121
|
+
/* Now look at y */
|
|
122
|
+
double slope = dy / dx;
|
|
123
|
+
ylo = y1 + slope * (xlo - x1);
|
|
124
|
+
yhi = y1 + slope * (xhi - x1);
|
|
125
|
+
|
|
126
|
+
/* Alternative code that may be more stable under certain circumstances */
|
|
127
|
+
/*
|
|
128
|
+
if (xlo < 0.0) {
|
|
129
|
+
xlo = 0.0;
|
|
130
|
+
ylo = y1 + (dy / dx) * (xlo - x1);
|
|
131
|
+
} else {
|
|
132
|
+
ylo = (sgn_dx > 0.0) ? y1 : y2;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
if (xhi > 1.0) {
|
|
136
|
+
xhi = 1.0;
|
|
137
|
+
yhi = y1 + (dy / dx) * (xhi - x1);
|
|
138
|
+
} else {
|
|
139
|
+
yhi = (sgn_dx > 0.0) ? y2 : y1;
|
|
140
|
+
}
|
|
141
|
+
*/
|
|
142
|
+
|
|
143
|
+
/* Trap segment entirely below axis */
|
|
144
|
+
if (ylo <= 0.0 && yhi <= 0.0) {
|
|
145
|
+
return 0.0;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/* There are four possibilities: both y below 1, both y above 1 and
|
|
149
|
+
one of each. */
|
|
150
|
+
if (ylo >= 1.0 && yhi >= 1.0) {
|
|
151
|
+
/* Line segment is entirely above square */
|
|
152
|
+
return sgn_dx * (xhi - xlo);
|
|
151
153
|
}
|
|
152
154
|
|
|
153
|
-
|
|
154
|
-
xtop = (1.0 - c) * inv_slope;
|
|
155
|
-
return sgn_dx * (0.5 * (xtop - xlo) * (1.0 + ylo) + xhi - xtop);
|
|
156
|
-
}
|
|
155
|
+
det = x1 * y2 - y1 * x2;
|
|
157
156
|
|
|
158
|
-
|
|
159
|
-
|
|
157
|
+
/* Adjust bounds if segment crosses axis (to exclude anything below
|
|
158
|
+
axis) */
|
|
159
|
+
if (ylo < 0.0) {
|
|
160
|
+
ylo = 0.0;
|
|
161
|
+
xlo = det / dy;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
if (yhi < 0.0) {
|
|
165
|
+
yhi = 0.0;
|
|
166
|
+
xhi = det / dy;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
if (ylo <= 1.0) {
|
|
170
|
+
if (yhi <= 1.0) {
|
|
171
|
+
/* Segment is entirely within the square.
|
|
172
|
+
The case of zero slope will end up here. */
|
|
173
|
+
return sgn_dx * 0.5 * (xhi - xlo) * (yhi + ylo);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/* Otherwise, it must cross the top of the square */
|
|
177
|
+
xtop = (dx + det) / dy;
|
|
178
|
+
return sgn_dx * (0.5 * (xtop - xlo) * (1.0 + ylo) + xhi - xtop);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
xtop = (dx + det) / dy;
|
|
182
|
+
return sgn_dx * (0.5 * (xhi - xtop) * (1.0 + yhi) + xtop - xlo);
|
|
160
183
|
}
|
|
161
184
|
|
|
162
185
|
/**
|
|
@@ -170,37 +193,34 @@ sgarea(const double x1, const double y1, const double x2, const double y2,
|
|
|
170
193
|
*/
|
|
171
194
|
|
|
172
195
|
double
|
|
173
|
-
boxer(double is, double js,
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
return sum;
|
|
196
|
+
boxer(double is, double js, const double x[4], const double y[4]) {
|
|
197
|
+
integer_t i;
|
|
198
|
+
double sum;
|
|
199
|
+
double px[4], py[4];
|
|
200
|
+
|
|
201
|
+
assert(x);
|
|
202
|
+
assert(y);
|
|
203
|
+
|
|
204
|
+
is -= 0.5;
|
|
205
|
+
js -= 0.5;
|
|
206
|
+
/* Set up coords relative to unit square at origin Note that the
|
|
207
|
+
+0.5s were added when this code was included in DRIZZLE */
|
|
208
|
+
|
|
209
|
+
for (i = 0; i < 4; ++i) {
|
|
210
|
+
px[i] = x[i] - is;
|
|
211
|
+
py[i] = y[i] - js;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/* For each line in the polygon (or at this stage, input
|
|
215
|
+
quadrilateral) calculate the area common to the unit square
|
|
216
|
+
(allow negative area for subsequent `vector' addition of
|
|
217
|
+
subareas). */
|
|
218
|
+
sum = 0.0;
|
|
219
|
+
for (i = 0; i < 4; ++i) {
|
|
220
|
+
sum += sgarea(px[i], py[i], px[(i + 1) & 0x3], py[(i + 1) & 0x3]);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
return sum;
|
|
204
224
|
}
|
|
205
225
|
|
|
206
226
|
/** ---------------------------------------------------------------------------
|
|
@@ -284,8 +304,7 @@ compute_area(double is, double js, const double x[4], const double y[4]) {
|
|
|
284
304
|
* segment inside the square
|
|
285
305
|
*/
|
|
286
306
|
width = segment[1][0] - segment[0][0];
|
|
287
|
-
area += 0.5 * width *
|
|
288
|
-
((1.0 + delta[0]) + (1.0 + delta[1]));
|
|
307
|
+
area += 0.5 * width * (2.0 + delta[0] + delta[1]);
|
|
289
308
|
}
|
|
290
309
|
}
|
|
291
310
|
|
|
@@ -313,14 +332,14 @@ compute_area(double is, double js, const double x[4], const double y[4]) {
|
|
|
313
332
|
width = segment[1][0] - midpoint[0];
|
|
314
333
|
/* Delta[0] is at the crossing point and thus zero
|
|
315
334
|
*/
|
|
316
|
-
area += 0.5 * width * (
|
|
335
|
+
area += 0.5 * width * (2.0 + delta[1]);
|
|
317
336
|
} else {
|
|
318
337
|
width = segment[1][0] - midpoint[0];
|
|
319
338
|
area += width;
|
|
320
339
|
width = midpoint[0] - segment[0][0];
|
|
321
340
|
/* Delta[1] is at the crossing point and thus zero
|
|
322
341
|
*/
|
|
323
|
-
area += 0.5 * width * (
|
|
342
|
+
area += 0.5 * width * (2.0 + delta[0]);
|
|
324
343
|
}
|
|
325
344
|
|
|
326
345
|
} else {
|
|
@@ -873,10 +892,8 @@ do_kernel_square(struct driz_param_t *p) {
|
|
|
873
892
|
integer_t bv, i, j, ii, jj, min_ii, max_ii, min_jj, max_jj, nhit;
|
|
874
893
|
integer_t osize[2], mapsize[2];
|
|
875
894
|
float scale2, vc, d, dow;
|
|
876
|
-
double dh, jaco, dover, w
|
|
895
|
+
double dh, jaco, dover, w;
|
|
877
896
|
double xin[4], yin[4], xout[4], yout[4];
|
|
878
|
-
double slope[4], inv_slope[4];
|
|
879
|
-
int sgn_dx[4];
|
|
880
897
|
|
|
881
898
|
struct scanner s;
|
|
882
899
|
int xmin, xmax, ymin, ymax, n;
|
|
@@ -918,32 +935,40 @@ do_kernel_square(struct driz_param_t *p) {
|
|
|
918
935
|
}
|
|
919
936
|
|
|
920
937
|
/* Set the input corner positions */
|
|
921
|
-
|
|
922
938
|
yin[1] = yin[0] = (double)j + dh;
|
|
923
939
|
yin[3] = yin[2] = (double)j - dh;
|
|
924
940
|
|
|
925
941
|
for (i = xmin; i <= xmax; ++i) {
|
|
926
942
|
nhit = 0;
|
|
927
943
|
|
|
928
|
-
xin[3] = xin[0] = (double)i - dh;
|
|
929
|
-
xin[2] = xin[1] = (double)i + dh;
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
944
|
+
// xin[3] = xin[0] = (double)i - dh;
|
|
945
|
+
// xin[2] = xin[1] = (double)i + dh;
|
|
946
|
+
|
|
947
|
+
// for (ii = 0; ii < 4; ++ii) {
|
|
948
|
+
// if (interpolate_point(p, xin[ii], yin[ii], xout + ii,
|
|
949
|
+
// yout + ii)) {
|
|
950
|
+
// goto _miss;
|
|
951
|
+
// }
|
|
952
|
+
// }
|
|
953
|
+
|
|
954
|
+
/* Assuming we don't need to extrapolate, call a more
|
|
955
|
+
* efficient interpolator that takes advantage of the fact
|
|
956
|
+
* that pixfrac<1 and that we are using a square grid.
|
|
957
|
+
*/
|
|
958
|
+
if (i > 0 && i < mapsize[0] - 2 && j > 0 && j < mapsize[1] - 2) {
|
|
959
|
+
if (interpolate_four_points(p, i, j, dh, xout, xout + 1,
|
|
960
|
+
xout + 2, xout + 3, yout, yout + 1,
|
|
961
|
+
yout + 2, yout + 3))
|
|
962
|
+
goto _miss;
|
|
963
|
+
} else {
|
|
964
|
+
xin[3] = xin[0] = (double)i - dh;
|
|
965
|
+
xin[2] = xin[1] = (double)i + dh;
|
|
966
|
+
for (ii = 0; ii < 4; ++ii) {
|
|
942
967
|
if (interpolate_point(p, xin[ii], yin[ii], xout + ii,
|
|
943
968
|
yout + ii))
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
969
|
+
goto _miss;
|
|
970
|
+
}
|
|
971
|
+
}
|
|
947
972
|
|
|
948
973
|
/* Work out the area of the quadrilateral on the output
|
|
949
974
|
* grid. If the points are in clockwise order we get a
|
|
@@ -951,7 +976,7 @@ do_kernel_square(struct driz_param_t *p) {
|
|
|
951
976
|
* will be negative, but so will the areas computed by
|
|
952
977
|
* boxer, so it doesn't actually matter once we divide it
|
|
953
978
|
* out.
|
|
954
|
-
|
|
979
|
+
*/
|
|
955
980
|
|
|
956
981
|
jaco = 0.5f * ((xout[1] - xout[3]) * (yout[0] - yout[2]) -
|
|
957
982
|
(xout[0] - xout[2]) * (yout[1] - yout[3]));
|
|
@@ -967,38 +992,20 @@ do_kernel_square(struct driz_param_t *p) {
|
|
|
967
992
|
w = 1.0 / jaco;
|
|
968
993
|
}
|
|
969
994
|
|
|
970
|
-
/* Pre-compute slopes and sign of dx for each segment,
|
|
971
|
-
since they will be used for all pixels in the loop.
|
|
972
|
-
Also compute the inverse of the slope to avoid more
|
|
973
|
-
division calls later.
|
|
974
|
-
*/
|
|
975
|
-
|
|
976
|
-
for (ii = 0; ii < 4; ii++) {
|
|
977
|
-
dx = xout[(ii+1) & 0x3] - xout[ii];
|
|
978
|
-
dy = yout[(ii+1) & 0x3] - yout[ii];
|
|
979
|
-
if (dx >= 0) {
|
|
980
|
-
sgn_dx[ii] = 1;
|
|
981
|
-
} else {
|
|
982
|
-
sgn_dx[ii] = -1;
|
|
983
|
-
}
|
|
984
|
-
slope[ii] = dy / dx;
|
|
985
|
-
inv_slope[ii] = dx / dy;
|
|
986
|
-
}
|
|
987
|
-
|
|
988
995
|
/* Loop over output pixels which could be affected */
|
|
989
996
|
min_jj = MAX(fortran_round(min_doubles(yout, 4)), 0);
|
|
990
997
|
max_jj = MIN(fortran_round(max_doubles(yout, 4)), osize[1] - 1);
|
|
991
998
|
min_ii = MAX(fortran_round(min_doubles(xout, 4)), 0);
|
|
992
999
|
max_ii = MIN(fortran_round(max_doubles(xout, 4)), osize[0] - 1);
|
|
993
1000
|
|
|
994
|
-
|
|
995
|
-
|
|
1001
|
+
for (jj = min_jj; jj <= max_jj; ++jj) {
|
|
1002
|
+
for (ii = min_ii; ii <= max_ii; ++ii) {
|
|
996
1003
|
/* Call boxer to calculate overlap */
|
|
997
|
-
//dover = compute_area((double)ii, (double)jj, xout, yout);
|
|
998
|
-
|
|
999
|
-
sgn_dx, slope, inv_slope);
|
|
1004
|
+
// dover = compute_area((double)ii, (double)jj, xout, yout);
|
|
1005
|
+
dover = boxer((double)ii, (double)jj, xout, yout);
|
|
1000
1006
|
|
|
1001
|
-
|
|
1007
|
+
/* Could be positive or negative, depending on the sign of
|
|
1008
|
+
* jaco */
|
|
1002
1009
|
if (dover != 0.0) {
|
|
1003
1010
|
vc = get_pixel(p->output_counts, ii, jj);
|
|
1004
1011
|
|
|
@@ -1008,7 +1015,7 @@ do_kernel_square(struct driz_param_t *p) {
|
|
|
1008
1015
|
++nhit;
|
|
1009
1016
|
|
|
1010
1017
|
/* If we are creating or modifying the context image we
|
|
1011
|
-
|
|
1018
|
+
do so here */
|
|
1012
1019
|
if (p->output_context && dow > 0.0) {
|
|
1013
1020
|
set_bit(p->output_context, ii, jj, bv);
|
|
1014
1021
|
}
|
|
@@ -25,9 +25,7 @@ int dobox(struct driz_param_t *p);
|
|
|
25
25
|
|
|
26
26
|
double compute_area(double is, double js, const double x[4], const double y[4]);
|
|
27
27
|
|
|
28
|
-
double boxer(double is, double js, const double x[4], const double y[4]
|
|
29
|
-
const int sgn_dx[4], const double slope[4],
|
|
30
|
-
const double inv_slope[4]);
|
|
28
|
+
double boxer(double is, double js, const double x[4], const double y[4]);
|
|
31
29
|
|
|
32
30
|
typedef int (*kernel_handler_t)(struct driz_param_t *);
|
|
33
31
|
|
|
@@ -19,6 +19,22 @@ static const double VERTEX_ATOL = 1.0e-12;
|
|
|
19
19
|
static const double APPROX_ZERO = 1.0e3 * DBL_MIN;
|
|
20
20
|
static const double MAX_INV_ERR = 0.03;
|
|
21
21
|
|
|
22
|
+
void
|
|
23
|
+
debug_print_polygon(const struct polygon *p, char *msg) {
|
|
24
|
+
int i;
|
|
25
|
+
if (msg) {
|
|
26
|
+
printf("%s\n", msg);
|
|
27
|
+
}
|
|
28
|
+
printf("Polygon with %d vertices:\n", p->npv);
|
|
29
|
+
for (i = 0; i < p->npv; ++i) {
|
|
30
|
+
printf(" Vertex %d: (%.20f, %.20f)\n", i, p->v[i].x, p->v[i].y);
|
|
31
|
+
}
|
|
32
|
+
printf("\n");
|
|
33
|
+
fflush(stdout);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
void rotate_polygon(struct polygon *p, int pos);
|
|
37
|
+
|
|
22
38
|
/** ---------------------------------------------------------------------------
|
|
23
39
|
* Find the tighest bounding box around valid (finite) pixmap values.
|
|
24
40
|
*
|
|
@@ -178,10 +194,10 @@ interpolate_point(struct driz_param_t *par, double xin, double yin,
|
|
|
178
194
|
* four x points, then four y points.
|
|
179
195
|
*/
|
|
180
196
|
int
|
|
181
|
-
interpolate_four_points(struct driz_param_t *par,
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
197
|
+
interpolate_four_points(struct driz_param_t *par, int ixcen, int iycen,
|
|
198
|
+
double h, double *x1, double *x2, double *x3,
|
|
199
|
+
double *x4, double *y1, double *y2, double *y3,
|
|
200
|
+
double *y4) {
|
|
185
201
|
int i, j, nx2, ny2;
|
|
186
202
|
double fac;
|
|
187
203
|
npy_intp *ndim;
|
|
@@ -205,30 +221,30 @@ interpolate_four_points(struct driz_param_t *par,
|
|
|
205
221
|
* center point, given by i=j=1 below. Loop ordered for speed
|
|
206
222
|
* based on numpy array order.
|
|
207
223
|
*/
|
|
224
|
+
ixcen -= 1;
|
|
225
|
+
iycen -= 1;
|
|
208
226
|
assert(h <= 1);
|
|
209
|
-
assert(ixcen >=
|
|
210
|
-
|
|
211
|
-
for (j = 0; j <= 2; j
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
g[i][j] = p[1] * fac;
|
|
225
|
-
}
|
|
227
|
+
assert(ixcen >= 0 && iycen >= 0 && ixcen < nx2 && iycen < ny2);
|
|
228
|
+
|
|
229
|
+
for (j = 0; j <= 2; ++j) {
|
|
230
|
+
for (i = 0; i <= 2; ++i) {
|
|
231
|
+
p = get_pixmap(pixmap, i + ixcen, j + iycen);
|
|
232
|
+
if (i == 1 && j == 1) {
|
|
233
|
+
fac = (1 - h) * (1 - h);
|
|
234
|
+
} else if (i == 1 || j == 1) {
|
|
235
|
+
fac = (1 - h) * h;
|
|
236
|
+
} else {
|
|
237
|
+
fac = h * h;
|
|
238
|
+
}
|
|
239
|
+
f[i][j] = p[0] * fac;
|
|
240
|
+
g[i][j] = p[1] * fac;
|
|
241
|
+
}
|
|
226
242
|
}
|
|
227
243
|
|
|
228
244
|
/* We return the vertices of a square going clockwise in the
|
|
229
245
|
* original pixel grid.
|
|
230
246
|
* Order in y: +h, +h, -h, -h; order in x: -h, +h, +h, -h
|
|
231
|
-
|
|
247
|
+
*/
|
|
232
248
|
|
|
233
249
|
*x1 = f[0][1] + f[1][1] + f[0][2] + f[1][2];
|
|
234
250
|
*y1 = g[0][1] + g[1][1] + g[0][2] + g[1][2];
|
|
@@ -242,17 +258,16 @@ interpolate_four_points(struct driz_param_t *par,
|
|
|
242
258
|
*x4 = f[0][0] + f[1][0] + f[0][1] + f[1][1];
|
|
243
259
|
*y4 = g[0][0] + g[1][0] + g[0][1] + g[1][1];
|
|
244
260
|
|
|
245
|
-
if (npy_isnan(*x1) || npy_isnan(*y1) ||
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
261
|
+
if (npy_isnan(*x1) || npy_isnan(*y1) || npy_isnan(*x2) || npy_isnan(*y2) ||
|
|
262
|
+
npy_isnan(*x3) || npy_isnan(*y3) || npy_isnan(*x4) || npy_isnan(*y4)) {
|
|
263
|
+
return 1;
|
|
264
|
+
}
|
|
249
265
|
|
|
250
266
|
return 0;
|
|
251
267
|
}
|
|
252
268
|
|
|
253
269
|
/** ---------------------------------------------------------------------------
|
|
254
270
|
* Map an integer pixel position from the input to the output image.
|
|
255
|
-
* Fall back on interpolation if the value at the point is undefined
|
|
256
271
|
*
|
|
257
272
|
* pixmap: The mapping of the pixel centers from input to output image
|
|
258
273
|
* i - The index of the x coordinate
|
|
@@ -260,7 +275,6 @@ interpolate_four_points(struct driz_param_t *par,
|
|
|
260
275
|
* x - X-coordinate of the point on the output image (output)
|
|
261
276
|
* y - Y-coordinate of the point on the output image (output)
|
|
262
277
|
*/
|
|
263
|
-
|
|
264
278
|
int
|
|
265
279
|
map_pixel(PyArrayObject *pixmap, int i, int j, double *x, double *y) {
|
|
266
280
|
double *pv = (double *)PyArray_GETPTR3(pixmap, j, i, 0);
|
|
@@ -442,6 +456,38 @@ is_point_strictly_in_hp(const struct vertex pt, const struct vertex v_,
|
|
|
442
456
|
return ((area(v, pt) - area(v_, pt) - area(v, v_)) > 0.0);
|
|
443
457
|
}
|
|
444
458
|
|
|
459
|
+
/**
|
|
460
|
+
* Rotates the vertices of a polygon by a specified number of positions.
|
|
461
|
+
*
|
|
462
|
+
* This function shifts the vertices of the given polygon `p` by `pos`
|
|
463
|
+
* positions. For each rotation, the first vertex is moved to the end of the
|
|
464
|
+
* vertex array, effectively rotating the polygon's vertex order. The operation
|
|
465
|
+
* is performed in-place and repeated `pos` times.
|
|
466
|
+
*
|
|
467
|
+
* @param p Pointer to the polygon structure to be rotated. The polygon is
|
|
468
|
+
* expected to have an array of vertices `v` and a count `npv`.
|
|
469
|
+
* @param pos Number of positions to rotate the polygon's vertices.
|
|
470
|
+
*/
|
|
471
|
+
void
|
|
472
|
+
rotate_polygon(struct polygon *p, int pos) {
|
|
473
|
+
int i, k, m;
|
|
474
|
+
double x, y;
|
|
475
|
+
|
|
476
|
+
for (i = 0; i < pos; ++i) {
|
|
477
|
+
// rotate polygon p by pos vertices
|
|
478
|
+
// (move first pos vertices to the end of the polygon)
|
|
479
|
+
x = p->v[0].x;
|
|
480
|
+
y = p->v[0].y;
|
|
481
|
+
for (k = 0; k < p->npv - 1; ++k) {
|
|
482
|
+
m = mod(k + 1, p->npv);
|
|
483
|
+
p->v[k].x = p->v[m].x;
|
|
484
|
+
p->v[k].y = p->v[m].y;
|
|
485
|
+
}
|
|
486
|
+
p->v[p->npv - 1].x = x;
|
|
487
|
+
p->v[p->npv - 1].y = y;
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
|
|
445
491
|
/**
|
|
446
492
|
* Append a vertex to a polygon.
|
|
447
493
|
*
|
|
@@ -619,12 +665,16 @@ clip_polygon_to_window(const struct polygon *p, const struct polygon *wnd,
|
|
|
619
665
|
// compute intersection point:
|
|
620
666
|
// https://en.wikipedia.org/wiki/Line–line_intersection
|
|
621
667
|
d = area(dp, dw); // d != 0 because (v2_inside != v1_inside)
|
|
668
|
+
|
|
622
669
|
app_ = area(*pv, *pv_);
|
|
623
670
|
aww_ = area(*wv, *wv_);
|
|
671
|
+
|
|
624
672
|
vi.x = (app_ * dw.x - aww_ * dp.x) / d;
|
|
625
673
|
vi.y = (app_ * dw.y - aww_ * dp.y) / d;
|
|
626
674
|
|
|
627
|
-
|
|
675
|
+
if (isfinite(vi.x) && isfinite(vi.y)) {
|
|
676
|
+
append_vertex(ppout, vi);
|
|
677
|
+
}
|
|
628
678
|
if (v2_inside) {
|
|
629
679
|
// outside to inside:
|
|
630
680
|
append_vertex(ppout, *pv);
|
|
@@ -633,6 +683,7 @@ clip_polygon_to_window(const struct polygon *p, const struct polygon *wnd,
|
|
|
633
683
|
// both edge vertices are inside
|
|
634
684
|
append_vertex(ppout, *pv);
|
|
635
685
|
}
|
|
686
|
+
|
|
636
687
|
// nothing to do when both edge vertices are outside
|
|
637
688
|
|
|
638
689
|
// advance polygon edge:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|