@Section @Title { Putting it all together } @Tag { together } @Begin @PP In this section we consider the problem of linking individual shapes together to form complex diagrams like this one: @ID @Fig { @Frame { 10c @Wide 6c @High } // X**0.1 ++ Y**0.4 @BaseOf A:: @Square { @I A } // X**0.4 ++ Y**0.7 @BaseOf B:: @Square { @I B } // X**0.6 ++ Y**0.1 @BaseOf C:: @Square { @I C } // X**0.8 ++ Y**0.6 @BaseOf D:: @Square { @I D } // A @JoinFigures arrow { forward } B // A @JoinFigures arrow { forward } C // B @JoinFigures arrow { forward } C // B @JoinFigures arrow { forward } D // C @JoinFigures arrow { forward } D } We already have several aids to hand: the basic graphics symbols for rotation and scaling, the ability to nest text, equations, and other figures (in fact arbitrary Lout objects) within our shapes; and the ability to define our own symbols. @PP Two other useful aids are the horizontal and vertical concatenation symbols from raw Lout: @ID @Code "A |1.0c B" causes @Code A and @Code B to appear side by side, one centimetre horizontal.con @Index { horizontal concatenation } concatenation @Index { concatenation } apart (this is horizontal concatenation). In general, @Code A and @Code B may be arbitrary objects, and any length is acceptable immediately after the @Code "|" symbol. Similarly, @ID @Code "A /1.0c B" makes @Code A and @Code B appear with @Code B directly beneath {@Code A} vertical.con @Index { vertical concatenation } (this is vertical concatenation), again with a one centimetre separation. You could use tables to get the same effects. Vertical concatenation often appears below in the special form {@Code "//"}, which roughly means vertical concatenation with zero separation. @PP The default values of the various options -- @Code "solid" for {@Code linestyle}, @Code noarrow for {@Code arrow}, and so on -- may be changed by giving options to the @Code "@Fig" symbol: @ID { @Code { "@Fig" " linestyle { noline }" " paint { black }" "{" " @Circle |1c @Square" " /1c @Diamond | @Polygon" "}" } ||7ct @Fig linestyle { noline } paint { black } { @Circle |1c @Square /1c @Diamond | @Polygon } } A complete list of options is given in the next section. @PP @Code "@Fig" provides another aid: the symbols {@Code "@BaseOf"} and base.of @Index @Code "@BaseOf" mark.of @Index @Code "@MarkOf" {@Code "@MarkOf"}. The right parameter of {@Code "@BaseOf"} is an arbitrary object, and its left parameter is a point. As far as Lout is concerned, the result of @Code "@BaseOf" is always an empty object; but the right parameter will appear on the page with the bottom left-hand corner of its base at the point denoted by the left parameter. We stress that Lout has no idea that this is happening, and so cannot prevent the shifted object from writing over other objects or even going off the edge of the page. Of course, this lack of discipline is just what is needed very often in diagrams. @PP The @Code "@MarkOf" symbol works in a similar way, except that the point where the object's alignment marks cross (rather than its bottom left-hand corner) will appear on the page at the point denoted by the left parameter. @PP We can set up a coordinate system for a figure: @ID @OneRow @Code { "@Figure shape { xsize 0 @Label X 0 ysize @Label Y }" "{ 10c @Wide 6c @High }" } In fact, Fig contains this shape under the name {@Code "@Frame"}, so we frame. @Index @Code "@Frame" need only write @ID @Code "@Frame { 10c @Wide 6c @High }" Of course, the right parameter may contain an arbitrary Lout object. @PP Once the frame is set up, we can specify points by their @Code X and @Code Y coordinates, as fractions of the total width and height: @ID @Code "X ** 0.5 ++ Y ** 0.8" To place the squares in the diagram above, we can use @ID @OneRow @Code { "// X**0.1 ++ Y**0.4 @BaseOf A:: @Square { @I A }" "// X**0.4 ++ Y**0.7 @BaseOf B:: @Square { @I B }" "// X**0.6 ++ Y**0.1 @BaseOf C:: @Square { @I C }" "// X**0.8 ++ Y**0.6 @BaseOf D:: @Square { @I D }" } The symbols' precedences are chosen so that this very common situation requires no braces. The result of this is @ID @Fig { @Box margin { 0c } @Frame { 10c @Wide 6c @High } // X**0.1 ++ Y**0.4 @BaseOf A:: @Square { @I A } // X**0.4 ++ Y**0.7 @BaseOf B:: @Square { @I B } // X**0.6 ++ Y**0.1 @BaseOf C:: @Square { @I C } // X**0.8 ++ Y**0.6 @BaseOf D:: @Square { @I D } } {@PageMark sumpoints} where we have drawn a box with margin 0 around the frame to make its extent clear. @PP Now the arrow from @I A to @I B starts on the boundary of @I A at the angle of a line drawn between the centres of @I A and {@I B}: @ID @Code "A@CTR ++ { {A@CTR @Angle B@CTR} A@CIRCUM }" and a similar expression will yield the endpoint of the arrow. Such expressions should be placed into definitions if they are to be used often: joinfigures. @Index @Code "@JoinFigures" @ID @OneRow @Code { "import @Fig" "def @JoinFigures" " left A" " named linestyle { solid }" " named dashlength { 0.15 cm }" " named arrow { noarrow }" " named linewidth { 0.5 pt }" " right B" "{ @Arrow" " from { A\"@CTR\" ++ {{A\"@CTR\" @Angle B\"@CTR\"} A\"@CIRCUM\"} }" " to { B\"@CTR\" ++ {{B\"@CTR\" @Angle A\"@CTR\"} B\"@CIRCUM\"} }" " linestyle { linestyle }" " dashlength { dashlength }" " arrow { arrow }" " linewidth { linewidth }" " {}" "}" } Definitions are the subject of Section {@NumberOf definitions}, although for @Code named parameters, which define options, you have to consult the Lout expert's guide @Cite { $kingston1995lout.expert }. Now, to the figure above we can add @ID @OneRow @Code { "// A @JoinFigures arrow { forward } B" "// A @JoinFigures arrow { forward } C" "// B @JoinFigures arrow { forward } C" "// B @JoinFigures arrow { forward } D" "// C @JoinFigures arrow { forward } D" } to obtain the diagram as it appears at the beginning of this section. Definitions are the best means of managing complexity in diagrams, and serious users of advanced graphics will need to keep a stock of them in a @Code "mydefs" file. @End @Section