#LincolnSchools Demonstration Control Script. # #Requirements: # - TNTmips 7.0 (or later) # - LincolnSchools layout # - Lincoln Property Viewer Atlas DVD # #This script can only be run as a control script. To use this script, open the LincolnSchools #layout. In the Layout Controls of Spatial Data Display, click Layout / Edit Control Script. numeric schoolPrclScl = 50000; numeric mouselocPrclScl = 15000; numeric labelOffset = 30; numeric schoolSymOffset = 25; class GEOREF vecGeoref; class POINT2D offset; #FindPointInPoly # #pre: #takes mouse location in map coordinates. #vPoints and vPolys assumed to have same georef and be in same projection as point. # #post: #returns 1 if point found in poly and places point in pointloc #returns 0 if point not found in poly, and pointloc is unmodified. func FindPointInPoly( class POINT2D pointloc, class VECTOR vPoints, class VECTOR vPolys, class POINT2D cursorpos) { numeric closepoly = FindClosestPoly(vPolys, cursorpos.x, cursorpos.y); numeric i; for(i=1; i<=vPoints.$info.NumPoints; i++) { numeric polyForPoint = FindClosestPoly(vPolys, vPoints.Point[i].Internal.x, vPoints.Point[i].Internal.y); if(polyForPoint == closepoly) { pointloc.x = vPoints.Point[i].Internal.x; pointloc.y = vPoints.Point[i].Internal.y; return 1; } } return 0; } func FindPointInPolyElemNum( class VECTOR vPoints, class VECTOR vPolys, class POINT2D cursorpos) { numeric closepoly = FindClosestPoly(vPolys, cursorpos.x, cursorpos.y); numeric i; for(i=1; i r.x2) opcode = opcode | 2; if(p.y > r.y2) opcode = opcode | 4; if(p.y < r.y1) opcode = opcode | 8; return opcode; } #clipPoint # #For point a outside the view window, finds the intersection of the view #window's extents with the line from the mouse pointer location to a. #For a point inside the view window, returns the point location. # #pre: all input parameters are in screen coordinates. ext is the view window's #extents in screen coordinates # #post: returned POINT2D is the location on the edge of the extents of #the view window (or just the location of the point if already inside the view). func class POINT2D clipPoint(class POINT2D p, class POINT2D mouseloc, class RECT ext) { class POINT2D out = p; numeric outcode = getBinaryOutcode(out, ext); while(outcode != 0) { class POINT2D temp = out; if(outcode & 1 == 1) { #clip left temp.x = ext.x1; temp.y = mouseloc.y + getTriOppositeLength(mouseloc.x - out.x, mouseloc.y - out.y, ext.x1 - mouseloc.x); } else if(outcode & 2 == 2) { #clip right temp.x = ext.x2; temp.y = mouseloc.y + getTriOppositeLength(mouseloc.x - out.x, mouseloc.y - out.y, ext.x2 - mouseloc.x); } else if(outcode & 4 == 4) { #clip bottom temp.x = mouseloc.x + getTriOppositeLength(mouseloc.y - out.y, mouseloc.x - out.x, ext.y2 - mouseloc.y); temp.y = ext.y2; } else if(outcode & 8 == 8) { #clip top temp.x = mouseloc.x + getTriOppositeLength(mouseloc.y - out.y, mouseloc.x - out.x, ext.y1 - mouseloc.y); temp.y = ext.y1; } out = temp; outcode = getBinaryOutcode(out, ext); } return out; } func calcAngle(class POINT2D a, class POINT2D b) { numeric x = b.x - a.x; numeric y = b.y - a.y; numeric angle = acos(x / sqrt(x^2 + y^2)); if(y < 0) return PI - angle; return angle - PI; } proc drawAngledLine(class GC gc, numeric x, numeric y, numeric angle, numeric len) { numeric a = len * cos(angle); numeric b = len * sin(angle); gc.MoveTo(x, y); gc.DrawTo(x-a, y-b); } proc drawAngledPoint(class GC gc, numeric x, numeric y, numeric angle, numeric len) { numeric a = len * cos(angle); numeric b = len * sin(angle); gc.DrawPoint(x-a, y-b); } func class POINT2D getAngledPoint(numeric x, numeric y, numeric angle, numeric len) { class POINT2D pt; pt.x = x - len * cos(angle); pt.y = y - len * sin(angle); return pt; } #drawParcel #draw a parcel polygon and returns its extents. # #pre: tp is the transparm from layer to screen, and parcelPolyID is the polygon number of the #parcel to draw. func class RECT drawParcel( class GC gc, class TRANSPARM tp, class VECTOR parcelVec, numeric parcelPolyID) { array polyLines[2048]; #arbitrarily large-sized array numeric numPolyLines = GetVectorPolyLineList(parcelVec, polyLines, parcelPolyID); numeric i; class RECT parcelExtents; for(i = 1; i <= numPolyLines; i++) { class POLYLINE curLine = GetVectorLine(parcelVec, polyLines[i]); curLine.ConvertForward(tp); parcelExtents.ExtendRect(curLine.ComputeExtents()); gc.DrawPolyLine2(curLine); } return parcelExtents; } # Function called when the cursor pauses triggering a datatip action event func OnViewDataTipShowRequest(class GRE_VIEW view, class POINT2D mouseScrn, class TOOLTIP datatip) { view.RestoreAll(); class GC gc = CreateGCForDrawingArea(view.DrawingArea); ActivateGC(gc); gc.SetColor("white"); class STRING name = "Schools"; class GRE_LAYER_VECTOR curPtLayer = MainLayout.GetGroupByName("Schools").FirstLayer; class GRE_LAYER_VECTOR curDistLayer = MainLayout.GetGroupByName("School Districts").FirstLayer; class GRE_LAYER_VECTOR parcels = MainLayout.GetGroupByName("Overlays").GetLayerByName("Parcels"); class VECTOR parcelVec; VectorLayerGetObject(parcels, parcelVec); class TRANSPARM tpPrclToScrn = ViewGetTransLayerToScreen(view, parcels); class POINT2D mousepoint; #draw parcel underneath mouse pointer mousepoint = TransPoint2D(mouseScrn, ViewGetTransViewToScreen(view, 1)); mousepoint = TransPoint2D(mousepoint, ViewGetTransMapToView(view, parcels.Projection, 1)); numeric closeParcel = FindClosestPoly(parcelVec, mousepoint.x, mousepoint.y); if(closeParcel != 0 && view.CurrentMapScale < mouselocPrclScl) { gc.SetLineWidth(2); class RECT parcelExtents = drawParcel( gc, tpPrclToScrn, parcelVec, closeParcel); class string parcelAddress = parcelVec.Poly[closeParcel].CA032904.SITUS_ADDR$; gc.DrawTextSetHeightPixels(12); numeric addressLen = gc.TextGetWidth(parcelAddress); gc.SetColor("Lemon Chiffon"); gc.FillRect(parcelExtents.x2 + 10, parcelExtents.y2, addressLen, 12); gc.DrawTextSetFont("Arial"); gc.DrawTextSimple(parcelAddress, parcelExtents.x2 + 10, parcelExtents.y2 + 11); } #draw school locations and parcels class STRINGLIST parcelColors; numeric iterNum=1; for(iterNum = 1; curPtLayer != 0 && curDistLayer != 0; iterNum++) { class VECTOR ptsVect, distVect; VectorLayerGetObject(curPtLayer, ptsVect); VectorLayerGetObject(curDistLayer, distVect); class string styleObj = "STYLE"; gc.DrawUseStyleSubObject(_context.Filename, ptsVect.$info.Name, styleObj); class POINT2D schoolLoc, mousepoint; numeric pointElemNum; mousepoint = TransPoint2D(mouseScrn, ViewGetTransViewToScreen(view, 1)); mousepoint = TransPoint2D(mousepoint, ViewGetTransMapToView(view, curDistLayer.Projection, 1)); if((pointElemNum = FindPointInPolyElemNum(ptsVect, distVect, mousepoint)) != -1) { schoolLoc.x = ptsVect.Point[pointElemNum].Internal.x; schoolLoc.y = ptsVect.Point[pointElemNum].Internal.y; schoolLoc = TransPoint2D(schoolLoc, ViewGetTransMapToView(view, curDistLayer.Projection)); schoolLoc = TransPoint2D(schoolLoc, ViewGetTransViewToScreen(view)); class RECT extents; numeric buf=5; extents.x1 = buf; extents.y1 = buf; extents.x2 = view.width-buf; extents.y2 = view.height-buf; class POINT2D newLocation = clipPoint(schoolLoc, mouseScrn, extents); class TEXTSTYLE textStyle; textStyle.Shadow = 1; gc.TextStyle = textStyle; gc.DrawTextSetColors("white", "black"); gc.DrawTextSetFont("Arial Black"); gc.DrawTextSetHeightPixels(12); class string schoolName = ptsVect.Point[pointElemNum].SchoolName.Name$; schoolName = schoolName.toUppercase(); numeric textWidth = gc.TextGetWidth(schoolName); gc.DrawSetPointStyle("School"); if(newLocation.x != schoolLoc.x || newLocation.y != schoolLoc.y) { gc.SetColor("white"); numeric angle = calcAngle(schoolLoc, mouseScrn); gc.DrawArrow(newLocation.x, newLocation.y, angle * 180 / PI, 20, 20); gc.SetLineWidth(3); drawAngledLine(gc, newLocation.x, newLocation.y, angle, 40); gc.SetLineWidth(1); drawAngledPoint(gc, newLocation.x, newLocation.y, angle, 70); class POINT2D textpos = getAngledPoint(newLocation.x, newLocation.y, angle, 70); gc.DrawTextSimple(schoolName, textpos.x - textWidth/2, textpos.y + labelOffset); } else { if(view.CurrentMapScale < schoolPrclScl) { class POINT2D schoolLocParcel = TransPoint2D(schoolLoc, ViewGetTransViewToScreen(view, 1)); schoolLocParcel = TransPoint2D(schoolLocParcel, ViewGetTransMapToView(view, parcels.Projection, 1)); numeric schoolPolyID = FindClosestPoly(parcelVec, schoolLocParcel.x, schoolLocParcel.y); gc.DrawSetLineStyle("Parcel"); class RECT parcelExtents = drawParcel(gc, tpPrclToScrn, parcelVec, schoolPolyID); class POINT2D screenCenter; screenCenter.x = view.Width/2; screenCenter.y = view.Height/2; numeric yPointPos = parcelExtents.y2 + schoolSymOffset; #gc.DrawSetPointStyle("School"); gc.DrawPoint(newLocation.x, yPointPos); gc.DrawTextSimple(schoolName, newLocation.x - textWidth/2, yPointPos + labelOffset); } else { gc.DrawPoint(newLocation.x, newLocation.y); gc.DrawTextSimple(schoolName, newLocation.x - textWidth / 2, newLocation.y + labelOffset); } } } curPtLayer = curPtLayer.NextLayer; curDistLayer = curDistLayer.NextLayer; } return 1; }