Calculate the illumination intensity for the normal vectors of a surface using the defined azimuth and elevation for the light source. Imagine an artificial sun placed at infinity in some azimuth and elevation position illuminating our surface. The parts of the surf
(self, normals, fraction=1.)
| 3912 | return self.shade_normals(normal, fraction) |
| 3913 | |
| 3914 | def shade_normals(self, normals, fraction=1.): |
| 3915 | """ |
| 3916 | Calculate the illumination intensity for the normal vectors of a |
| 3917 | surface using the defined azimuth and elevation for the light source. |
| 3918 | |
| 3919 | Imagine an artificial sun placed at infinity in some azimuth and |
| 3920 | elevation position illuminating our surface. The parts of the surface |
| 3921 | that slope toward the sun should brighten while those sides facing away |
| 3922 | should become darker. |
| 3923 | |
| 3924 | Parameters |
| 3925 | ---------- |
| 3926 | fraction : number, optional |
| 3927 | Increases or decreases the contrast of the hillshade. Values |
| 3928 | greater than one will cause intermediate values to move closer to |
| 3929 | full illumination or shadow (and clipping any values that move |
| 3930 | beyond 0 or 1). Note that this is not visually or mathematically |
| 3931 | the same as vertical exaggeration. |
| 3932 | |
| 3933 | Returns |
| 3934 | ------- |
| 3935 | `~numpy.ndarray` |
| 3936 | A 2D array of illumination values between 0-1, where 0 is |
| 3937 | completely in shadow and 1 is completely illuminated. |
| 3938 | """ |
| 3939 | |
| 3940 | intensity = normals.dot(self.direction) |
| 3941 | |
| 3942 | # Apply contrast stretch |
| 3943 | imin, imax = intensity.min(), intensity.max() |
| 3944 | intensity *= fraction |
| 3945 | |
| 3946 | # Rescale to 0-1, keeping range before contrast stretch |
| 3947 | # If constant slope, keep relative scaling (i.e. flat should be 0.5, |
| 3948 | # fully occluded 0, etc.) |
| 3949 | if (imax - imin) > 1e-6: |
| 3950 | # Strictly speaking, this is incorrect. Negative values should be |
| 3951 | # clipped to 0 because they're fully occluded. However, rescaling |
| 3952 | # in this manner is consistent with the previous implementation and |
| 3953 | # visually appears better than a "hard" clip. |
| 3954 | intensity -= imin |
| 3955 | intensity /= (imax - imin) |
| 3956 | intensity = np.clip(intensity, 0, 1) |
| 3957 | |
| 3958 | return intensity |
| 3959 | |
| 3960 | def shade(self, data, cmap, norm=None, blend_mode='overlay', vmin=None, |
| 3961 | vmax=None, vert_exag=1, dx=1, dy=1, fraction=1, **kwargs): |