how to get a polygon

本文讨论了如何在给定点的情况下确定该点所在的多边形,并计算该多边形的面积。提供了使用NTS几何扩展进行操作的方法。
how to get a polygon 
Tags: General Topics, SharpMap v0.9 / v1.0, SharpMap v2.0, Web Controls, WinForms Controls

Aug 24 2007 at 3:36 PM
i want to get a polygon where a point in it. then get the area of this polygon.

can anyone help me ? thanks in advance

Coordinator
Aug 24 2007 at 3:56 PM
You'd need to use the NTS geometry extension for this. The page on the NetTopologySuite Data Provider extension has an example which might be useful.

Aug 27 2007 at 9:55 AM
 
 
profile M和profile G在以下这个函数上的区别GetProfiles Description: Retrieve the profile with the specified token or all defined media profiles. If no Type is provided the returned profiles shall contain no configuration information. If a single Type with value 'All' is provided the returned profiles shall include all associated configurations. Otherwise the requested list of configurations shall for each profile include the configurations present as Type. SOAP action: http://www.onvif.org/ver20/media/wsdl/GetProfiles Input: [GetProfiles] Token - optional; [ReferenceToken] Optional token of the requested profile. Type - optional, unbounded; [string] The types shall be provided as defined by tr2:ConfigurationEnumeration. Output: [GetProfilesResponse] Profiles - optional, unbounded; [MediaProfile] Lists all profiles that exist in the media service. The response provides the requested types of Configurations as far as available. If a profile doesn't contain a type no error shall be provided. token - required; [ReferenceToken] Unique identifier of the profile. fixed [boolean] A value of true signals that the profile cannot be deleted. Default is false. Name [Name] User readable name of the profile. Configurations - optional; [ConfigurationSet] The configurations assigned to the profile. VideoSource - optional; [VideoSourceConfiguration] Optional configuration of the Video input. token - required; [ReferenceToken] Token that uniquely references this configuration. Length up to 64 characters. Name [Name] User readable name. Length up to 64 characters. UseCount [int] Number of internal references currently using this configuration. This informational parameter is read-only. Deprecated for Media2 Service. ViewMode [string] Readonly parameter signalling Source configuration's view mode, for devices supporting different view modes as defined in tt:viewModes. SourceToken [ReferenceToken] Reference to the physical input. Bounds [IntRectangle] Rectangle specifying the Video capturing area. The capturing area shall not be larger than the whole Video source area. x - required; [int] y - required; [int] width - required; [int] height - required; [int] Extension - optional; [VideoSourceConfigurationExtension] Rotate - optional; [Rotate] Optional element to configure rotation of captured image. What resolutions a device supports shall be unaffected by the Rotate parameters. If a device is configured with Rotate=AUTO, the device shall take control over the Degree parameter and automatically update it so that a client can query current rotation. The device shall automatically apply the same rotation to its pan/tilt control direction depending on the following condition: if Reverse=AUTO in PTControlDirection or if the device doesn’t support Reverse in PTControlDirection Mode [RotateMode] Parameter to enable/disable Rotation feature. - enum { 'OFF', 'ON', 'AUTO' } Degree - optional; [int] Optional parameter to configure how much degree of clockwise rotation of image for On mode. Omitting this parameter for On mode means 180 degree rotation. Extension - optional; [RotateExtension] Extension - optional; [VideoSourceConfigurationExtension2] LensDescription - optional, unbounded; [LensDescription] Optional element describing the geometric lens distortion. Multiple instances for future variable lens support. FocalLength [float] Optional focal length of the optical system. Offset [LensOffset] Offset of the lens center to the imager center in normalized coordinates. x [float] Optional horizontal offset of the lens center in normalized coordinates. y [float] Optional vertical offset of the lens center in normalized coordinates. Projection - unbounded; [LensProjection] Radial description of the projection characteristics. The resulting curve is defined by the B-Spline interpolation over the given elements. The element for Radius zero shall not be provided. The projection points shall be ordered with ascending Radius. Items outside the last projection Radius shall be assumed to be invisible (black). Angle [float] Angle of incidence. Radius [float] Mapping radius as a consequence of the emergent angle. Transmittance - optional; [float] Optional ray absorption at the given angle due to vignetting. A value of one means no absorption. XFactor [float] Compensation of the x coordinate needed for the ONVIF normalized coordinate system. SceneOrientation - optional; [SceneOrientation] Optional element describing the scene orientation in the camera’s field of view. Mode [SceneOrientationMode] Parameter to assign the way the camera determines the scene orientation. - enum { 'MANUAL', 'AUTO' } Orientation - optional; [string] Assigned or determined scene orientation based on the Mode. When assigning the Mode to AUTO, this field is optional and will be ignored by the device. When assigning the Mode to MANUAL, this field is required and the device will return an InvalidArgs fault if missing. AudioSource - optional; [AudioSourceConfiguration] Optional configuration of the Audio input. token - required; [ReferenceToken] Token that uniquely references this configuration. Length up to 64 characters. Name [Name] User readable name. Length up to 64 characters. UseCount [int] Number of internal references currently using this configuration. This informational parameter is read-only. Deprecated for Media2 Service. SourceToken [ReferenceToken] Token of the Audio Source the configuration applies to VideoEncoder - optional; [VideoEncoder2Configuration] Optional configuration of the Video encoder. token - required; [ReferenceToken] Token that uniquely references this configuration. Length up to 64 characters. Name [Name] User readable name. Length up to 64 characters. UseCount [int] Number of internal references currently using this configuration. This informational parameter is read-only. Deprecated for Media2 Service. GovLength [int] Group of Video frames length. Determines typically the interval in which the I-Frames will be coded. An entry of 1 indicates I-Frames are continuously generated. An entry of 2 indicates that every 2nd image is an I-Frame, and 3 only every 3rd frame, etc. The frames in between are coded as P or B Frames. AnchorFrameDistance [int] Distance between anchor frames of type I-Frame and P-Frame. '1' indicates no B-Frames, '2' indicates that every 2nd frame is encoded as B-Frame, '3' indicates a structure like IBBPBBP..., etc. Profile [string] The encoder profile as defined in tt:VideoEncodingProfiles. GuaranteedFrameRate [boolean] A value of true indicates that frame rate is a fixed value rather than an upper limit, and that the video encoder shall prioritize frame rate over all other adaptable configuration values such as bitrate. Default is false. Signed [boolean] Indicates if this stream will be signed according to the Media Signing Specification. Encoding [string] Video Media Subtype for the video format. For definitions see tt:VideoEncodingMimeNames and IANA Media Types. Resolution [VideoResolution2] Configured video resolution Width [int] Number of the columns of the Video image. If there is a 90-degree rotation, this represents the number of lines of the Video image. Height [int] Number of the lines of the Video image. If there is a 90-degree rotation, this represents the number of columns of the Video image. RateControl - optional; [VideoRateControl2] Optional element to configure rate control related parameters. ConstantBitRate [boolean] Enforce constant bitrate. FrameRateLimit [float] Desired frame rate in fps. The actual rate may be lower due to e.g. performance limitations. BitrateLimit [int] the maximum output bitrate in kbps Multicast - optional; [MulticastConfiguration] Defines the multicast settings that could be used for video streaming. Address [IPAddress] The multicast address (if this address is set to 0 no multicast streaming is enaled) Type [IPType] Indicates if the address is an IPv4 or IPv6 address. - enum { 'IPv4', 'IPv6' } IPv4Address - optional; [IPv4Address] IPv4 address. IPv6Address - optional; [IPv6Address] IPv6 address Port [int] The RTP mutlicast destination port. A device may support RTCP. In this case the port value shall be even to allow the corresponding RTCP stream to be mapped to the next higher (odd) destination port number as defined in the RTSP specification. TTL [int] In case of IPv6 the TTL value is assumed as the hop limit. Note that for IPV6 and administratively scoped IPv4 multicast the primary use for hop limit / TTL is to prevent packets from (endlessly) circulating and not limiting scope. In these cases the address contains the scope. AutoStart [boolean] Read only property signalling that streaming is persistant. Use the methods StartMulticastStreaming and StopMulticastStreaming to switch its state. Quality [float] Relative value for the video quantizers and the quality of the video. A high value within supported quality range means higher quality AudioEncoder - optional; [AudioEncoder2Configuration] Optional configuration of the Audio encoder. token - required; [ReferenceToken] Token that uniquely references this configuration. Length up to 64 characters. Name [Name] User readable name. Length up to 64 characters. UseCount [int] Number of internal references currently using this configuration. This informational parameter is read-only. Deprecated for Media2 Service. Encoding [string] Audio Media Subtype for the audio format. For definitions see tt:AudioEncodingMimeNames and IANA Media Types. Multicast - optional; [MulticastConfiguration] Optional multicast configuration of the audio stream. Address [IPAddress] The multicast address (if this address is set to 0 no multicast streaming is enaled) Type [IPType] Indicates if the address is an IPv4 or IPv6 address. - enum { 'IPv4', 'IPv6' } IPv4Address - optional; [IPv4Address] IPv4 address. IPv6Address - optional; [IPv6Address] IPv6 address Port [int] The RTP mutlicast destination port. A device may support RTCP. In this case the port value shall be even to allow the corresponding RTCP stream to be mapped to the next higher (odd) destination port number as defined in the RTSP specification. TTL [int] In case of IPv6 the TTL value is assumed as the hop limit. Note that for IPV6 and administratively scoped IPv4 multicast the primary use for hop limit / TTL is to prevent packets from (endlessly) circulating and not limiting scope. In these cases the address contains the scope. AutoStart [boolean] Read only property signalling that streaming is persistant. Use the methods StartMulticastStreaming and StopMulticastStreaming to switch its state. Bitrate [int] The output bitrate in kbps. SampleRate [int] The output sample rate in kHz. Analytics - optional; [VideoAnalyticsConfiguration] Optional configuration of the analytics module and rule engine. token - required; [ReferenceToken] Token that uniquely references this configuration. Length up to 64 characters. Name [Name] User readable name. Length up to 64 characters. UseCount [int] Number of internal references currently using this configuration. This informational parameter is read-only. Deprecated for Media2 Service. AnalyticsEngineConfiguration [AnalyticsEngineConfiguration] AnalyticsModule - optional, unbounded; [Config] Name - required; [string] Name of the configuration. Type - required; [QName] The Type attribute specifies the type of rule and shall be equal to value of one of Name attributes of ConfigDescription elements returned by GetSupportedRules and GetSupportedAnalyticsModules command. Parameters [ItemList] List of configuration parameters as defined in the corresponding description. SimpleItem - optional, unbounded; Value name pair as defined by the corresponding description. Name - required; [string] Item name. Value - required; [anySimpleType] Item value. The type is defined in the corresponding description. ElementItem - optional, unbounded; Complex value structure. Name - required; [string] Item name. Extension - optional; [ItemListExtension] Extension - optional; [AnalyticsEngineConfigurationExtension] RuleEngineConfiguration [RuleEngineConfiguration] Rule - optional, unbounded; [Config] Name - required; [string] Name of the configuration. Type - required; [QName] The Type attribute specifies the type of rule and shall be equal to value of one of Name attributes of ConfigDescription elements returned by GetSupportedRules and GetSupportedAnalyticsModules command. Parameters [ItemList] List of configuration parameters as defined in the corresponding description. SimpleItem - optional, unbounded; Value name pair as defined by the corresponding description. Name - required; [string] Item name. Value - required; [anySimpleType] Item value. The type is defined in the corresponding description. ElementItem - optional, unbounded; Complex value structure. Name - required; [string] Item name. Extension - optional; [ItemListExtension] Extension - optional; [RuleEngineConfigurationExtension] PTZ - optional; [PTZConfiguration] Optional configuration of the pan tilt zoom unit. token - required; [ReferenceToken] Token that uniquely references this configuration. Length up to 64 characters. Name [Name] User readable name. Length up to 64 characters. UseCount [int] Number of internal references currently using this configuration. This informational parameter is read-only. Deprecated for Media2 Service. MoveRamp [int] The optional acceleration ramp used by the device when moving. PresetRamp [int] The optional acceleration ramp used by the device when recalling presets. PresetTourRamp [int] The optional acceleration ramp used by the device when executing PresetTours. NodeToken [ReferenceToken] A mandatory reference to the PTZ Node that the PTZ Configuration belongs to. DefaultAbsolutePantTiltPositionSpace - optional; [anyURI] If the PTZ Node supports absolute Pan/Tilt movements, it shall specify one Absolute Pan/Tilt Position Space as default. DefaultAbsoluteZoomPositionSpace - optional; [anyURI] If the PTZ Node supports absolute zoom movements, it shall specify one Absolute Zoom Position Space as default. DefaultRelativePanTiltTranslationSpace - optional; [anyURI] If the PTZ Node supports relative Pan/Tilt movements, it shall specify one RelativePan/Tilt Translation Space as default. DefaultRelativeZoomTranslationSpace - optional; [anyURI] If the PTZ Node supports relative zoom movements, it shall specify one Relative Zoom Translation Space as default. DefaultContinuousPanTiltVelocitySpace - optional; [anyURI] If the PTZ Node supports continuous Pan/Tilt movements, it shall specify one Continuous Pan/Tilt Velocity Space as default. DefaultContinuousZoomVelocitySpace - optional; [anyURI] If the PTZ Node supports continuous zoom movements, it shall specify one Continuous Zoom Velocity Space as default. DefaultPTZSpeed - optional; [PTZSpeed] If the PTZ Node supports absolute or relative PTZ movements, it shall specify corresponding default Pan/Tilt and Zoom speeds. PanTilt - optional; [Vector2D] Pan and tilt speed. The x component corresponds to pan and the y component to tilt. If omitted in a request, the current (if any) PanTilt movement should not be affected. Zoom - optional; [Vector1D] A zoom speed. If omitted in a request, the current (if any) Zoom movement should not be affected. DefaultPTZTimeout - optional; [duration] If the PTZ Node supports continuous movements, it shall specify a default timeout, after which the movement stops. PanTiltLimits - optional; [PanTiltLimits] The Pan/Tilt limits element should be present for a PTZ Node that supports an absolute Pan/Tilt. If the element is present it signals the support for configurable Pan/Tilt limits. If limits are enabled, the Pan/Tilt movements shall always stay within the specified range. The Pan/Tilt limits are disabled by setting the limits to –INF or +INF. Range [Space2DDescription] A range of pan tilt limits. URI [anyURI] A URI of coordinate systems. XRange [FloatRange] A range of x-axis. Min [float] Max [float] YRange [FloatRange] A range of y-axis. Min [float] Max [float] ZoomLimits - optional; [ZoomLimits] The Zoom limits element should be present for a PTZ Node that supports absolute zoom. If the element is present it signals the supports for configurable Zoom limits. If limits are enabled the zoom movements shall always stay within the specified range. The Zoom limits are disabled by settings the limits to -INF and +INF. Range [Space1DDescription] A range of zoom limit URI [anyURI] A URI of coordinate systems. XRange [FloatRange] A range of x-axis. Min [float] Max [float] Extension - optional; [PTZConfigurationExtension] PTControlDirection - optional; [PTControlDirection] Optional element to configure PT Control Direction related features. EFlip - optional; [EFlip] Optional element to configure related parameters for E-Flip. Mode [EFlipMode] Parameter to enable/disable E-Flip feature. - enum { 'OFF', 'ON', 'Extended' } Reverse - optional; [Reverse] Optional element to configure related parameters for reversing of PT Control Direction. Mode [ReverseMode] Parameter to enable/disable Reverse feature. - enum { 'OFF', 'ON', 'AUTO', 'Extended' } Extension - optional; [PTControlDirectionExtension] Extension - optional; [PTZConfigurationExtension2] Metadata - optional; [MetadataConfiguration] Optional configuration of the metadata stream. token - required; [ReferenceToken] Token that uniquely references this configuration. Length up to 64 characters. Name [Name] User readable name. Length up to 64 characters. UseCount [int] Number of internal references currently using this configuration. This informational parameter is read-only. Deprecated for Media2 Service. CompressionType [string] Optional parameter to configure compression type of Metadata payload. Use values from enumeration MetadataCompressionType. GeoLocation [boolean] Optional parameter to configure if the metadata stream shall contain the Geo Location coordinates of each target. ShapePolygon [boolean] Optional parameter to configure if the generated metadata stream should contain shape information as polygon. PTZStatus - optional; [PTZFilter] optional element to configure which PTZ related data is to include in the metadata stream Status [boolean] True if the metadata stream shall contain the PTZ status (IDLE, MOVING or UNKNOWN) Position [boolean] True if the metadata stream shall contain the PTZ position FieldOfView - optional; [boolean] True if the metadata stream shall contain the field-of-view information Events - optional; [EventSubscription] Optional element to configure the streaming of events. A client might be interested in receiving all, none or some of the events produced by the device: To get all events: Include the Events element but do not include a filter. To get no events: Do not include the Events element. To get only some events: Include the Events element and include a filter in the element. Filter - optional; [FilterType] SubscriptionPolicy - optional; Analytics - optional; [boolean] Defines whether the streamed metadata will include metadata from the analytics engines (video, cell motion, audio etc.) Multicast [MulticastConfiguration] Defines the multicast settings that could be used for video streaming. Address [IPAddress] The multicast address (if this address is set to 0 no multicast streaming is enaled) Type [IPType] Indicates if the address is an IPv4 or IPv6 address. - enum { 'IPv4', 'IPv6' } IPv4Address - optional; [IPv4Address] IPv4 address. IPv6Address - optional; [IPv6Address] IPv6 address Port [int] The RTP mutlicast destination port. A device may support RTCP. In this case the port value shall be even to allow the corresponding RTCP stream to be mapped to the next higher (odd) destination port number as defined in the RTSP specification. TTL [int] In case of IPv6 the TTL value is assumed as the hop limit. Note that for IPV6 and administratively scoped IPv4 multicast the primary use for hop limit / TTL is to prevent packets from (endlessly) circulating and not limiting scope. In these cases the address contains the scope. AutoStart [boolean] Read only property signalling that streaming is persistant. Use the methods StartMulticastStreaming and StopMulticastStreaming to switch its state. SessionTimeout [duration] The rtsp session timeout for the related audio stream (when using Media2 Service, this value is deprecated and ignored) AnalyticsEngineConfiguration - optional; [AnalyticsEngineConfiguration] Indication which AnalyticsModules shall output metadata. Note that the streaming behavior is undefined if the list includes items that are not part of the associated AnalyticsConfiguration. AnalyticsModule - optional, unbounded; [Config] Name - required; [string] Name of the configuration. Type - required; [QName] The Type attribute specifies the type of rule and shall be equal to value of one of Name attributes of ConfigDescription elements returned by GetSupportedRules and GetSupportedAnalyticsModules command. Parameters [ItemList] List of configuration parameters as defined in the corresponding description. SimpleItem - optional, unbounded; Value name pair as defined by the corresponding description. Name - required; [string] Item name. Value - required; [anySimpleType] Item value. The type is defined in the corresponding description. ElementItem - optional, unbounded; Complex value structure. Name - required; [string] Item name. Extension - optional; [ItemListExtension] Extension - optional; [AnalyticsEngineConfigurationExtension] Extension - optional; [MetadataConfigurationExtension] AudioOutput - optional; [AudioOutputConfiguration] Optional configuration of the Audio output. token - required; [ReferenceToken] Token that uniquely references this configuration. Length up to 64 characters. Name [Name] User readable name. Length up to 64 characters. UseCount [int] Number of internal references currently using this configuration. This informational parameter is read-only. Deprecated for Media2 Service. OutputToken [ReferenceToken] Token of the phsycial Audio output. SendPrimacy - optional; [anyURI] An audio channel MAY support different types of audio transmission. While for full duplex operation no special handling is required, in half duplex operation the transmission direction needs to be switched. The optional SendPrimacy parameter inside the AudioOutputConfiguration indicates which direction is currently active. An NVC can switch between different modes by setting the AudioOutputConfiguration. The following modes for the Send-Primacy are defined: www.onvif.org/ver20/HalfDuplex/Server The server is allowed to send audio data to the client. The client shall not send audio data via the backchannel to the NVT in this mode. www.onvif.org/ver20/HalfDuplex/Client The client is allowed to send audio data via the backchannel to the server. The NVT shall not send audio data to the client in this mode. www.onvif.org/ver20/HalfDuplex/Auto It is up to the device how to deal with sending and receiving audio data. Acoustic echo cancellation is out of ONVIF scope. OutputLevel [int] Volume setting of the output. The applicable range is defined via the option AudioOutputOptions.OutputLevelRange. AudioDecoder - optional; [AudioDecoderConfiguration] Optional configuration of the Audio decoder. token - required; [ReferenceToken] Token that uniquely references this configuration. Length up to 64 characters. Name [Name] User readable name. Length up to 64 characters. UseCount [int] Number of internal references currently using this configuration. This informational parameter is read-only. Deprecated for Media2 Service. Receiver - optional; [ReceiverConfiguration] Optional configuration of the Receiver. Mode [ReceiverMode] The following connection modes are defined: - AutoConnect: The receiver connects on demand, as required by consumers of the media streams. - AlwaysConnect: The receiver attempts to maintain a persistent connection to the configured endpoint. - NeverConnect: The receiver does not attempt to connect. - Unknown: This case should never happen. MediaUri [anyURI] Details of the URI to which the receiver should connect. StreamSetup [StreamSetup] Stream connection parameters. Stream [StreamType] Defines if a multicast or unicast stream is requested - enum { 'RTP-Unicast', 'RTP-Multicast' } Transport [Transport] Protocol [TransportProtocol] Defines the network protocol for streaming, either UDP=RTP/UDP, RTSP=RTP/RTSP/TCP or HTTP=RTP/RTSP/HTTP/TCP - enum { 'UDP', 'TCP', 'RTSP', 'HTTP' } Tunnel - optional; [Transport] Optional element to describe further tunnel options. This element is normally not needed Protocol [TransportProtocol] Defines the network protocol for streaming, either UDP=RTP/UDP, RTSP=RTP/RTSP/TCP or HTTP=RTP/RTSP/HTTP/TCP - enum { 'UDP', 'TCP', 'RTSP', 'HTTP' } Tunnel - optional; [Transport] Optional element to describe further tunnel options. This element is normally not needed ... is recursive token [ReferenceToken]
09-19
################################## # Semi-OOP version of runes.py # # Last updated: 21 January 2025 # ################################## ######### START OF SETUP ######### # Imports import functools import graphics import math import time import PyGif from random import random # Constants viewport_size = 600 # This is the height of the viewport spread = 20 active_hollusion = None lastframe = None Posn = graphics.Posn Rgb = graphics.Rgb draw_solid_polygon = graphics.draw_solid_polygon graphics.init(viewport_size) vp = graphics.open_viewport("ViewPort", viewport_size, viewport_size) lp = graphics.open_pixmap("LeftPort", viewport_size, viewport_size) rp = graphics.open_pixmap("RightPort", viewport_size, viewport_size) def type_checker(types): """ A setup function to help you check for types. Nothing to see here. """ def decorator(func): name = func.__name__ # functools.wraps preserves the docstring @functools.wraps(func) def checker(*args): for i in range(len(args)): if not isinstance(args[i], types[i]): expected = types[i].__name__ actual = type(args[i]).__name__ raise TypeError( f"Function {name}: Expected type {expected} for argument #{i + 1} but given {args[i]} of type {actual}" ) return func(*args) return checker return decorator def is_list_or_tuple(lst): """ A setup function to check for types. Nothing to see here. """ return isinstance(lst, (list, tuple)) class Frame: """ A frame object. Nothing to see here. """ def __init__(self, p0, p1, p2, z1, z2): self.orig = p0 self.x = p1 self.y = p2 self.z1 = z1 self.z2 = z2 unit_frame = Frame(Posn(0, 0), Posn(viewport_size, 0), Posn(0, viewport_size), 0, 1) class Rune: """ A rune object. Nothing to see here. """ def __init__(self, func): self.fn = func def show(self, vp, frame): self.fn(vp, frame) def __str__(self): return "Rune" def scale_vect(mult, p): """ A setup function to scale vectors. Nothing to see here. """ return Posn(mult * p.x, mult * p.y) def transform_posn(frame): """ A setup function for position transformation. Nothing to see here. """ def f(posn): return frame.orig + ( scale_vect(posn.x / viewport_size, frame.x) + scale_vect(posn.y / viewport_size, frame.y) ) return f def inverse_transform_posn(frame): """ The 'inverse' of transform_posn. Nothing to see here. """ a = frame.x.x b = frame.y.x c = frame.x.y d = frame.y.y det = a * d - b * c if det == 0: raise Exception("somehow you managed to zero the determinant for your frame") inv_mat = ((d / det, -b / det), (-c / det, a / det)) def function(posn): nonlocal inv_mat t = list( map( lambda m: m[0] * (posn.x - frame.orig.x) + m[1] * (posn.y - frame.orig.y), inv_mat, ) ) return Posn(viewport_size * t[0], viewport_size * t[1]) return Rune(function) def center_and_fill(p): """ A function used in circle_bb, spiral_bb, and ribbon_bb. Nothing to see here. """ center = Posn(viewport_size / 2, viewport_size / 2) return center + scale_vect(viewport_size / 2, p) ############ END OF SETUP ############ @type_checker((Rune,)) def show(rune): """ Shows the `rune` at the working window. """ return rune.show(vp, unit_frame) def clear_all(): """ Clears the current working window. """ global active_hollusion global vp, lp, rp if active_hollusion != None: active_hollusion("kill") active_hollusion = None graphics.clear_viewport(vp) graphics.clear_viewport(lp) graphics.clear_viewport(rp) def blank_bbf(vp, frame): """ A blank rune. Basically nothing. """ blank_bb = Rune(blank_bbf) def sail_bbf(vp, frame): """ A sail-shaped rune. """ p = [ Posn(viewport_size / 2, 0), Posn(viewport_size / 2, viewport_size), Posn(viewport_size, viewport_size), ] if is_list_or_tuple(vp[0]): for count, port in enumerate(vp): draw_solid_polygon( port, map(transform_posn(frame), p), Posn( (0.3 - frame.z1) * (spread * (((2 * count) / (len(vp) - 1)) - 1)), 0 ), Rgb(frame.z1, frame.z1, frame.z1), ) elif vp != None: draw_solid_polygon( vp, map(transform_posn(frame), p), Posn(0, 0), Rgb(frame.z1, frame.z1, frame.z1), ) sail_bb = Rune(sail_bbf) def corner_bbf(vp, frame): """ A small triangular rune at the corner. """ p = [ Posn(viewport_size / 2, 0), Posn(viewport_size, 0), Posn(viewport_size, viewport_size / 2), ] if is_list_or_tuple(vp[0]): for count, port in enumerate(vp): draw_solid_polygon( port, map(transform_posn(frame), p), Posn( (0.3 - frame.z1) * (spread * (((2 * count) / (len(vp) - 1)) - 1)), 0 ), Rgb(frame.z1, frame.z1, frame.z1), ) elif vp != None: draw_solid_polygon( vp, map(transform_posn(frame), p), Posn(0, 0), Rgb(frame.z1, frame.z1, frame.z1), ) corner_bb = Rune(corner_bbf) def black_bbf(vp, frame): """ A rune without any blank space. """ p = [ Posn(0, 0), Posn(viewport_size, 0), Posn(viewport_size, viewport_size), Posn(0, viewport_size), ] if is_list_or_tuple(vp[0]): for count, port in enumerate(vp): draw_solid_polygon( port, map(transform_posn(frame), p), Posn( (0.3 - frame.z1) * (spread * (((2 * count) / (len(vp) - 1)) - 1)), 0 ), Rgb(frame.z1, frame.z1, frame.z1), ) elif vp != None: draw_solid_polygon( vp, map(transform_posn(frame), p), Posn(0, 0), Rgb(frame.z1, frame.z1, frame.z1), ) black_bb = Rune(black_bbf) def spiral_bbf(vp, frame): """ A rune that definitely looks like a spiral. """ theta_max = 30 offset = 0.1 angle = 0 p = [] while angle < theta_max: p.append( Posn( (offset + angle / theta_max) * math.cos(angle), (offset + angle / theta_max) * math.sin(angle), ) ) angle += offset if is_list_or_tuple(vp[0]): for count, port in enumerate(vp): draw_solid_polygon( port, map(transform_posn(frame), map(center_and_fill, p)), Posn( (0.3 - frame.z1) * (spread * (((2 * count) / (len(vp) - 1)) - 1)), 0 ), Rgb(frame.z1, frame.z1, frame.z1), ) elif vp != None: draw_solid_polygon( vp, map(transform_posn(frame), map(center_and_fill, p)), Posn(0, 0), Rgb(frame.z1, frame.z1, frame.z1), ) spiral_bb = Rune(spiral_bbf) def circle_bbf(vp, frame): """ A perfect circle rune! """ unit = 50 p = [] angle = 0 while angle < 2 * math.pi: p.append(Posn(math.cos(angle), math.sin(angle))) angle += unit / viewport_size if is_list_or_tuple(vp[0]): for count, port in enumerate(vp): draw_solid_polygon( port, map(transform_posn(frame), map(center_and_fill, p)), Posn( (0.3 - frame.z1) * (spread * (((2 * count) / (len(vp) - 1)) - 1)), 0 ), Rgb(frame.z1, frame.z1, frame.z1), ) elif vp != None: draw_solid_polygon( vp, map(transform_posn(frame), map(center_and_fill, p)), Posn(0, 0), Rgb(frame.z1, frame.z1, frame.z1), ) circle_bb = Rune(circle_bbf) def quarter_bbf(vp, frame): """ Quarter of a circle """ unit = 50 p = [] angle = 0 while angle < math.pi / 2: p.append(Posn(-2 * math.cos(angle) + 1, -2 * math.sin(angle) + 1)) angle += unit / viewport_size p.append(Posn(1, -1)) # Top corner p.append(Posn(1, 1)) # Center of circle if is_list_or_tuple(vp[0]): for count, port in enumerate(vp): draw_solid_polygon( port, map(transform_posn(frame), map(center_and_fill, p)), Posn( (0.3 - frame.z1) * (spread * (((2 * count) / (len(vp) - 1)) - 1)), 0 ), Rgb(frame.z1, frame.z1, frame.z1), ) elif vp != None: draw_solid_polygon( vp, map(transform_posn(frame), map(center_and_fill, p)), Posn(0, 0), Rgb(frame.z1, frame.z1, frame.z1), ) quarter_bb = Rune(quarter_bbf) def pentagram_bbf(vp, frame): """ A star-shaped rune. How cool is that? """ unit_offset = viewport_size / 2 s1 = math.sin(2 * math.pi / 5) * unit_offset c1 = math.cos(2 * math.pi / 5) * unit_offset s2 = math.sin(4 * math.pi / 5) * unit_offset c2 = math.cos(math.pi / 5) * unit_offset a = s2 / (s1 + s2) a_ = 1 - a p = [ Posn(-s1 + unit_offset, -c1 + unit_offset), Posn(s1 + unit_offset, -c1 + unit_offset), Posn(-s2 + unit_offset, c2 + unit_offset), Posn(unit_offset, 0), Posn(s2 + unit_offset, c2 + unit_offset), ] p = [ p[0], p[3] * a + p[2] * a_, p[2], p[1] * a + p[2] * a_, p[4], p[2] * a + p[1] * a_, p[1], p[4] * a + p[3] * a_, p[3], p[2] * a + p[3] * a_, ] if is_list_or_tuple(vp[0]): for count, port in enumerate(vp): draw_solid_polygon( port, map(transform_posn(frame), p), Posn( (0.3 - frame.z1) * (spread * (((2 * count) / (len(vp) - 1)) - 1)), 0 ), Rgb(frame.z1, frame.z1, frame.z1), ) elif vp != None: draw_solid_polygon( vp, map(transform_posn(frame), p), Posn(0, 0), Rgb(frame.z1, frame.z1, frame.z1), ) pentagram_bb = Rune(pentagram_bbf) def heart_bbf(vp, frame): """ A heart-shaped rune. Good to spread positivity :) """ k = math.sqrt(2) / 2 p = [ Posn(viewport_size / 2, (1 - k) / (1 + 3 * k) * viewport_size), Posn( (1 - k) / (1 + k) * viewport_size / 2, (1 + k) / (1 + 3 * k) * viewport_size ), Posn(viewport_size / 2, viewport_size), Posn( viewport_size - (1 - k) / (1 + k) * viewport_size / 2, (1 + k) / (1 + 3 * k) * viewport_size, ), ] # Draws a kite if is_list_or_tuple(vp[0]): for count, port in enumerate(vp): draw_solid_polygon( port, map(transform_posn(frame), p), Posn( (0.3 - frame.z1) * (spread * (((2 * count) / (len(vp) - 1)) - 1)), 0 ), Rgb(frame.z1, frame.z1, frame.z1), ) elif vp != None: draw_solid_polygon( vp, map(transform_posn(frame), p), Posn(0, 0), Rgb(frame.z1, frame.z1, frame.z1), ) # Draws the top of the heart heart_circle = stack_frac( 2 / (1 + 3 * k), quarter_turn_right(stack_frac(k / (1 + k), blank_bb, circle_bb)), blank_bb, ) heart_circle.show(vp, frame) flip_horiz(heart_circle).show(vp, frame) heart_bb = Rune(heart_bbf) def rcross_bbf(vp, frame): """ An upper triangular rune with some small part mirrored to its diagonal. """ p1 = [ Posn(0, 0), Posn(viewport_size / 4, viewport_size / 4), Posn(3 * viewport_size / 4, viewport_size / 4), Posn(3 * viewport_size / 4, 3 * viewport_size / 4), Posn(viewport_size, viewport_size), Posn(viewport_size, 0), ] p2 = [ Posn(viewport_size / 4, viewport_size / 4), Posn(viewport_size / 4, 3 * viewport_size / 4), Posn(3 * viewport_size / 4, 3 * viewport_size / 4), ] if is_list_or_tuple(vp[0]): for count, port in enumerate(vp): draw_solid_polygon( port, map(transform_posn(frame), p1), Posn( (0.3 - frame.z1) * (spread * (((2 * count) / (len(vp) - 1)) - 1)), 0 ), Rgb(frame.z1, frame.z1, frame.z1), ) draw_solid_polygon( port, map(transform_posn(frame), p2), Posn( (0.3 - frame.z1) * (spread * (((2 * count) / (len(vp) - 1)) - 1)), 0 ), Rgb(frame.z1, frame.z1, frame.z1), ) elif vp != None: draw_solid_polygon( vp, map(transform_posn(frame), p1), Posn(0, 0), Rgb(frame.z1, frame.z1, frame.z1), ) draw_solid_polygon( vp, map(transform_posn(frame), p2), Posn(0, 0), Rgb(frame.z1, frame.z1, frame.z1), ) rcross_bb = Rune(rcross_bbf) def ribbon_bbf(vp, frame): """ A ribbon-shaped rune, similar to a beautiful spiral. """ theta_max = 30 thickness = -1 / theta_max unit = 0.1 p = [] angle = 0 # Make ribbon while angle < theta_max: p.append( Posn( (angle / theta_max) * math.cos(angle), (angle / theta_max) * math.sin(angle), ) ) angle += unit # Close it while angle > 0: p.append( Posn( abs(math.cos(angle) * thickness) + (angle / theta_max * math.cos(angle)), abs(math.sin(angle) * thickness) + (angle / theta_max * math.sin(angle)), ) ) angle -= unit if is_list_or_tuple(vp[0]): for count, port in enumerate(vp): draw_solid_polygon( port, map(transform_posn(frame), map(center_and_fill, p)), Posn( (0.3 - frame.z1) * (spread * (((2 * count) / (len(vp) - 1)) - 1)), 0 ), Rgb(frame.z1, frame.z1, frame.z1), ) elif vp != None: draw_solid_polygon( vp, map(transform_posn(frame), map(center_and_fill, p)), Posn(0, 0), Rgb(frame.z1, frame.z1, frame.z1), ) ribbon_bb = Rune(ribbon_bbf) def nova_bbf(vp, frame): """ Two small sail-shaped runes combined into an L-shaped rune. """ p = [ Posn(viewport_size / 2, 0), Posn(viewport_size / 4, viewport_size / 2), Posn(viewport_size, viewport_size / 2), Posn(viewport_size / 2, viewport_size / 4), ] if is_list_or_tuple(vp[0]): for count, port in enumerate(vp): draw_solid_polygon( port, map(transform_posn(frame), p), Posn( (0.3 - frame.z1) * (spread * (((2 * count) / (len(vp) - 1)) - 1)), 0 ), Rgb(frame.z1, frame.z1, frame.z1), ) elif vp != None: draw_solid_polygon( vp, map(transform_posn(frame), p), Posn(0, 0), Rgb(frame.z1, frame.z1, frame.z1), ) nova_bb = Rune(nova_bbf) # Frame transformation factory def process_frame(op, frame): """ A frame transformation factory. Nothing to see here. """ p0 = frame.orig p1 = frame.x p2 = frame.y z1 = frame.z1 z2 = frame.z2 if op == "bottom_frac": return lambda frac: Frame( p0 + scale_vect(1 - frac, p2), p1, scale_vect(frac, p2), z1, z2 ) elif op == "top_frac": return lambda frac: Frame(p0, p1, scale_vect(frac, p2), z1, z2) # To devs, probably unused elif op == "left": return Frame(p0, scale_vect(1 / 2, p1), p2, z1, z2) # To devs, probably unused elif op == "right": return Frame(p0 + scale_vect(1 / 2, p1), scale_vect(1 / 2, p1), p2, z1, z2) elif op == "flip_horiz": return Frame(p0 + p1, scale_vect(-1, p1), p2, z1, z2) elif op == "flip_vert": return Frame(p0 + p2, p1, scale_vect(-1, p2), z1, z2) elif op == "reduce_2": # unused in original raise NotImplementedError("reduce_2 is not implemented") elif op == "rotate": def function(rad): cos_theta = math.cos(rad) sin_theta = math.sin(rad) def rotate_posn(p): return Posn( cos_theta * p.x + sin_theta * p.y, cos_theta * p.y - sin_theta * p.x ) half_gradient = scale_vect(1 / 2, p1 + p2) center = p0 + half_gradient + rotate_posn(scale_vect(-1, half_gradient)) return Frame(center, rotate_posn(p1), rotate_posn(p2), z1, z2) return function elif op == "rotate90": return Frame(p0 + p1, p2, scale_vect(-1, p1), z1, z2) elif op == "deep_frac": return lambda frac: Frame(p0, p1, p2, z1 + ((z2 - z1) * frac), z2) elif op == "shallow_frac": return lambda frac: Frame(p0, p1, p2, z1, z1 + ((z2 - z1) * frac)) elif op == "scale_independent": def function(ratio_x, ratio_y): d_xy = (p1 * (1 - ratio_x) + p2 * (1 - ratio_y)) * 0.5 center = p0 + d_xy return Frame(center, p1 * ratio_x, p2 * ratio_y, z1, z2) return function elif op == "translate": return lambda x, y: Frame( p0 + scale_vect(x, p1) + scale_vect(y, p2), p1, p2, z1, z2 ) # Basic rune combinations @type_checker((float, Rune, Rune)) def stack_frac(frac, rune1, rune2): """ Stacks `rune1` on top and `rune2` at the bottom with the vertical proportion of `rune1` equals to `frac`. """ def function(vp, frame): if not 0 <= frac <= 1: raise ValueError("stack_frac: 0 <= frac <= 1 is required") else: uf = process_frame("top_frac", frame)(frac) lf = process_frame("bottom_frac", frame)(1 - frac) rune1.show(vp, uf) rune2.show(vp, lf) return Rune(function) @type_checker((Rune, Rune)) def stack(rune1, rune2): """ Stacks `rune1` on top and `rune2` at the bottom with equal proportion. """ return stack_frac(1 / 2, rune1, rune2) @type_checker((float, Rune)) def rotate(rad, rune): """ Rotate `rune` by a certain angle `rad`, in radians, counterclockwise. """ def function(vp, frame): rune.show(vp, process_frame("rotate", frame)(rad)) return Rune(function) @type_checker((Rune,)) def eighth_turn_left(rune): """ Rotate `rune` by pi/4 radians counterclockwise. In other words, 45 degrees to the left. """ return rotate(math.pi / 4, rune) @type_checker((Rune,)) def quarter_turn_right(rune): """ Rotate `rune` by pi/2 radians clockwise. In other words, 90 degrees to the right. """ def function(vp, frame): rune.show(vp, process_frame("rotate90", frame)) return Rune(function) @type_checker((Rune,)) def flip_vert(rune): """ Flips `rune` vertically. """ def function(vp, frame): rune.show(vp, process_frame("flip_vert", frame)) return Rune(function) @type_checker((Rune,)) def flip_horiz(rune): """ Flips `rune` horizontally. """ def function(vp, frame): rune.show(vp, process_frame("flip_horiz", frame)) return Rune(function) @type_checker((float, Rune, Rune)) def overlay_frac(frac, rune1, rune2): """ Overlay `rune1` on top and `rune2` at the bottom with the z-axis proportion of `rune1` equals `frac`. Basically a 3D-representation of stack_frac. """ def function(vp, frame): if not 0 <= frac <= 1: raise ValueError("overlay_frac: 0 <= frac <= 1 is required") else: df = process_frame("deep_frac", frame)(frac) sf = process_frame("shallow_frac", frame)(frac) rune2.show(vp, df) rune1.show(vp, sf) return Rune(function) @type_checker((Rune, Rune)) def overlay(rune1, rune2): """ Overlay `rune1` on top and `rune2` at the bottom with equal z-axis proportion. """ return overlay_frac(1 / 2, rune1, rune2) @type_checker((float, float, Rune)) def scale_independent(ratio_x, ratio_y, rune): """ Scales `rune`'s width by `ratio_x` and its height by `ratio_y`. The scaling anchor point is the center of the rune. """ def function(vp, frame): rune.show(vp, process_frame("scale_independent", frame)(ratio_x, ratio_y)) return Rune(function) @type_checker((float, Rune)) def scale(ratio, rune): """ Scales `rune` by `ratio`, maintaining aspect ratio. """ return scale_independent(ratio, ratio, rune) @type_checker((float, float, Rune)) def translate(x, y, rune): """ Translates `rune` by `x` * 100% of the screen to the right and by `y` * 100% of the screen downwards. Positive `x` means to the right, positive `y` means downwards. """ def function(vp, frame): rune.show(vp, process_frame("translate", frame)(x, y)) return Rune(function) @type_checker((Rune,)) def turn_upside_down(rune): """ Turns `rune` upside down, a.k.a. 180 degrees. """ return quarter_turn_right(quarter_turn_right(rune)) @type_checker((Rune,)) def quarter_turn_left(rune): """ Turns `rune` to the left by 90 degrees. In other word, pi/2 radians counterclockwise. """ return turn_upside_down(quarter_turn_right(rune)) @type_checker((Rune, Rune)) def beside(rune1, rune2): """ Puts `rune1` and `rune2` beside each other. Both runes share the same horizontal proportion. """ return quarter_turn_right(stack(quarter_turn_left(rune2), quarter_turn_left(rune1))) @type_checker((Rune,)) def make_cross(rune): """ Creates a cross out of the base `rune`. """ return stack( beside(quarter_turn_right(rune), turn_upside_down(rune)), beside(rune, quarter_turn_left(rune)), ) # TODO refactor type_checker, pat is a function, but function is not a keyword or built-in. def repeat_pattern(n, pat, pic): """ Repeats a pattern, pat, on a rune, pic, by n times. """ if n == 0: return pic else: return pat(repeat_pattern(n - 1, pat, pic)) @type_checker((int, Rune)) def stackn(n, rune): """ Stacks n identical `rune` vertically. The vertical proportions of the runes will be all equal. """ if n == 1: return rune else: return stack_frac(1 / n, rune, stackn(n - 1, rune)) ########################################################################## # Functions below this line are deprecated! You don't have to check them # ########################################################################## def hollusion(rune, ports=None): """ Creates a hollusion of `rune`. """ global active_hollusion frequency = 2 MAX_X = round(viewport_size) MAX_Y = round(viewport_size) num = ports if ports == None or ports <= 2: num = 9 buffers = list( map( lambda p: graphics.open_pixmap("buffer", viewport_size, viewport_size), range(num), ) ) def animation(cmd=None): ports = buffers kill = False curr = -1 dir = 1 def Self(msg): nonlocal kill nonlocal curr nonlocal Self nonlocal dir if msg == "next": curr += dir if curr == num or curr < 0: dir = -dir curr += 2 * dir graphics.show_viewport(buffers[curr]) if not kill: vp[0].after( round(1000 / (frequency * len(ports))), lambda: Self("next") ) elif msg == "kill": kill = True elif msg == "buffer": return ports else: return return Self rune.show(buffers, unit_frame) if active_hollusion != None: active_hollusion("kill") active_hollusion = animation() active_hollusion("next") return active_hollusion def anaglyph(rune): """ Creates an anaglyph of `rune`. Very advisable to use 3D glasses for the effects. """ if graphics.PIL_available: MAX_X = round(viewport_size) MAX_Y = viewport_size stereo = vp depth = graphics.open_pixmap("Depthmap Viewport", viewport_size, viewport_size) def get_depth(x, y, pix): return pix[x, y][0] rune.show([lp, rp], unit_frame) lp_pix = graphics.get_pixels(lp) rp_pix = graphics.get_pixels(rp) pixels = graphics.get_pixels(stereo) for y in range(MAX_Y): for x in range(MAX_X): l = get_depth(x, y, lp_pix) r = get_depth(x, y, rp_pix) pixels[x, y] = (r, l, l) graphics.pixels_to_canvas(stereo) else: print("PIL does not appear to be available") def function_to_painter(depth_fun): """ Converts a depth function depth_fun into a rune. """ tolerance = 1 / spread def get_depth(x, y, dir, frame): # lp -> dir = -1, rp -> dir = 1 result = 1 for c in range(0, spread): ox = round(x + (dir * ((-0.3 * spread) + c))) if 0 <= ox < viewport_size: curr = depth_fun(round(ox), round(y)) if curr != 1: curr = frame.z1 + ((frame.z2 - frame.z1) * curr) d = abs(curr - c / spread) if d < tolerance: result = curr return result def painter(vp, frame): def ana_out_loop(port, count): inverse_transform = inverse_transform_posn(frame) tgtpixels = graphics.get_pixels(port) size = graphics.get_image_size(port) MAX_X = size[0] MAX_Y = size[1] tgtpixels = graphics.get_pixels(port) for y in range(MAX_Y): for x in range(MAX_X): posn = inverse_transform(Posn(x, y)) col = get_depth(posn.x, posn.y, count, frame) col = round(min(col, 1) * 255) if col < 255: tgtpixels[x, y] = ( min(col, tgtpixels[x, y][0]), min(col, tgtpixels[x, y][1]), min(col, tgtpixels[x, y][2]), ) graphics.pixels_to_canvas(port) if is_list_or_tuple(vp[0]): for count, port in enumerate(vp): ana_out_loop(port, ((2 * count) / (len(vp) - 1) - 1)) else: inverse_transform = inverse_transform_posn(frame) tgtpixels = graphics.get_pixels(vp) size = graphics.get_image_size(vp) MAX_X = size[0] MAX_Y = size[1] for y in range(MAX_Y): for x in range(MAX_X): posn = inverse_transform(Posn(x, y)) color = depth_fun(posn.x, posn.y) if color != 1: color = frame.z1 + ((frame.z2 - frame.z1) * color) color = round(min(color, 1) * 255) if color < 255: # assuming that white is the transparency color tgtpixels[x, y] = ( min(color, tgtpixels[x, y][0]), min(color, tgtpixels[x, y][1]), min(color, tgtpixels[x, y][2]), ) graphics.pixels_to_canvas(vp) return painter def image_to_painter(filename): """ Converts an image file to a rune. Probably a work in progress. """ img = graphics.load_image(filename) tolerance = 1 / spread limit = 0.86 # Process def painter(vp, frame): if is_list_or_tuple(vp[0]): def get_depth(x, y, dir): global spread nonlocal pixels for c in range(spread): ox = round(x + dir * (-0.3 * spread + c)) if 0 <= ox < viewport_size: if ( type(pixels[ox, y]) is int ): # this is a workaround for black/white pictures curr = pixels[ox, y] else: curr = pixels[ox, y][0] d = abs(curr - 255 * c / spread) if d <= tolerance * 255: return curr return 255 def ana_out_loop(port, count): nonlocal img size = graphics.get_image_size(img) MAX_X = size[0] MAX_Y = size[1] tsize = graphics.get_image_size(port) TMAX_X = tsize[0] TMAX_Y = tsize[1] tgtpixels = graphics.get_pixels(port) inv_transform = inverse_transform_posn(frame) for y in range(TMAX_Y): for x in range(TMAX_X): orig = inv_transform(Posn(x, y)) rx = round(orig.x) ry = round(orig.y) if 0 <= rx < MAX_X and 0 <= ry < MAX_Y: # within bounds col = get_depth(rx, ry, count) if col > 255 * limit: col = 999 else: col = round( frame.z1 * 255 + (frame.z2 - frame.z1) * col ) if col <= 255: tgtpixels[x, y] = ( min(col, tgtpixels[x, y][0]), min(col, tgtpixels[x, y][1]), min(col, tgtpixels[x, y][2]), ) graphics.pixels_to_canvas(port) pixels = graphics.get_pixels(img) for count, port in enumerate(vp): ana_out_loop(port, ((2 * count) / (len(vp) - 1) - 1)) else: transform = inverse_transform_posn(frame) graphics.blit_pixels( vp, transform, graphics.get_pixels(img), graphics.get_image_size(vp), graphics.get_image_size(img), True, frame.z1, frame.z2, ) # block level image transfer return painter def stereogram(painter): """ Generates a stereogram of a rune. """ E = 300 # distance between eyes in pixels D = 600 # distance between eyes and image plane in pixels delta = 40 # stereo separation MAX_X = round(viewport_size) MAX_Y = viewport_size MAX_Z = 0 CENTRE = round(MAX_X / 2) stereo = vp pixels = graphics.get_pixels(stereo) depthmap = graphics.open_pixmap("temp", viewport_size, viewport_size) depth_pix = graphics.get_pixels(depthmap) painter(depthmap, unit_frame) Infinity = float("inf") depth_pix = graphics.get_pixels(depthmap) def get_depth(x, y): if (0) < x < (MAX_X): return -100 * depth_pix[x, y][0] / 255 - 400 else: return -500 for y in range(MAX_Y): link_left = {} link_right = {} colours = {} for x in range(MAX_X): z = get_depth(x, y) s = delta + z * ( E / (z - D) ) # Determine distance between intersection of lines of sight on image left = x - round(s / 2) # x is integer, left is integer right = left + round(s) # right is integer if left > 0 and right < MAX_X: if (not (left in link_right) or s < link_right[left]) and ( not (right in link_left) or s < link_left[right] ): link_right[left] = round(s) link_left[right] = round(s) # Constraint resolution for x in range(MAX_X): try: s = link_left[x] except KeyError: s = Infinity if s != Infinity: s = x d = None if x > s: d = link_right[x - s] else: d = Infinity if s == Infinity or s > d: link_left[x] = 0 # Drawing step for x in range(MAX_X): s = link_left[x] # should be valid for [0, MAX_X - 1] try: colour = colours[x - s] except KeyError: colour = ( round(random() * 10 / 9 * 255), round(random() * 10 / 9 * 255), round(random() * 10 / 9 * 255), ) pixels[x, y] = colour colours[x] = colour graphics.pixels_to_canvas(stereo) def save_image(filename): """ Saves a rune into an image file. """ graphics.saveImage(vp, filename) def save_hollusion(filename): """ Saves a hollusion into a GIF file. filename is a string without ".gif" at the back. """ if graphics.PIL_available: if active_hollusion == None: raise ("No hollusion active") else: filename += ".gif" frames = list( map(lambda vp: graphics.get_image(vp), active_hollusion("buffer")) ) rev = frames[1 : len(frames) - 1] rev.reverse() frames.extend(rev) PyGif.saveAnimated(filename, frames, 1 / len(frames)) else: print("PIL does not appear to be available")
09-01
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值