জিওটুলস [বন্ধ] সহ চিত্রটি মানচিত্র তৈরি করা এবং এটিকে ছবিতে সংরক্ষণ করা


9

আমি জিওটুলস সহ একটি মানচিত্র তৈরি করতে এবং এটি একটি চিত্রে সংরক্ষণ করতে চাই (যেমন জেপিইজি)। আমার প্রয়োজনীয়তা সহজ:

  1. 2 স্তর সহ বিশ্বের মানচিত্র তৈরি করুন: রাজনৈতিক সীমানা এবং একটি গ্র্যাচিকুল। স্তরগুলি বিভিন্ন উত্স এবং বিভিন্ন অনুমান থেকে।
  2. মানচিত্রকে বিভিন্ন অনুমানগুলিতে আউটপুট করুন (উদাঃ "EPSG: 5070", "EPSG: 4326", "EPSG: 54012", "EPSG: 54009" ইত্যাদি)
  3. আউটপুটটি বিভিন্ন এওআইতে ক্লিপ করুন (যেমন -124.79 থেকে -66.9 লম্বা, 24.4 থেকে 49.4 ল্যাট)।

আমি এপিআইয়ের মাধ্যমে এই প্রোগ্রামটিমেটিকভাবে করতে চাই। এখনও অবধি আমার সীমাবদ্ধ সাফল্য ছিল। আমি এই পদ্ধতির ব্যবহার করে বিভিন্ন অনুমানে একটি মানচিত্র এবং আউটপুট তৈরি করতে শিখেছি:

//Step 1: Create map
MapContent map = new MapContent();
map.setTitle("World");

//Step 2: Set projection
CoordinateReferenceSystem crs = CRS.decode("EPSG:5070"); //Conic projection over US
MapViewport vp = map.getViewport();
vp.setCoordinateReferenceSystem(crs);

//Step 3: Add layers to map
CoordinateReferenceSystem mapCRS = map.getCoordinateReferenceSystem();
map.addLayer(reproject(getPoliticalBoundaries(), mapCRS));
map.addLayer(reproject(getGraticules(), mapCRS));

//Step 4: Save image
saveImage(map, "/temp/graticules.jpg", 800);

সংরক্ষণ পদ্ধতিটি জিওটুলস ওয়েবসাইট থেকে সরাসরি :

public void saveImage(final MapContent map, final String file, final int imageWidth) {

    GTRenderer renderer = new StreamingRenderer();
    renderer.setMapContent(map);

    Rectangle imageBounds = null;
    ReferencedEnvelope mapBounds = null;
    try {
        mapBounds = map.getMaxBounds();
        double heightToWidth = mapBounds.getSpan(1) / mapBounds.getSpan(0);
        imageBounds = new Rectangle(
                0, 0, imageWidth, (int) Math.round(imageWidth * heightToWidth));

    } catch (Exception e) {
        // failed to access map layers
        throw new RuntimeException(e);
    }

    BufferedImage image = new BufferedImage(imageBounds.width, imageBounds.height, BufferedImage.TYPE_INT_RGB);

    Graphics2D gr = image.createGraphics();
    gr.setPaint(Color.WHITE);
    gr.fill(imageBounds);

    try {
        renderer.paint(gr, imageBounds, mapBounds);
        File fileToSave = new File(file);
        ImageIO.write(image, "jpeg", fileToSave);

    } catch (IOException e) {
        throw new RuntimeException(e);
    }
}

পুনঃপ্রকাশের পদ্ধতিটি আমার আবিষ্কার। এটি কিছুটা হ্যাক তবে এর একমাত্র উপায় আমি কোনও নির্দিষ্ট অভিক্ষেপে কোনও চিত্র আউটপুট খুঁজে পেতে পারি।

private static Layer reproject(Layer layer, CoordinateReferenceSystem mapCRS) throws Exception {

    SimpleFeatureSource featureSource = (SimpleFeatureSource) layer.getFeatureSource();


  //Define coordinate transformation
    CoordinateReferenceSystem dataCRS = featureSource.getSchema().getCoordinateReferenceSystem();
    boolean lenient = true; // allow for some error due to different datums
    MathTransform transform = CRS.findMathTransform(dataCRS, mapCRS, lenient);


  //Create new feature collection
    SimpleFeatureCollection copy = FeatureCollections.newCollection("internal");
    SimpleFeatureType featureType = SimpleFeatureTypeBuilder.retype(featureSource.getSchema(), mapCRS);
    SimpleFeatureIterator iterator = featureSource.getFeatures().features();
    try {

        while (iterator.hasNext()) {

            SimpleFeature feature = iterator.next();
            Geometry geometry = (Geometry) feature.getDefaultGeometry();
            Geometry geometry2 = JTS.transform(geometry, transform);
            copy.add( SimpleFeatureBuilder.build( featureType, new Object[]{ geometry2 }, null) );
        }

    }
    catch (Exception e) {
        e.printStackTrace();
    }
    finally {
        iterator.close();
    }


  //Return new layer
    Style style = SLD.createLineStyle(Color.BLACK, 1);
    layer = new FeatureLayer(copy, style);
    layer.setTitle("Graticules");
    return layer;
}

আউটপুটটি সত্যই খারাপ:

প্রত্যাশা থেকে আউটপুট

সুতরাং, আমি অনুমান করি আমার কয়েকটি পৃথক প্রশ্ন রয়েছে:

  1. এটা কি সঠিক পন্থা? আমার কি সত্যিই স্তরে স্তরে পুনরায় প্রজেক্ট করা দরকার বা ম্যাপভিউপোর্টটি আমার জন্য এটি করার কথা?
  2. আমি কীভাবে একটি নির্দিষ্ট এওআইতে আউটপুট ক্লিপ করব? আমি ম্যাপভিউপোর্টপোর্ট.সেটবাউন্ডস (খাম) পদ্ধতিটি ব্যবহার করে সীমানা নির্ধারণ করার চেষ্টা করেছি তবে সেভ-ইমেজ পদ্ধতিটি সীমানাকে উপেক্ষা করে বলে মনে হচ্ছে।
  3. আর্কস হিসাবে রেন্ডার করতে আমি কীভাবে আমার অক্ষাংশ রেখা পেতে পারি? আমি কি অনুপস্থিত একটি রূপান্তর সেটিংস আছে?

আমি জিওটুলগুলি 8.7 ব্যবহার করছি।

উত্তর:


1

1) মানচিত্রটি আপনার জন্য প্রত্যাখ্যান পরিচালনা করবে। উদাহরণের জন্য কুইকস্টার্টটি দেখুন ।

2) আপনি মানচিত্রটিকে এটি সর্বাধিক সীমানার নয়, সর্বাধিক সীমাবদ্ধতার জন্য জিজ্ঞাসা করুন এবং অপ্রীতিকর অদ্ভুততা এড়াতে আপনি সিআরএসের ডোমেনঅফভিডালিটি দ্বারা ক্লিপ করতে চাইতে পারেন।

3) আমি নিশ্চিত না আপনি কীভাবে আপনার গ্রাফিকেলগুলি তৈরি করছেন তবে আপনি গ্রিড মডিউলটি ব্যবহার করলে আপনি লাইনগুলিকে আর্ক করে তোলার জন্য ঘনত্ব তৈরি করতে পারেন।

যদি আমি state.shp ব্যবহার করি তবে সম্পাদনা করুন (জিও সার্ভার থেকে) আমি এটি পাই:

এখানে চিত্র বর্ণনা লিখুন

কোডটি এখানে ব্যবহার করছি

শেষ সম্পাদনা

পরিশেষে প্রজেকশন হ্যান্ডলিংটি সম্প্রতি উন্নত করা হয়েছে যাতে আপনি জিওটুলস 12 বা 13 এ যেতে চান।

উদাহরণ মানচিত্র


2

আয়ানের উত্তর সঠিক, এবং আমি এটি হিসাবে চিহ্নিত করেছি। আগ্রহী হতে পারে অন্য কারও জন্য সম্পূর্ণতার জন্য ...


প্রশ্ন 1

না, আপনাকে ম্যানুয়ালি স্তরগুলি পুনরায় প্রজেক্ট করতে হবে না। ভিউপোর্টে প্রক্ষেপণ নির্দিষ্ট করা যথেষ্ট হবে। উদাহরণ:

    MapViewport vp = map.getViewport();
    CoordinateReferenceSystem crs = CRS.decode("EPSG:5070");
    vp.setCoordinateReferenceSystem(crs);

প্রশ্ন 2

অর্ডার মানচিত্র ক্লিপ জন্য, আপনাকে ভিউপোর্ট সীমা সেট করতে হবে এবং saveImage ফাংশন আপডেট করুন। প্রজেকশন এক্সটেন্টসগুলিতে সীমা নির্ধারণের জন্য এখানে একটি উদাহরণ রয়েছে:

    Extent crsExtent = crs.getDomainOfValidity();
    for (GeographicExtent element : crsExtent.getGeographicElements()) {
        if (element instanceof GeographicBoundingBox) {
            GeographicBoundingBox bounds = (GeographicBoundingBox) element;
            ReferencedEnvelope bbox = new ReferencedEnvelope(
                bounds.getSouthBoundLatitude(),
                bounds.getNorthBoundLatitude(),
                bounds.getWestBoundLongitude(),
                bounds.getEastBoundLongitude(),

                CRS.decode("EPSG:4326")
            );
            ReferencedEnvelope envelope = bbox.transform(crs, true);
            vp.setBounds(envelope);
        }
    }

ভিউপোর্টের সীমানা নির্ধারণের পাশাপাশি মানচিত্রের পরিবর্তে ভিউপোর্ট সীমানা ব্যবহার করার জন্য সেভ - ইমেজ ফাংশনটি পরিবর্তন করা উচিত get

পরিবর্তন:

mapBounds = map.getMaxBounds();

এটি:

mapBounds = map.getViewport().getBounds();

এখানে ফলাফল:

আমাদের


প্রশ্ন 3

আয়ানের পরামর্শের জন্য ধন্যবাদ, আমি রেখার স্ট্রিংটি ঘন করে অক্ষাংশ রেখাগুলি বক্ররেখায় পেতে সক্ষম হয়েছি। মূল পোস্টে রেফারেন্স প্রাপ্ত গ্রেটিকুলস () পদ্ধতি থেকে মূল স্নিপিট এখানে দেওয়া হয়েছে:

  //Add lines of latitude
    for (int y=-90; y<=90; y+=15){
        java.util.ArrayList<Coordinate> coords = new java.util.ArrayList<Coordinate>();
        for (double x=-135; x<=-45; x+=0.5){
            coords.add(new Coordinate(y,x,0));
        }
        LineString line = new LineString(coords.toArray(new Coordinate[coords.size()]), precisionModel, 4326);
        collection.add( SimpleFeatureBuilder.build( TYPE, new Object[]{ line }, null) );
    }

আউটপুট নিম্নরূপ:

প্রত্যাশা থেকে আউটপুট 2

যদিও এই পদ্ধতির কাজ করে, আমি একটি রূপান্তর সেটিং বা এমন কিছু আশা করছিলাম যা আমার জন্য লাইনগুলিকে চাপ দেয়।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.