Model of a commercial district
In this section we discuss the development of some parameterized symbolic models of virtual warehousing buildings, that could be used by a security enforcement system to model the protection and the security of a logistics company. Our modeling design will be based on the elementary standardized items of such kind of building trade, i.e.~on the models of the pallet and of the storage rack.
Modular warehouse elements
In Listing 1 is given the PLaSM coding of the EUR-Epal pallet specification, shown in Figure 6a. Each layer is generated by Cartesian product of three 1D polyhedral complexes. The four wooden layers are stacked by the TOP operator, and finally the solid angles are subtracted to the model, named europallet. The single angle is generated by extrusion (Cartesian product by the 1D segment q:1.66) of the properly-scaled standard triangle simplex:2 of unit size.
DEF europallet = (layer4 TOP layer3 TOP layer2 TOP layer1) - angles WHERE dy = (0.800 - 0.145*3 - 0.100*2)/4, layer1 = q:1.2 * q:<0.145,-:dy,0.1,-:dy,0.145,-:dy,0.1,-:dy,0.145> * q:0.022, layer2 = q:<0.145,-0.382,0.145,-0.382,0.145> * q:0.8 * q:0.022, layer3 = q:<0.145,-0.382,0.145,-0.382,0.145> * q:<0.1,-:(dy+0.045),-0.1,-:dy,0.145,-:dy,-0.1,-:(dy+0.045),0.1> * q:0.1, layer4 = q:1.2 * q:<0.1,-:(dy+0.045),-0.1,-:dy,0.145,-:dy,-0.1,-:(dy+0.045),0.1> * q:0.022, angle = S:<1,2>:<0.022,0.022>:(simplex:2) * q:1.66, angles = STRUCT:< angle,T:1:1.2 ~ S:1:-1,angle,T:2:0.8 ~ S:2:-1,angle,S:1:-1~T:1:-1.2,angle > END; VIEW:europallet;
A deposit of pallets is generated by the code in Listing 2 and displayed in Figure 6c. The palletpile function concatenates n instances of the pair <europalette,T:3:0.166>, where T:3:0.166 is a z -translation of 0.166 meters, and assembles the pile according to the semantics of the PHIGS structures [iso/iec 9592-1 1989]. The europalette symbol contains a geometric value obtained by europallet by exchanging the x and y coordinates, according to the semantics of the MAP operator.
DEF palletpile(n::isintpos) = (STRUCT~##:n):<europalette,T:3:0.166> WHERE europalette = MAP:[s2,s1,s3]:europallet END; DEF palletwall(n,m::isintpos) = (STRUCT~##:m):<palletpile:n,T:1:0.8>; VIEW:(palletwall:<30,12>);
In Listing 3 we show the definition of a warehouse rack parameterized with respect to the number nn of floors, the number m of piles, the height, width, and depth of the single floor, and even to the geometry of the stored warehouse. The frame module is a structure of four column at the angles of the rack element, named theframe, which also contains two horizzontal elements hsupport and two pairs of diagonal elements dsupport1 and dsupport2. It may be useful to notice that dsupport2 is generated by applying a suitable vertex MAP to dsupport1, that reverses the sign of the x coordinates, and applies a linear map $y \mapsto depth •y$ to the y coordinates, while leaving the z coordinates invariant.
DEF warehouse_rack (nn,m::isintpos)(height,width,depth::isrealpos) (loading::ispol) = (STRUCT~##:m):< pile,T:1:(width+0.2)> WHERE frame_module = STRUCT:< column,T:2:depth,column,T:1:width,column,T:2:(-:depth),column >, column = cylinder:<0.02,height>:12, hsupport = STRUCT:<T:1:-0.02,cuboid:<0.04,depth,0.02>>, dsupport1 = (R:<2,3>:(atan:(height/depth))~CUBOID):<0.01,SQRT:(height**2+depth**2),0.02>, dsupport2 = MAP:[-~S1,K:depth - S2,S3]:dsupport1, beams = q:width * (q~#:nbeams):0.1 * q:<-0.02,0.1> TOP loading, nbeams = FLOOR:(depth/0.1), theframe = STRUCT:<beams,frame_module ,dsupport1,dsupport2,hsupport,T:1:width,hsupport,dsupport1,dsupport2>, pile = (STRUCT~##:nn):<theframe,T:3:height> TOP top_pile, top_pile = STRUCT:<beams,hsupport,T:1:width,hsupport > END;
In Listing 4 we show a possible definition for the loading of the warehouse rack, in this case given as a double pair, in turn assembled as a carton and an europallet oriented with the main axis along the y direction. The loading value defined here is the one used in Figures 7a and 7b.
DEF loading = STRUCT:< pair,T:1:1.2, pair > WHERE pair = MAP:[s2,s1,s3]:europallet TOP carton, carton = CUBOID:<0.7,1.2,1.2> END; VIEW:(pallet_rack:<6,8>:<1.8,2.5,1.5>: loading);
The model shown in Figure 7c is generated by the PLaSM code in Listing 5. The warehouse function has the same interface than the warehouse rack function, but without the formal parameter loading of polyhedral type. The reader may see that the argument expression of the VIEW primitive is used to generate three warehouse instances with different actual parameter values, and to locate the 1st and 3rd instances below and on the left of the 2nd one, respectively. The reader should understand that a multiple infix expression like exp1 OP1 exp2 OP2 ex3 is evaluated from left-toright as ((exp1 OP1 exp2 ) OP2 ex3 ).
%DEF warehouse (nn,m::isintpos) (height,width,depth::isrealpos) = .... ; VIEW:(warehouse:<3,4>:<1.8,2.5,1.5> STRUCT T:3:(1.8*3):(warehouse:<1,4>:<1.8,2.5,1.0>) LEFT T:1:0.2:(warehouse:<4,3>:<1.8,2,1.0>) );%
Warehouse buildings
In order to generate some nice models of very different warehouse buildings, we start by preparing a small geometric library, allowing for both realistic and fancy construction models. We have a double aim: (a) to generate some complex models by writing an extremely compact PLaSM code; (b) to show the amazing descriptive power of the language. In particular, we proceed in the following way. First, we generate three Coons' surfaces S, S, S: [0, 1]^2 \rightarrow E^3.
Then we linearly combine such surfaces pairwise, to generate two volume maps V0, V1: [0, 1]^3 \rightarrow E^3 that we will use to produce the columns and the beams, respectively, according to different engineering schemes for the resistant structure. Let us notice that a CoonsPatch is a surface generated by transfinite interpolation of 4 boundary curves u0,u1,v0,v1. Bezier is the PLaSM naming of the transfinite and multivariate B •ezier library function (see, e.g. [Paoluzzi 2003]). The physical dimensions of the building are defined by the parameters w,d,h of the surface function, which stand for width, depth, and height (in meters), respectively. The further parameters uw,ud,uh and vw,vd,vh are used to variate the geometry of the beams and the roof in the u, v directions of the domain space, and are all zero in the building of Figure 9a.
DEF surface(w,d,h::isreal)(uw,ud,uh::isreal) (vw,vd,vh::isreal) = CoonsPatch:<u0,u1,v0,v1> WHERE u0 = bezier:s1:<<0,0,h>,<w/3,0,h+uh>,<2*w/3,0,h+uh>,<w,0,h>>, u1 = bezier:s1:<<0,d,h>,<w/3,d,h+uh>,<2*w/3,d,h+uh>,<w,d,h>>, v0 = bezier:s1:<<0,0,h>,<0,d/3,h+vh>,<0,2*d/3,h+vh>,<0,d,h>> (AA:COMP~DISTR) [S2], v1 = bezier:s1:<<w,0,h>,<w,d/3,h+vh>,<w,2*d/3,h+vh>,<w,d,h>> (AA:COMP~DISTR) [S2] END; DEF S_0 = surface:<40,16,0>:<0,0,0>:<0,0,0>; DEF S_1 = surface:<40,16,10>:<0,0,-1>:<0,0,1.0>; DEF S_2 = surface:<40,16,12>:<0,0,-2>:<0,0,2.0>; DEF V0 = bezier:s3:< S_0, S_1 >; DEF V1 = bezier:s3:< S_1, S_2 >;
The actual building shape is defined by suitably setting some subsets of the domain 3 of the volume maps V0 , V1 to accomodate the various building fabric subsystems, i.e. columns, beams, roofs, enclosure1 and enclosure2, each one defined as a Cartesian product of three 1D (set of) intervals. The resulting building as a set of E3 points is just a STRUCT aggregation of the MAPped subdomains of [0, 1]3 . Figure 9 shows some examples.
DEF dom (n::isint; m::isrealpos) = ##:(n - 1):<full,-:empty> AR full WHERE full = m/n, empty = (1- full*n)/(n - 1) END; DEF pattern = dom:<12,0.10>; DEF columns = q:pattern * q:<0.05,-0.9,0.05>* q:1; DEF beams = q:pattern * q:(#:20:0.05) * q:1; DEF roofs = (q ~ aa:-):pattern * q:(#:20:0.05) * q:<-0.8,0.2>; DEF enclosure1 = (q ~ aa:-):pattern * q:<0.01,-0.98,0.01> * q:<0.5,-0.5>; DEF enclosure2 = (q ~ aa:-):pattern * q:<0.01,-0.98,0.01> * q:1;
DEF building1 = STRUCT:< MAP:V0:columns, MAP:V1:beams, MAP:V1:roofs, MAP:V0:enclosure1, MAP:V1: enclosure2%, deposit% > WHERE S_0 = surface:<60,12,0>:<0,0,0>:<0,0,0>, S_1 = surface:<60,12,10>:<0,0,-1>:<0,0,1.0>, S_2 = surface:<60,12,12>:<0,0,-2>:<0,0,2.0>, V0 = bezier:S3:< S_0, S_1 >, V1 = bezier:S3:< S_1, S_2 > END; DEF building2 = STRUCT:< MAP:V0:columns, MAP:V1:beams, MAP:V1:roofs, MAP:V0:enclosure1, MAP:V1: enclosure2%, deposit% > WHERE S_0 = surface:<60,12,0>:<0,0,0>:<0,0,0>, S_1 = surface:<60,12,10>:<0,0,-1>:<0,0,-1.0>, S_2 = surface:<60,12,12>:<0,0,-2>:<0,0,-2.0>, V0 = bezier:S3:< S_0, S_1 >, V1 = bezier:S3:< S_1, S_2 > END; DEF building3 = STRUCT:< MAP:V0:columns, MAP:V1:beams, MAP:V1:roofs, MAP:V0:enclosure1, MAP:V1: enclosure2%, deposit% > WHERE S_0 = surface:<60,12,0>:<0,0,0>:<0,0,0>, S_1 = surface:<60,12,10>:<0,0,1>:<0,0,0>, S_2 = surface:<60,12,12>:<0,0,2>:<0,0,0>, V0 = bezier:S3:< S_0, S_1 >, V1 = bezier:S3:< S_1, S_2 > END; DEF building4 = STRUCT:< MAP:V0:columns, MAP:V1:beams, MAP:V1:roofs, MAP:V0:enclosure1, MAP:V1: enclosure2%, deposit% > WHERE S_0 = surface:<60,12,0>:<0,0,0>:<0,0,0>, S_1 = surface:<60,12,10>:<0,0,0>:<0,0,1>, S_2 = surface:<60,12,12>:<0,0,0>:<0,0,2>, V0 = bezier:S3:< S_0, S_1 >, V1 = bezier:S3:< S_1, S_2 > END; DEF loading_rack = (T:1:20~R:<1,2>:(pi/2)~ warehouse_rack:<4,3>:<1.8, 2.5, 1.5>): loading; DEF deposit = (STRUCT ~ ##:10):< loading_rack , T:1:3.6>; VIEW: building1;
Simple road models
The function road in Listing 8 takes as input a polycurve output, i.e. a sequence of triples of control points, as well as a width w, and returns a solid model of the road having as axis the set of quadratic B •ezier curves produced by the control points. The set of roads of our model in generated by Listing 9.
DEF road(w::isreal) = STRUCT ~ aa:(stripe:<w,6>); DEF stripe(width::IsReal;n::IsIntPos) (points::ismat) = MAP:coordFuncs:domain WHERE coordFuncs = Bezier:s1:points vectsum (s2 scalarvectprod (Norm2 ~DerBezier):points), domain = (S:2:(width/2) ~ T:<1,2>:<1E-5,-1>): (Intervals:1:n * Intervals:2:1) END;
DEF polycurve (radius::isreal) (points::ismat) = if:< gt:2 ~ len, cat ~ addExtremeLinearSegments ~ distributeLinearSegmentsBetweenQuadratic, id> :points WHERE addExtremeLinearSegments = [[[k:(first:points), s1~s1]], id, [[last~last, k:(last:points)]]], distributeLinearSegmentsBetweenQuadratic = rtail~cat~trans~[id, ar~[trans~[rtail~s3, tail~s1]~trans, K:0]] ~ generateQuadraticSegments, generateQuadraticSegments = aa:(newpoints:radius) ~ triples, triples = trans~[rtail~rtail, tail~rtail, tail~tail], newpoints (b::isrealpos) (p1,p2,p3::ispoint) = <p12,p2,p23> WHERE v12 = p1 vectdiff p2, v23 = p3 vectdiff p2, p12 = p2 vectsum (v12 scalarvectprod (b / vectnorm:v12)), p23 = p2 vectsum (v23 scalarvectprod (b / vectnorm:v23)) END END;
DEF road(width::isreal) = STRUCT ~ AA:(stripe:<width,6>); DEF avenue1 = (road:6 ~ polycurve:10): <<0,0>,<0,-74>,<0,-148>>; DEF avenue2 = (road:6 ~ polycurve:10): <<78,-12>,<78,-151>,<-78,-151>,<-78,-12>>; DEF parking = (T:<1,2>:<3,-141> ~ CUBOID): <72,40,0.2>; DEF road112 = (road:8 ~ polycurve:20):<<0,-160>,<-90,-160>,<-90,4>,<90+170,4>,<90+170,-180>,<90,-180>,<30,-160>,<0,-160>>; DEF road01 = (STRUCT ~ AA:(road:8 ~ polycurve:20) ~ [ID, AA:[s1, C:+:-8 ~ s2]]): < <-190,-160>,<0,-160>,<30,-160>,<90,-180>,<260,-180>,<360,-180> >; VIEW: road01;
The model of a commercial district
The VR model of a whole commercial district, including roads, service zones, parkings and several warehouse building with internal warehouse decks, merchandise containers, cartons and pallets is generated using the code discussed in the above subsections, as the value produced by the evaluation of the commercial district symbol, given in Listing 10 and shown in Figure 1. Such a virtual environment is very easy to set up or digitize, as it only requires a small set of points to define the control points of the road axes.
DEF triple(p::ispol) = (STRUCT ~ ##:3 ~ [ID, T:2 ~ SIZE:2]):p; DEF double(b1,b2::ispol) = STRUCT:<T:<1,2>:<-75,-48>,b1,T:2:-48,b2>; DEF avenue12 = STRUCT:<avenue1,avenue2,parking, S:1:-1:parking, (double ~ AA:triple):<building1,building2>, (S:1:-1 ~ double ~ AA:triple):<building3,building4> >; DEF commercial_district = STRUCT:< road01,road112,avenue12,T:1:170,S:1:-1:avenue12 >; VIEW:commercial_district;