------------------------------------------------------------------ -- -- NAME: CONVERT_NDC_DC - BODY -- DISCREPANCY REPORTS: -- ------------------------------------------------------------------ -- File: CONVERT_NDC_DC_MA_B.ADA -- Level: ma, 0a with DC_POINT_OPS; with NDC_POINT_OPS; use DC_POINT_OPS; use NDC_POINT_OPS; package body CONVERT_NDC_DC is -- This package body implements the SCALING and TRANSFORMATION -- functions used to convert between the NDC and DC coordinate systems. -- -- Type NDC_DC_SCALE_TYPE contains the ready-to-use scale and shift -- factors needed to perform the workstation transformation and its -- inverse. -- -- Define index for range arrays type LIMIT is (MIN, MAX); -- Define a new kind of rectangle which is easier to manipulate, -- using NDC_POINT_OPS, than the GKS_COORDINATE_SYSTEM records type NDC_RECTANGLE is array (LIMIT) of NDC . POINT; type DC_RECTANGLE is array (LIMIT) of DC . POINT; -- -- Define simple conversions -- function NDC_POINT (POINT : DC . POINT ) return NDC . POINT; -- Convert each coordinate using basic conversion function NDC_VECTOR (VECTOR : DC . VECTOR ) return NDC . VECTOR; -- Convert each coordinate using basic conversion function DC_POINT (POINT : NDC . POINT ) return DC . POINT; -- Convert each coordinate using basic conversion function DC_VECTOR (VECTOR : NDC . VECTOR ) return DC . VECTOR; -- Convert each coordinate using basic conversion -- -- Define scaling conversions -- procedure SET_UNIFORM_SCALES (WINDOW : WINDOW_TYPE; VIEWPORT : VIEWPORT_TYPE; SCALE : out NDC_DC_SCALE_TYPE) is -- Compute SCALE based on largest image of WINDOW fitting in the -- lower-left of VIEWPORT. This retains the uniform scale factors. -- The NDC_DC_SCALE_TYPE is not, itself, restricted to uniform -- scaling; it is this procedure which produces restricted values. -- -- WINDOW - NDC units window of uniform transform -- VIEWPORT - DC units viewport of uniform transform -- SCALE - private type holding returned scale values -- Get rectangles into two-point form, for readable operations W_RECT : NDC_RECTANGLE := NDC_RECTANGLE '( NDC . POINT '( WINDOW . XMIN, WINDOW . YMIN), NDC . POINT '( WINDOW . XMAX, WINDOW . YMAX)); -- W_RECT is the window rectangle V_RECT : DC_RECTANGLE := DC_RECTANGLE '( DC . POINT '( VIEWPORT . XMIN, VIEWPORT . YMIN), DC . POINT '( VIEWPORT . XMAX, VIEWPORT . YMAX)); -- V_RECT is the viewport rectangle -- Compute deltas W_DELTA : NDC . VECTOR := W_RECT (MAX) - W_RECT (MIN); -- W_DELTA is the size of the window V_DELTA : DC . VECTOR := V_RECT (MAX) - V_RECT (MIN); -- V_DELTA is the size of the viewport W_SCALE : NDC . POINT; -- W_SCALE is the scale factors to transform to the window-space V_SCALE : DC . POINT; -- V_SCALE is the scale factors to transform to the viewport-space begin begin W_SCALE . X := W_DELTA . X / NDC_TYPE (V_DELTA . X); exception when others => -- V_DELTA . X may be zero resulting in overflow W_SCALE . X := 1.0; end; begin W_SCALE . Y := W_DELTA . Y / NDC_TYPE (V_DELTA . Y); exception when others => -- V_DELTA . Y may be zero resulting in overflow W_SCALE . Y := 1.0; end; begin V_SCALE . X := V_DELTA . X / DC_TYPE (W_DELTA . X); exception when others => -- W_DELTA . X may be zero resulting in overflow V_SCALE . X := 1.0; end; begin V_SCALE . Y := V_DELTA . Y / DC_TYPE (W_DELTA . Y); exception when others => -- W_DELTA . Y may be zero resulting in overflow V_SCALE . Y := 1.0; end; -- To achieve a uniform scale, the dimension of V_SCALE with the -- smaller scale is allowed to dominate the other dimension . if V_SCALE . X < V_SCALE . Y then -- X scale dominates Y scale V_SCALE . Y := V_SCALE . X; -- W_SCALE follows V_SCALE proportions W_SCALE . Y := W_SCALE . X; else -- Y scale dominates X scale V_SCALE . X := V_SCALE . Y; -- W_SCALE follows V_SCALE proportions W_SCALE . X := W_SCALE . Y; end if; SCALE := NDC_DC_SCALE_TYPE' ( V_SCALE => V_SCALE, V_SHIFT => V_RECT (MIN) - V_SCALE * DC_POINT (W_RECT (MIN)), W_SCALE => W_SCALE, W_SHIFT => W_RECT (MIN) - W_SCALE * NDC_POINT (V_RECT (MIN))); end SET_UNIFORM_SCALES; -- Define Conversion to DC types function DC_POINT (POINT : NDC . POINT; SCALE : NDC_DC_SCALE_TYPE) return DC . POINT is -- Convert POINT to DC units using SCALE factor -- -- POINT - input POINT -- SCALE - pre-computed scaling factors begin return DC_POINT (POINT) * SCALE . V_SCALE + SCALE . V_SHIFT; end DC_POINT; function DC_POINT_ARRAY (POINT_ARRAY : NDC . POINT_ARRAY; SCALE : NDC_DC_SCALE_TYPE) return DC . POINT_ARRAY is -- Convert all POINTs in POINT_ARRAY to DC units using SCALE factor -- -- POINT_ARRAY - array of input POINTs -- SCALE - pre-computed scaling factors POINTS : DC . POINT_ARRAY (POINT_ARRAY'RANGE); -- Array to hold converted points begin for I in POINT_ARRAY'RANGE loop POINTS (I) := DC_POINT (POINT_ARRAY (I), SCALE); end loop; return POINTS; end DC_POINT_ARRAY; function DC_RECTANGLE_LIMITS (RECTANGLE_LIMITS : NDC . RECTANGLE_LIMITS; SCALE : NDC_DC_SCALE_TYPE) return DC . RECTANGLE_LIMITS is -- Convert RECTANGLE_LIMITS to DC units using SCALE factor -- -- RECTANGLE_LIMITS - input RECTANGLE_LIMITS -- SCALE - pre-computed scaling factors SX : DC_TYPE renames SCALE . V_SCALE . X; SY : DC_TYPE renames SCALE . V_SCALE . Y; DX : DC_TYPE renames SCALE . V_SHIFT . X; DY : DC_TYPE renames SCALE . V_SHIFT . Y; begin return DC . RECTANGLE_LIMITS' ( XMIN => DC_TYPE (RECTANGLE_LIMITS . XMIN) * SX + DX, XMAX => DC_TYPE (RECTANGLE_LIMITS . XMAX) * SX + DX, YMIN => DC_TYPE (RECTANGLE_LIMITS . YMIN) * SY + DY, YMAX => DC_TYPE (RECTANGLE_LIMITS . YMAX) * SY + DY); -- RECTANGLE_LIMITS are not compatible with DC_POINT_OPS, so -- component-by-component expressions are used. end DC_RECTANGLE_LIMITS; -- The following functions are for relative scaling only, -- not absolute positions function DC_VECTOR (VECTOR : NDC . VECTOR; SCALE : NDC_DC_SCALE_TYPE) return DC . VECTOR is -- Convert VECTOR to DC units using SCALE factor -- -- VECTOR - input VECTOR -- SCALE - pre-computed scaling factors begin return DC_VECTOR (VECTOR) * DC . VECTOR (SCALE . V_SCALE); end DC_VECTOR; function DC_SIZE (SIZE : NDC . SIZE; SCALE : NDC_DC_SCALE_TYPE) return DC . SIZE is -- Convert SIZE to DC units using SCALE factor -- -- SIZE - input SIZE -- SCALE - pre-computed scaling factors SX : DC . MAGNITUDE := DC . MAGNITUDE (abs SCALE . V_SCALE . X); -- Scale factor compatible with output type (DC . MAGNITUDE) SY : DC . MAGNITUDE := DC . MAGNITUDE (abs SCALE . V_SCALE . Y); -- Scale factor compatible with output type (DC . MAGNITUDE) begin return DC . SIZE' ( XAXIS => DC . MAGNITUDE (SIZE . XAXIS) * SX, YAXIS => DC . MAGNITUDE (SIZE . YAXIS) * SY); end DC_SIZE; -- -- Define bodies of simple conversions -- It is possible to use UNCHECKED_CONVERSIONS if the element types -- are the same. However, explicit handling of each component is -- more general. -- function DC_POINT (POINT : NDC . POINT ) return DC . POINT is -- Convert `POINT' to an equal `DC . POINT' (no scaling) -- -- POINT - input NDC . POINT begin return DC . POINT' (DC_TYPE (POINT . X), DC_TYPE (POINT . Y)); end DC_POINT; function DC_VECTOR (VECTOR : NDC . VECTOR ) return DC . VECTOR is -- Convert `VECTOR' to an equal `DC . VECTOR' (no scaling) -- -- VECTOR - input NDC . VECTOR begin return DC . VECTOR' (DC_TYPE (VECTOR . X), DC_TYPE (VECTOR . Y)); end DC_VECTOR; -- Define Conversion to NDC types function NDC_POINT (POINT : DC . POINT; SCALE : NDC_DC_SCALE_TYPE) return NDC . POINT is -- Convert POINT to DC units using SCALE factor -- -- POINT - input POINT -- SCALE - pre-computed scaling factors begin return NDC_POINT (POINT) * SCALE . W_SCALE + SCALE . W_SHIFT; end NDC_POINT; function NDC_POINT_ARRAY (POINT_ARRAY : DC . POINT_ARRAY; SCALE : NDC_DC_SCALE_TYPE) return NDC . POINT_ARRAY is -- Convert all POINTs in POINT_ARRAY to NDC units using SCALE factor -- -- POINT_ARRAY - array of input POINTs -- SCALE - pre-computed scaling factors POINTS : NDC . POINT_ARRAY (POINT_ARRAY'RANGE); -- Array to hold converted points begin for I in POINT_ARRAY'RANGE loop POINTS (I) := NDC_POINT (POINT_ARRAY (I),SCALE); end loop; return POINTS; end NDC_POINT_ARRAY; function NDC_RECTANGLE_LIMITS (RECTANGLE_LIMITS : DC . RECTANGLE_LIMITS; SCALE : NDC_DC_SCALE_TYPE) return NDC . RECTANGLE_LIMITS is -- Convert RECTANGLE_LIMITS to NDC units using SCALE factor -- -- RECTANGLE_LIMITS - input RECTANGLE_LIMITS -- SCALE - pre-computed scaling factors SX : NDC_TYPE renames SCALE . W_SCALE . X; SY : NDC_TYPE renames SCALE . W_SCALE . Y; DX : NDC_TYPE renames SCALE . W_SHIFT . X; DY : NDC_TYPE renames SCALE . W_SHIFT . Y; begin return NDC . RECTANGLE_LIMITS' ( XMIN => NDC_TYPE (RECTANGLE_LIMITS . XMIN) * SX + DX, XMAX => NDC_TYPE (RECTANGLE_LIMITS . XMAX) * SX + DX, YMIN => NDC_TYPE (RECTANGLE_LIMITS . YMIN) * SY + DY, YMAX => NDC_TYPE (RECTANGLE_LIMITS . YMAX) * SY + DY); -- RECTANGLE_LIMITS are not compatible with DC_POINT_OPS, so -- component-by-component expressions are used. end NDC_RECTANGLE_LIMITS; -- The following functions are for relative scaling only, -- not absolute positions function NDC_VECTOR (VECTOR : DC . VECTOR; SCALE : NDC_DC_SCALE_TYPE) return NDC . VECTOR is -- Convert VECTOR to NDC units using SCALE factor -- -- VECTOR - input VECTOR -- SCALE - pre-computed scaling factors begin return NDC_VECTOR (VECTOR) * NDC . VECTOR (SCALE . W_SCALE); end NDC_VECTOR; function NDC_SIZE (SIZE : DC . SIZE; SCALE : NDC_DC_SCALE_TYPE) return NDC . SIZE is -- Convert SIZE to NDC units using SCALE factor -- -- SIZE - input SIZE -- SCALE - pre-computed scaling factors SX : NDC . MAGNITUDE := NDC . MAGNITUDE (abs SCALE . W_SCALE . X); -- Scale factor compatible with output type (NDC . MAGNITUDE) SY : NDC . MAGNITUDE := NDC . MAGNITUDE (abs SCALE . W_SCALE . Y); -- Scale factor compatible with output type (NDC . MAGNITUDE) begin return NDC . SIZE' ( XAXIS => NDC . MAGNITUDE (SIZE . XAXIS) * SX, YAXIS => NDC . MAGNITUDE (SIZE . YAXIS) * SY); end NDC_SIZE; -- Define bodies of simple conversions -- It is possible to use UNCHECKED_CONVERSIONS if the element types -- are the same . However, explicit handling of each component is -- more general . function NDC_POINT (POINT : DC . POINT ) return NDC . POINT is -- Convert `POINT' to an equal `NDC . POINT' (no scaling) -- -- POINT - input DC . POINT begin return NDC . POINT' (NDC_TYPE (POINT . X), NDC_TYPE (POINT . Y)); end NDC_POINT; function NDC_VECTOR (VECTOR : DC . VECTOR ) return NDC . VECTOR is -- Convert `VECTOR' to an equal `NDC . VECTOR' (no scaling) -- -- VECTOR - input DC . VECTOR begin return NDC . VECTOR' (NDC_TYPE (VECTOR . X), NDC_TYPE (VECTOR . Y)); end NDC_VECTOR; end CONVERT_NDC_DC;