/***************************************************************************** * "Irit" - the 3d (not only polygonal) solid modeller. * * * * Written by: Gershon Elber Ver 0.2, May 1995 * ****************************************************************************** * (C) Gershon Elber, Technion, Israel Institute of Technology * ****************************************************************************** * Module to compute the offset of a polygon/line, in the XY plame. * *****************************************************************************/ #include #include #include "irit_sm.h" #include "allocate.h" #include "geom_loc.h" #define MINIMUM_MITTER_SCALE 0.01 /* A mitter scale of 100. */ static RealType GMPolyOffsetAmountConstant(RealType *Coord); /***************************************************************************** * DESCRIPTION: * * Default offset amount estimating routine - returns a constant scaling * * factor of one. * * * * PARAMETERS: * * Coord: Of point as XYZ values. * * * * RETURN VALUE: * * RealType: scaling factor of offset amount. * *****************************************************************************/ static RealType GMPolyOffsetAmountConstant(RealType *Coord) { return 1.0; } /***************************************************************************** * DESCRIPTION: M * Sets the offset amount to be a function of the depth Z value by scaling M * with 1/Z. M * * * PARAMETERS: M * Coord: Of point as XYZ values. M * * * RETURN VALUE: M * RealType: scaling factor of offset amount. M * * * SEE ALSO: M * GMPolyOffset M * * * KEYWORDS: M * GMPolyOffsetAmountDepth M *****************************************************************************/ RealType GMPolyOffsetAmountDepth(RealType *Coord) { return 1.0 / (IRIT_EPS + FABS(Coord[2] + 10.0)); } /***************************************************************************** * DESCRIPTION: M * Computes the offset of a given polygon/line in the XY plane by Ofst. M * M * * * PARAMETERS: M * Poly: To compute its offset in the XY plane. M * IsPolygon: TRUE for a polygon, FALSE for a polyline. M * Ofst: Amount of offset. M * AmountFunc: Scale the offset amount according to this function. A NULL M * here will use a constant scaling factor of one. M * * * RETURN VALUE: M * IPPolygonStruct *: Offset of Poly by Ofst amount. M * * * SEE ALSO: M * GMPolyOffsetAmountDepth M * * * KEYWORDS: M * GMPolyOffset M *****************************************************************************/ IPPolygonStruct *GMPolyOffset(IPPolygonStruct *Poly, int IsPolygon, RealType Ofst, GMPolyOffsetAmountFuncType AmountFunc) { RealType R; VectorType Dir, DirAux, PrevDir; IPPolygonStruct *PolyOfst = IPAllocPolygon(Poly -> Tags, IPCopyVertexList(Poly -> PVertex), NULL); IPVertexStruct *V = Poly -> PVertex, *Vnext = V -> Pnext, *VO = PolyOfst -> PVertex; if (AmountFunc == NULL) AmountFunc = GMPolyOffsetAmountConstant; PT_SUB(PrevDir, Vnext -> Coord, V -> Coord); PrevDir[2] = 0.0; /* Make sure Z is zero. */ PT_NORMALIZE(PrevDir); if (!IsPolygon) { /* Handle the first vertex, if a polyline. */ R = AmountFunc(VO -> Coord) * Ofst; VO -> Coord[0] += PrevDir[1] * R; VO -> Coord[1] -= PrevDir[0] * R; } /* Iterate through the rest of the points. For a polygon the list is */ /* assumed circular. For a polyline the list is assumed NULL terminated.*/ V = Vnext; Vnext = Vnext -> Pnext; VO = VO -> Pnext; if (Vnext != NULL) { do { PT_SUB(Dir, Vnext -> Coord, V -> Coord); Dir[2] = 0.0; /* Make sure Z is zero. */ PT_NORMALIZE(Dir); PT_ADD(DirAux, Dir, PrevDir); PT_NORMALIZE(DirAux); /* Compute the mitter joint's scaling factor of 1/sin(alpha). */ R = sin(acos(-DOT_PROD(Dir, PrevDir)) * 0.5); if (R < MINIMUM_MITTER_SCALE) R = MINIMUM_MITTER_SCALE; R = AmountFunc(VO -> Coord) * Ofst / R; VO -> Coord[0] += DirAux[1] * R; VO -> Coord[1] -= DirAux[0] * R; V = Vnext; Vnext = Vnext -> Pnext; VO = VO -> Pnext; PT_COPY(PrevDir, Dir); } while (Vnext != NULL && V != Poly -> PVertex -> Pnext); } else PT_COPY(Dir, PrevDir); if (!IsPolygon) { /* Do the last point. */ R = AmountFunc(VO -> Coord) * Ofst; VO -> Coord[0] += Dir[1] * R; VO -> Coord[1] -= Dir[0] * R; } else IPUpdatePolyPlane(PolyOfst); return PolyOfst; }